#include #include #include #include #include #include GLuint program; GLuint vbo_vertices; GLuint vbo_pressure; GLuint ibo_elements; GLint attribute_coord2d; GLint attribute_pressure; GLfloat *point; int points; GLuint *triangle; int triangles; GLfloat *pressure; void read_VTK_pressure(const char *filename) { char line[80]; int i; FILE *f; f = fopen(filename, "r"); assert(f); while(fgets(line, 80, f)) { if (strstr(line, "POINTS")) { float dummy_y; points = atof(line+7); point = malloc(points*2*sizeof(float)); pressure = malloc(points*sizeof(float)); assert(point != NULL && pressure != NULL); for(i = 0; i < points; ++i) fscanf(f, "%f %f %f", &point[i*2], &dummy_y, &point[i*2+1]); } else if (strstr(line, "POLYGONS")) { triangles = atof(line+9); triangle = malloc(triangles*3*sizeof(GLuint)); for (i = 0; i < triangles; ++i) { int n; fscanf(f, "%d %d %d %d", &n, &triangle[i*3], &triangle[i*3+1], &triangle[i*3+2]); assert( n == 3 ); } } else if (strstr(line, "FIELD")) { fgets(line, 80, f); // skip: p 1 27582 float for (i = 0; i < points; ++i) fscanf(f, "%f", &pressure[i]); } } fclose(f); printf("Read %d points for %d triangles for field %s\n", points, triangles, filename); } static const GLchar * vertex_shader[] = { "attribute vec2 coord2d;" // input vertex position "attribute float pressure;" // custom variable along with vertex position "varying float t;" // communicate between the vertex and the fragment shader "void main()" "{" " t = (pressure+200.0)/400.0;" " vec2 moved = coord2d + vec2(-0.7, -0.7);" " gl_Position = gl_ModelViewProjectionMatrix*vec4(moved, 0.0, 1.0);" "}" }; static const GLchar * fragment_shader[] = { "vec3 Cool = vec3(0, 0, 1);" // Red "vec3 Hot = vec3(1, 0, 0);" // Blue "varying float t;" // Interpolated by fragment "void main()" "{" " vec3 color = mix(Cool, Hot, t);" // use the built-in mix() function " gl_FragColor = vec4(color, 1.0);" // append alpha channel "}" }; void active_vertex_shader_inputs(GLuint prog) { char *name; GLint active_attribs, max_length; unsigned i; glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &active_attribs); glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_length); name = malloc(max_length + 1); printf("Active vertex shader inputs:\n"); for (i = 0; i < active_attribs; i++) { GLint size; GLenum type; glGetActiveAttrib(prog, i, max_length + 1, NULL, &size, &type, name); printf("Vertex input attribute %s of type %d is at location %d\n", name, type, glGetAttribLocation(prog, name)); } free(name); } void create_shaders() { GLuint v, f; v = glCreateShader(GL_VERTEX_SHADER); f = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(v, 1, vertex_shader, NULL); glShaderSource(f, 1, fragment_shader, NULL); glCompileShader(v); GLint compiled; glGetShaderiv(v, GL_COMPILE_STATUS, &compiled ); if ( !compiled ) { GLsizei maxLength, length; glGetShaderiv( v, GL_INFO_LOG_LENGTH, &maxLength ); GLchar* log = malloc(sizeof(GLchar)*(maxLength+1)); glGetShaderInfoLog(v, maxLength, &length, log); printf("Vertex Shader compilation failed: %s\n", log); free(log); } glCompileShader(f); glGetShaderiv(f, GL_COMPILE_STATUS, &compiled ); if ( !compiled ) { GLsizei maxLength, length; glGetShaderiv( f, GL_INFO_LOG_LENGTH, &maxLength ); GLchar* log = malloc(sizeof(GLchar)*(maxLength+1)); glGetShaderInfoLog(f, maxLength, &length, log); printf("Fragment Shader compilation failed: %s\n", log); free(log); } program = glCreateProgram(); glAttachShader(program, f); glAttachShader(program, v); glLinkProgram(program); GLint linked; glGetProgramiv(program, GL_LINK_STATUS, &linked ); if ( !linked ) { GLsizei len; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len ); GLchar* log = malloc(sizeof(GLchar)*(len+1)); glGetProgramInfoLog(program, len, &len, log ); printf("Shader linking failed: %s\n", log); free(log); } glUseProgram(program); attribute_coord2d = glGetAttribLocation(program, "coord2d"); if (attribute_coord2d == -1) { fprintf(stderr, "Could not bind attribute coord2d\n"); } glEnableVertexAttribArray(attribute_coord2d); attribute_pressure = glGetAttribLocation(program, "pressure"); if (attribute_pressure == -1) { fprintf(stderr, "Could not bind attribute pressure\n"); } glEnableVertexAttribArray(attribute_pressure); // toggle this active_vertex_shader_inputs(program); } void send_buffers_to_GPU(void) { GLuint vertex_array_object; glGenVertexArrays(1, &vertex_array_object); glBindVertexArray(vertex_array_object); glGenBuffers(1, &vbo_vertices); glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices); glBufferData(GL_ARRAY_BUFFER, points*2*sizeof(GLfloat), point, GL_STATIC_DRAW); glGenBuffers(1, &vbo_pressure); glBindBuffer(GL_ARRAY_BUFFER, vbo_pressure); glBufferData(GL_ARRAY_BUFFER, points*sizeof(GLfloat), pressure, GL_STATIC_DRAW); glGenBuffers(1, &ibo_elements); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_elements); glBufferData(GL_ELEMENT_ARRAY_BUFFER, triangles*3*sizeof(GLuint), triangle, GL_STATIC_DRAW); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices); glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, NULL); glBindBuffer(GL_ARRAY_BUFFER, vbo_pressure); glVertexAttribPointer(attribute_pressure, 1, GL_FLOAT, GL_FALSE, 0, NULL); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_elements); glDrawElements(GL_TRIANGLES, triangles*3, GL_UNSIGNED_INT, 0); glutSwapBuffers(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutCreateWindow("GLSL Intro"); glutDisplayFunc(display); glewInit(); if (!glewIsSupported("GL_VERSION_2_0")) { printf("GLSL not supported\n"); exit(EXIT_FAILURE); } glClearColor(0.9,1.0,1.0,1.0); read_VTK_pressure("p_yNormal.vtk"); send_buffers_to_GPU(); // we don't need this anymore as it is in GPU by now free(point); free(triangle); free(pressure); create_shaders(); glutMainLoop(); return EXIT_SUCCESS; }