#include #include #include #include #include #include "../common/shader_utils.h" #include "res_texture.c" GLuint program; GLint attribute_coord2d; GLint uniform_offset_x; GLint uniform_scale_x; GLint uniform_sprite; GLuint texture_id; GLint uniform_mytexture; float offset_x = 0.0; float scale_x = 1.0; int mode = 0; struct point { GLfloat x; GLfloat y; }; GLuint vbo; int init_resources() { program = create_program("graph.v.glsl", "graph.f.glsl"); if (program == 0) return 0; attribute_coord2d = get_attrib(program, "coord2d"); uniform_offset_x = get_uniform(program, "offset_x"); uniform_scale_x = get_uniform(program, "scale_x"); uniform_sprite = get_uniform(program, "sprite"); uniform_mytexture = get_uniform(program, "mytexture"); if (attribute_coord2d == -1 || uniform_offset_x == -1 || uniform_scale_x == -1 || uniform_sprite == -1 || uniform_mytexture == -1) return 0; /* Enable blending */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* Enable point sprites (not necessary for true OpenGL ES 2.0) */ #ifndef GL_ES_VERSION_2_0 glEnable(GL_POINT_SPRITE); glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); #endif /* Upload the texture for our point sprites */ glActiveTexture(GL_TEXTURE0); glGenTextures(1, &texture_id); glBindTexture(GL_TEXTURE_2D, texture_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res_texture.width, res_texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, res_texture.pixel_data); // Create the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // Create our own temporary buffer point graph[2000]; // Fill it in just like an array for (int i = 0; i < 2000; i++) { float x = (i - 1000.0) / 100.0; graph[i].x = x; graph[i].y = sin(x * 10.0) / (1.0 + x * x); } // Tell OpenGL to copy our array to the buffer object glBufferData(GL_ARRAY_BUFFER, sizeof graph, graph, GL_STATIC_DRAW); return 1; } void display() { glUseProgram(program); glUniform1i(uniform_mytexture, 0); glUniform1f(uniform_offset_x, offset_x); glUniform1f(uniform_scale_x, scale_x); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); /* Draw using the vertices in our vertex buffer object */ glBindBuffer(GL_ARRAY_BUFFER, vbo); glEnableVertexAttribArray(attribute_coord2d); glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, 0); /* Push each element in buffer_vertices to the vertex shader */ switch (mode) { case 0: glUniform1f(uniform_sprite, 0); glDrawArrays(GL_LINE_STRIP, 0, 2000); break; case 1: glUniform1f(uniform_sprite, 1); glDrawArrays(GL_POINTS, 0, 2000); break; case 2: glUniform1f(uniform_sprite, res_texture.width); glDrawArrays(GL_POINTS, 0, 2000); break; } glutSwapBuffers(); } void special(int key, int x, int y) { switch (key) { case GLUT_KEY_F1: mode = 0; printf("Now drawing using lines.\n"); break; case GLUT_KEY_F2: mode = 1; printf("Now drawing using points.\n"); break; case GLUT_KEY_F3: mode = 2; printf("Now drawing using point sprites.\n"); break; case GLUT_KEY_LEFT: offset_x -= 0.1; break; case GLUT_KEY_RIGHT: offset_x += 0.1; break; case GLUT_KEY_UP: scale_x *= 1.5; break; case GLUT_KEY_DOWN: scale_x /= 1.5; break; case GLUT_KEY_HOME: offset_x = 0.0; scale_x = 1.0; break; } glutPostRedisplay(); } void free_resources() { glDeleteProgram(program); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB); glutInitWindowSize(640, 480); glutCreateWindow("My Graph"); GLenum glew_status = glewInit(); if (GLEW_OK != glew_status) { fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status)); return 1; } if (!GLEW_VERSION_2_0) { fprintf(stderr, "No support for OpenGL 2.0 found\n"); return 1; } GLfloat range[2]; glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, range); if (range[1] < res_texture.width) fprintf(stderr, "WARNING: point sprite range (%f, %f) too small\n", range[0], range[1]); printf("Use left/right to move horizontally.\n"); printf("Use up/down to change the horizontal scale.\n"); printf("Press home to reset the position and scale.\n"); printf("Press F1 to draw lines.\n"); printf("Press F2 to draw points.\n"); printf("Press F3 to draw point sprites.\n"); if (init_resources()) { glutDisplayFunc(display); glutSpecialFunc(special); glutMainLoop(); } free_resources(); return 0; }