2 * Demonstration of doing triangle rasterization with a fragment program.
4 * 1. Draw screen-aligned quad / bounding box around the triangle verts.
5 * 2. For each pixel in the quad, determine if pixel is inside/outside
24 static GLint WinWidth
= 300, WinHeight
= 300;
25 static char *FragProgFile
= NULL
;
26 static char *VertProgFile
= NULL
;
27 static GLuint fragShader
;
28 static GLuint vertShader
;
29 static GLuint program
;
31 static GLboolean anim
= GL_TRUE
;
32 static GLfloat Zrot
= 0.0f
;
33 static GLint uv0
, uv1
, uv2
;
36 static const GLfloat TriVerts
[3][2] = {
44 RotateVerts(GLfloat a
,
45 GLuint n
, const GLfloat vertsIn
[][2], GLfloat vertsOut
[][2])
48 GLfloat cx
= WinWidth
/ 2, cy
= WinHeight
/ 2;
49 for (i
= 0; i
< n
; i
++) {
50 float x
= vertsIn
[i
][0] - cx
;
51 float y
= vertsIn
[i
][1] - cy
;
53 vertsOut
[i
][0] = x
* cos(a
) + y
* sin(a
) + cx
;
54 vertsOut
[i
][1] = -x
* sin(a
) + y
* cos(a
) + cy
;
59 ComputeBounds(GLuint n
, GLfloat vertsIn
[][2],
60 GLfloat
*xmin
, GLfloat
*ymin
,
61 GLfloat
*xmax
, GLfloat
*ymax
)
64 *xmin
= *xmax
= vertsIn
[0][0];
65 *ymin
= *ymax
= vertsIn
[0][1];
66 for (i
= 1; i
< n
; i
++) {
67 if (vertsIn
[i
][0] < *xmin
)
68 *xmin
= vertsIn
[i
][0];
69 else if (vertsIn
[i
][0] > *xmax
)
70 *xmax
= vertsIn
[i
][0];
71 if (vertsIn
[i
][1] < *ymin
)
72 *ymin
= vertsIn
[i
][1];
73 else if (vertsIn
[i
][1] > *ymax
)
74 *ymax
= vertsIn
[i
][1];
82 GLfloat v
[3][2], xmin
, ymin
, xmax
, ymax
;
84 RotateVerts(Zrot
, 3, TriVerts
, v
);
85 ComputeBounds(3, v
, &xmin
, &ymin
, &xmax
, &ymax
);
87 glUniform2fv_func(uv0
, 1, v
[0]);
88 glUniform2fv_func(uv1
, 1, v
[1]);
89 glUniform2fv_func(uv2
, 1, v
[2]);
91 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
95 glVertex2f(xmin
, ymin
);
96 glVertex2f(xmax
, ymin
);
97 glVertex2f(xmax
, ymax
);
98 glVertex2f(xmin
, ymax
);
110 Zrot
= glutGet(GLUT_ELAPSED_TIME
) * 0.0005;
119 Reshape(int width
, int height
)
121 glViewport(0, 0, width
, height
);
122 glMatrixMode(GL_PROJECTION
);
124 glOrtho(0, width
, 0, height
, -1, 1);
126 glMatrixMode(GL_MODELVIEW
);
134 glDeleteShader_func(fragShader
);
135 glDeleteShader_func(vertShader
);
136 glDeleteProgram_func(program
);
137 glutDestroyWindow(win
);
142 Key(unsigned char key
, int x
, int y
)
172 LoadAndCompileShader(GLuint shader
, const char *text
)
176 glShaderSource_func(shader
, 1, (const GLchar
**) &text
, NULL
);
178 glCompileShader_func(shader
);
180 glGetShaderiv_func(shader
, GL_COMPILE_STATUS
, &stat
);
184 glGetShaderInfoLog_func(shader
, 1000, &len
, log
);
185 fprintf(stderr
, "fslight: problem compiling shader:\n%s\n", log
);
192 * Read a shader from a file.
195 ReadShader(GLuint shader
, const char *filename
)
197 const int max
= 100*1000;
199 char *buffer
= (char*) malloc(max
);
200 FILE *f
= fopen(filename
, "r");
202 fprintf(stderr
, "fslight: Unable to open shader file %s\n", filename
);
206 n
= fread(buffer
, 1, max
, f
);
207 printf("fslight: read %d bytes from shader file %s\n", n
, filename
);
210 LoadAndCompileShader(shader
, buffer
);
219 CheckLink(GLuint prog
)
222 glGetProgramiv_func(prog
, GL_LINK_STATUS
, &stat
);
226 glGetProgramInfoLog_func(prog
, 1000, &len
, log
);
227 fprintf(stderr
, "Linker error:\n%s\n", log
);
235 static const char *fragShaderText
=
236 "uniform vec2 v0, v1, v2; \n"
237 "float crs(const vec2 u, const vec2 v) \n"
239 " return u.x * v.y - u.y * v.x; \n"
243 " vec2 p = gl_FragCoord.xy; \n"
244 " if (crs(v1 - v0, p - v0) >= 0 && \n"
245 " crs(v2 - v1, p - v1) >= 0 && \n"
246 " crs(v0 - v2, p - v2) >= 0) \n"
247 " gl_FragColor = vec4(1.0); \n"
249 " gl_FragColor = vec4(0.5); \n"
251 static const char *vertShaderText
=
253 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
257 version
= (const char *) glGetString(GL_VERSION
);
258 if (version
[0] != '2' || version
[1] != '.') {
259 printf("This program requires OpenGL 2.x, found %s\n", version
);
265 fragShader
= glCreateShader_func(GL_FRAGMENT_SHADER
);
267 ReadShader(fragShader
, FragProgFile
);
269 LoadAndCompileShader(fragShader
, fragShaderText
);
271 vertShader
= glCreateShader_func(GL_VERTEX_SHADER
);
273 ReadShader(vertShader
, VertProgFile
);
275 LoadAndCompileShader(vertShader
, vertShaderText
);
277 program
= glCreateProgram_func();
278 glAttachShader_func(program
, fragShader
);
279 glAttachShader_func(program
, vertShader
);
280 glLinkProgram_func(program
);
282 glUseProgram_func(program
);
284 uv0
= glGetUniformLocation_func(program
, "v0");
285 uv1
= glGetUniformLocation_func(program
, "v1");
286 uv2
= glGetUniformLocation_func(program
, "v2");
287 printf("Uniforms: %d %d %d\n", uv0
, uv1
, uv2
);
289 /*assert(glGetError() == 0);*/
291 glClearColor(0.3f
, 0.3f
, 0.3f
, 0.0f
);
292 glEnable(GL_DEPTH_TEST
);
294 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER
));
296 assert(glIsProgram_func(program
));
297 assert(glIsShader_func(fragShader
));
298 assert(glIsShader_func(vertShader
));
305 ParseOptions(int argc
, char *argv
[])
308 for (i
= 1; i
< argc
; i
++) {
309 if (strcmp(argv
[i
], "-fs") == 0) {
310 FragProgFile
= argv
[i
+1];
312 else if (strcmp(argv
[i
], "-vs") == 0) {
313 VertProgFile
= argv
[i
+1];
320 main(int argc
, char *argv
[])
322 glutInit(&argc
, argv
);
323 glutInitWindowPosition( 0, 0);
324 glutInitWindowSize(WinWidth
, WinHeight
);
325 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
326 win
= glutCreateWindow(argv
[0]);
327 glutReshapeFunc(Reshape
);
328 glutKeyboardFunc(Key
);
329 glutDisplayFunc(Redisplay
);
332 ParseOptions(argc
, argv
);