/** * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/OpenGL_Programming * This file is in the public domain. * Contributors: Sylvain Beucler */ #include #include /* Use glew.h instead of gl.h to get all the GL prototypes declared */ #include /* Using the GLUT library for the base windowing setup */ #include #define GLM_FORCE_RADIANS #include #include #include GLuint program; GLint attribute_coord2d; GLint uniform_mvp; int init_resources() { GLint compile_ok = GL_FALSE, link_ok = GL_FALSE; GLuint vs = glCreateShader(GL_VERTEX_SHADER); const char *vs_source = #ifdef GL_ES_VERSION_2_0 "#version 100\n" // OpenGL ES 2.0 #else "#version 120\n" // OpenGL 2.1 #endif "attribute vec2 coord2d; " "uniform mat4 mvp;" "void main(void) { " " gl_Position = mvp * vec4(coord2d.x, coord2d.y/2, 0.0, 1.0); " "}"; glShaderSource(vs, 1, &vs_source, NULL); glCompileShader(vs); glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok); if (!compile_ok) { fprintf(stderr, "Error in vertex shader\n"); return 0; } GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); const char *fs_source = #ifdef GL_ES_VERSION_2_0 "#version 100\n" // OpenGL ES 2.0 #else "#version 120\n" // OpenGL 2.1 #endif "void main(void) { " " gl_FragColor[0] = 0.0; " " gl_FragColor[1] = 1000 - gl_FragCoord.x / 1000; " " gl_FragColor[2] = gl_FragCoord.x / 1000; " "}"; glShaderSource(fs, 1, &fs_source, NULL); glCompileShader(fs); glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_ok); if (!compile_ok) { fprintf(stderr, "Error in fragment shader\n"); return 0; } program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &link_ok); if (!link_ok) { fprintf(stderr, "glLinkProgram:"); return 0; } const char* attribute_name = "coord2d"; attribute_coord2d = glGetAttribLocation(program, attribute_name); if (attribute_coord2d == -1) { fprintf(stderr, "Could not bind attribute %s\n", attribute_name); return 0; } const char* uniform_name; uniform_name = "mvp"; uniform_mvp = glGetUniformLocation(program, uniform_name); if (uniform_mvp == -1) { fprintf(stderr, "Could not bind uniform %s\n", uniform_name); return 0; } return 1; } void onDisplay() { float angle = glutGet(GLUT_ELAPSED_TIME) / 1000.0 * 45; // 45° per second glm::vec3 axis_y(0, 1, 0); glm::mat4 anim = glm::rotate(glm::mat4(1.0f), glm::radians(angle), axis_y); glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0, 0.0, -4.0)); glm::mat4 view = glm::lookAt(glm::vec3(0.0, 2.0, 0.0), glm::vec3(0.0, 0.0, -4.0), glm::vec3(0.0, 1.0, 0.0)); glm::mat4 projection = glm::perspective(45.0f, 1.0f*640.0f/480.0f, 0.1f, 10.0f); glm::mat4 mvp = projection * view * model * anim; glUseProgram(program); /* Push each element in buffer_vertices to the vertex shader */ glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(mvp)); glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glEnableVertexAttribArray(attribute_coord2d); GLfloat triangle_vertices[] = { 0.0, 0.8, -0.8, -0.8, 0.8, -0.8, }; /* Describe our vertices array to OpenGL (it can't guess its format automatically) */ glVertexAttribPointer( attribute_coord2d, // attribute 2, // number of elements per vertex, here (x,y) GL_FLOAT, // the type of each element GL_FALSE, // take our values as-is 0, // no extra data between each position triangle_vertices // pointer to the C array ); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableVertexAttribArray(attribute_coord2d); glutSwapBuffers(); } void free_resources() { glDeleteProgram(program); } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitContextVersion(2,0); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowSize(640, 480); glutCreateWindow("My First Triangle"); GLenum glew_status = glewInit(); if (glew_status != GLEW_OK) { fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status)); return 1; } if (init_resources()) { glutDisplayFunc(onDisplay); glutIdleFunc(onDisplay); glutMainLoop(); } free_resources(); return 0; }