1 | #include <stdio.h> |
---|
2 | #include <stdlib.h> |
---|
3 | #include <GL/glew.h> |
---|
4 | #include <GL/glut.h> |
---|
5 | |
---|
6 | GLuint program; |
---|
7 | GLuint vbo_vertices; |
---|
8 | GLUINT vbo_temperature; |
---|
9 | GLint attribute_coord2d; |
---|
10 | GLint attribute_temperature; |
---|
11 | |
---|
12 | static const GLchar * vertex_shader[] = { |
---|
13 | "attribute vec2 coord2d;" // input vertex position |
---|
14 | "attribute float temperature;" // custom variable along with vertex position |
---|
15 | "varying float t;" // communicate between the vertex and the fragment shader |
---|
16 | "void main()" |
---|
17 | "{" |
---|
18 | " t = temperature;" |
---|
19 | " gl_Position = gl_ModelViewProjectionMatrix*vec4(coord2d, 0.0, 1.0);" |
---|
20 | "}" |
---|
21 | }; |
---|
22 | static const GLchar * fragment_shader[] = { |
---|
23 | "vec3 Cool = vec3(0, 0, 1);" // Red |
---|
24 | "vec3 Hot = vec3(1, 0, 0);" // Blue |
---|
25 | "varying float t;" // Interpolated by fragment |
---|
26 | "void main()" |
---|
27 | "{" |
---|
28 | " vec3 color = mix(Cool, Hot, t);" // use the built-in mix() function |
---|
29 | " gl_FragColor = vec4(color, 1.0);" // append alpha channel |
---|
30 | "}" |
---|
31 | }; |
---|
32 | |
---|
33 | void active_vertex_shader_inputs(GLuint prog) |
---|
34 | { |
---|
35 | char *name; |
---|
36 | GLint active_attribs, max_length; |
---|
37 | unsigned i; |
---|
38 | |
---|
39 | glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &active_attribs); |
---|
40 | glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_length); |
---|
41 | |
---|
42 | name = malloc(max_length + 1); |
---|
43 | printf("Active vertex shader inputs:\n"); |
---|
44 | for (i = 0; i < active_attribs; i++) { |
---|
45 | GLint size; |
---|
46 | GLenum type; |
---|
47 | |
---|
48 | glGetActiveAttrib(prog, i, max_length + 1, NULL, |
---|
49 | &size, &type, name); |
---|
50 | printf("Vertex input attribute %s of type %d is at location %d\n", |
---|
51 | name, type, glGetAttribLocation(prog, name)); |
---|
52 | } |
---|
53 | free(name); |
---|
54 | } |
---|
55 | |
---|
56 | void create_shaders() |
---|
57 | { |
---|
58 | GLuint v, f; |
---|
59 | |
---|
60 | v = glCreateShader(GL_VERTEX_SHADER); |
---|
61 | f = glCreateShader(GL_FRAGMENT_SHADER); |
---|
62 | glShaderSource(v, 1, vertex_shader, NULL); |
---|
63 | glShaderSource(f, 1, fragment_shader, NULL); |
---|
64 | glCompileShader(v); |
---|
65 | GLint compiled; |
---|
66 | glGetShaderiv(v, GL_COMPILE_STATUS, &compiled ); |
---|
67 | if ( !compiled ) { |
---|
68 | GLsizei maxLength, length; |
---|
69 | glGetShaderiv( v, GL_INFO_LOG_LENGTH, &maxLength ); |
---|
70 | GLchar* log = malloc(sizeof(GLchar)*(maxLength+1)); |
---|
71 | glGetShaderInfoLog(v, maxLength, &length, log); |
---|
72 | printf("Vertex Shader compilation failed: %s\n", log); |
---|
73 | free(log); |
---|
74 | } |
---|
75 | glCompileShader(f); |
---|
76 | glGetShaderiv(f, GL_COMPILE_STATUS, &compiled ); |
---|
77 | if ( !compiled ) { |
---|
78 | GLsizei maxLength, length; |
---|
79 | glGetShaderiv( f, GL_INFO_LOG_LENGTH, &maxLength ); |
---|
80 | GLchar* log = malloc(sizeof(GLchar)*(maxLength+1)); |
---|
81 | glGetShaderInfoLog(f, maxLength, &length, log); |
---|
82 | printf("Fragment Shader compilation failed: %s\n", log); |
---|
83 | free(log); |
---|
84 | } |
---|
85 | program = glCreateProgram(); |
---|
86 | glAttachShader(program, f); |
---|
87 | glAttachShader(program, v); |
---|
88 | glLinkProgram(program); |
---|
89 | GLint linked; |
---|
90 | glGetProgramiv(program, GL_LINK_STATUS, &linked ); |
---|
91 | if ( !linked ) { |
---|
92 | GLsizei len; |
---|
93 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len ); |
---|
94 | GLchar* log = malloc(sizeof(GLchar)*(len+1)); |
---|
95 | glGetProgramInfoLog(program, len, &len, log ); |
---|
96 | printf("Shader linking failed: %s\n", log); |
---|
97 | free(log); |
---|
98 | } |
---|
99 | glUseProgram(program); |
---|
100 | |
---|
101 | |
---|
102 | attribute_coord2d = glGetAttribLocation(program, "coord2d"); |
---|
103 | if (attribute_coord2d == -1) { |
---|
104 | fprintf(stderr, "Could not bind attribute coord2d\n"); |
---|
105 | } |
---|
106 | glEnableVertexAttribArray(attribute_coord2d); |
---|
107 | |
---|
108 | attribute_temperature = glGetAttribLocation(program, "temperature"); |
---|
109 | if (attribute_temperature == -1) { |
---|
110 | fprintf(stderr, "Could not bind attribute temperature\n"); |
---|
111 | } |
---|
112 | glEnableVertexAttribArray(attribute_temperature); // toggle this |
---|
113 | active_vertex_shader_inputs(program); |
---|
114 | |
---|
115 | } |
---|
116 | |
---|
117 | void send_buffers_to_GPU(void) |
---|
118 | { |
---|
119 | GLuint vertex_array_object; |
---|
120 | glGenVertexArrays(1, &vertex_array_object); |
---|
121 | glBindVertexArray(vertex_array_object); |
---|
122 | |
---|
123 | GLfloat vertices[][2] = { |
---|
124 | { -0.90, -0.90 }, // Triangle 1 |
---|
125 | { 0.85, -0.90 }, |
---|
126 | { -0.90, 0.85 }, |
---|
127 | { 0.90, -0.85 }, // Triangle 2 |
---|
128 | { 0.90, 0.90 }, |
---|
129 | { -0.85, 0.90 } |
---|
130 | }; |
---|
131 | |
---|
132 | glGenBuffers(1, &vbo_vertices); |
---|
133 | glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices); |
---|
134 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); |
---|
135 | |
---|
136 | GLfloat vertex_temperature[] = {0, 1, 0.2, 0.1, 0.5, 0.9}; |
---|
137 | glGenBuffers(1, &vbo_temperature); |
---|
138 | glBindBuffer(GL_ARRAY_BUFFER, vbo_temperature); |
---|
139 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_temperature), |
---|
140 | vertex_temperature, GL_STATIC_DRAW); |
---|
141 | } |
---|
142 | |
---|
143 | |
---|
144 | void display(void) |
---|
145 | { |
---|
146 | glClear(GL_COLOR_BUFFER_BIT); |
---|
147 | |
---|
148 | glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices); |
---|
149 | glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, NULL); |
---|
150 | |
---|
151 | glBindBuffer(GL_ARRAY_BUFFER, vbo_temperature); |
---|
152 | glVertexAttribPointer(attribute_temperature, 1, GL_FLOAT, GL_FALSE, 0, NULL); |
---|
153 | |
---|
154 | glDrawArrays(GL_TRIANGLES, 0, 6); // Draw 6 vertices |
---|
155 | glutSwapBuffers(); |
---|
156 | } |
---|
157 | |
---|
158 | int main(int argc, char **argv) |
---|
159 | { |
---|
160 | glutInit(&argc, argv); |
---|
161 | glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); |
---|
162 | glutCreateWindow("GLSL Intro"); |
---|
163 | glutDisplayFunc(display); |
---|
164 | glewInit(); |
---|
165 | if (!glewIsSupported("GL_VERSION_2_0")) |
---|
166 | { |
---|
167 | printf("GLSL not supported\n"); |
---|
168 | exit(EXIT_FAILURE); |
---|
169 | } |
---|
170 | glClearColor(0.9,1.0,1.0,1.0); |
---|
171 | send_buffers_to_GPU(); |
---|
172 | create_shaders(); |
---|
173 | |
---|
174 | glutMainLoop(); |
---|
175 | return EXIT_SUCCESS; |
---|
176 | } |
---|