namespace shader { std::string vFlat = "#version 150" "\n" "uniform mat4 transform, camera, projection;" "\n" "in vec3 position, normal;" "\n" "in vec2 uv;" "\n" "out mat4 modelview;" "\n" "out vec3 frag_position, frag_normal;" "\n" "out vec2 frag_uv;" "\n" "void main() {" "\n" "modelview = camera * transform;" "\n" "vec4 eye_position = modelview * vec4(position, 1.0);" "\n" "gl_Position = projection * eye_position;" "\n" "frag_position = eye_position.xyz;" "\n" "frag_normal = (modelview * vec4(normal, 0.0)).xyz;" "\n" "frag_uv = uv;" "\n" "}"; std::string fFlat = "#version 150" "\n" "in mat4 modelview;" "\n" "in vec3 frag_position, frag_normal;" "\n" "in vec2 frag_uv;" "\n" "uniform vec4 color;" "\n" "const vec3 light_direction = vec3(0.408248, -0.816497, -0.408248);" "\n" "out vec4 fragColor;" "\n" "void main() {" "\n" "vec3 normal = normalize(frag_normal);" "\n" "float shade = 0.5 * (-dot(normal, normalize(light_direction)) + 1.0);" "\n" "fragColor = vec4(color.rgb * shade, color.a);" "\n" "}"; } namespace gl { struct Vertex { glm::vec3 position; glm::vec3 normal; glm::vec2 uv; }; class Object { public: glm::vec4 color; GLuint data; vector faces; GLuint program; mat4 transform; }; } class OBJMesh { public: OBJMesh(string const& filename); vector verts; vector faces; vector segments; } gl::Object* cube = NULL; void load() { // assumes context is created : no errors up to this point GLuint v = glCreateShader(GL_VERTEX_SHADER), f = glCreateShader(GL_FRAGMENT_SHADER); GLint length = static_cast(shader::vFlat.length()); char const* text = shader::vFlat.c_str(); glShaderSource(v, 1, &text, &length); glCompileShader(v); GLint status = GL_FALSE; glGetShaderiv(v, GL_COMPILE_STATUS, &status); length = static_cast(shader::fFlat.length()); text = shader::fFlat.c_str(); glShaderSource(f, 1, &text, &length); glCompileShader(f); glGetShaderiv(f, GL_COMPILE_STATUS, &status); plain = glCreateProgram(); glAttachShader(plain, v); glAttachShader(plain, f); glBindAttribLocation(plain, 0, "position"); glBindAttribLocation(plain, 1, "normal"); glBindAttribLocation(plain, 2, "uv"); glLinkProgram(plain); glGetProgramiv(plain, GL_LINK_STATUS, &status); glDetachShader(plain, v); glDetachShader(plain, f); glUseProgram(plain); glUniformMatrix4fv(glGetUniformLocation(plain, "camera"), 1, GL_FALSE, glm::value_ptr(glm::lookAt(vec3(0.0f, 2.0f, 4.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)))); glUniformMatrix4fv(glGetUniformLocation(plain, "projection"), 1, GL_FALSE, glm::value_ptr(glm::frustum(-2.0f, 2.0f, -1.5f, 1.5f, 02.0f, -5.0f))); glUniformMatrix4fv(glGetUniformLocation(plain, "transform"), 1, GL_FALSE, glm::value_ptr(glm::mat4())); cube = new gl::Object(); glGenVertexArrays(1, &cube->data); cube->program = plain; cube->color = glm::vec4(1.0f); cube->transform = glm::mat4(); OBJMesh cubeMesh("cube.obj"); // confirmed working GLuint vbo, ebo; glGenBuffers(1, &vbo); glGenBuffers(1, &ebo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(gl::Vertex) * cubeMesh.verts.size(), cubeMesh.verts.data(), GL_STATIC_DRAW); glBindVertexArray(cube->data); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(gl::Vertex), reinterpret_cast(0)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(gl::Vertex), reinterpret_cast(sizeof(glm::vec3))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(gl::Vertex), reinterpret_cast(sizeof(glm::vec3)+sizeof(glm::vec3))); glBindVertexArray(0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); glBindVertexArray(cube->data); // because of C++ wrapper class in original code glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * cubeMesh.faces.size(), cubeMesh.faces.data(), GL_STATIC_DRAW); glBindVertexArray(0); glDeleteBuffers(1, &ebo); glDeleteBuffers(1, &vbo); cube->faces = cubeMesh.segments(); } void render() { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glUseProgram(cube->program); glUniform4fv(glGetUniformLocation(cube->program, "color"), 1, glm::value_ptr(cube->color)); glUniformMatrix4fv(glGetUniformLocation(cube->program, "transform"), 1, GL_FALSE, glm::value_ptr(cube->transform)); glBindVertexArray(cube->data); GLushort position = 0; for (GLushort range: faces) { // THIS glDrawElements LINE YIELDS GL_OUT_OF_MEMORY ON THE FIRST CALL!!!!! glDrawElements(GL_TRIANGLE_STRIP, range, GL_UNSIGNED_SHORT, reinterpret_cast(position * sizeof(GLushort))); position += range; } glBindVertexArray(0); }