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
22 #include "shaderutil.h"
25 static GLint WinWidth
= 300, WinHeight
= 300;
26 static char *FragProgFile
= NULL
;
27 static char *VertProgFile
= NULL
;
28 static GLuint fragShader
;
29 static GLuint vertShader
;
30 static GLuint program
;
32 static GLboolean anim
= GL_TRUE
;
33 static GLfloat Zrot
= 0.0f
;
34 static GLint uv0
, uv1
, uv2
;
37 static const GLfloat TriVerts
[3][2] = {
45 RotateVerts(GLfloat a
,
46 GLuint n
, const GLfloat vertsIn
[][2], GLfloat vertsOut
[][2])
49 GLfloat cx
= WinWidth
/ 2, cy
= WinHeight
/ 2;
50 for (i
= 0; i
< n
; i
++) {
51 float x
= vertsIn
[i
][0] - cx
;
52 float y
= vertsIn
[i
][1] - cy
;
54 vertsOut
[i
][0] = x
* cos(a
) + y
* sin(a
) + cx
;
55 vertsOut
[i
][1] = -x
* sin(a
) + y
* cos(a
) + cy
;
60 ComputeBounds(GLuint n
, GLfloat vertsIn
[][2],
61 GLfloat
*xmin
, GLfloat
*ymin
,
62 GLfloat
*xmax
, GLfloat
*ymax
)
65 *xmin
= *xmax
= vertsIn
[0][0];
66 *ymin
= *ymax
= vertsIn
[0][1];
67 for (i
= 1; i
< n
; i
++) {
68 if (vertsIn
[i
][0] < *xmin
)
69 *xmin
= vertsIn
[i
][0];
70 else if (vertsIn
[i
][0] > *xmax
)
71 *xmax
= vertsIn
[i
][0];
72 if (vertsIn
[i
][1] < *ymin
)
73 *ymin
= vertsIn
[i
][1];
74 else if (vertsIn
[i
][1] > *ymax
)
75 *ymax
= vertsIn
[i
][1];
83 GLfloat v
[3][2], xmin
, ymin
, xmax
, ymax
;
85 RotateVerts(Zrot
, 3, TriVerts
, v
);
86 ComputeBounds(3, v
, &xmin
, &ymin
, &xmax
, &ymax
);
88 glUniform2fv_func(uv0
, 1, v
[0]);
89 glUniform2fv_func(uv1
, 1, v
[1]);
90 glUniform2fv_func(uv2
, 1, v
[2]);
92 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
96 glVertex2f(xmin
, ymin
);
97 glVertex2f(xmax
, ymin
);
98 glVertex2f(xmax
, ymax
);
99 glVertex2f(xmin
, ymax
);
111 Zrot
= glutGet(GLUT_ELAPSED_TIME
) * 0.0005;
120 Reshape(int width
, int height
)
122 glViewport(0, 0, width
, height
);
123 glMatrixMode(GL_PROJECTION
);
125 glOrtho(0, width
, 0, height
, -1, 1);
127 glMatrixMode(GL_MODELVIEW
);
135 glDeleteShader_func(fragShader
);
136 glDeleteShader_func(vertShader
);
137 glDeleteProgram_func(program
);
138 glutDestroyWindow(win
);
143 Key(unsigned char key
, int x
, int y
)
175 static const char *fragShaderText
=
176 "uniform vec2 v0, v1, v2; \n"
177 "float crs(const vec2 u, const vec2 v) \n"
179 " return u.x * v.y - u.y * v.x; \n"
183 " vec2 p = gl_FragCoord.xy; \n"
184 " if (crs(v1 - v0, p - v0) >= 0 && \n"
185 " crs(v2 - v1, p - v1) >= 0 && \n"
186 " crs(v0 - v2, p - v2) >= 0) \n"
187 " gl_FragColor = vec4(1.0); \n"
189 " gl_FragColor = vec4(0.5); \n"
191 static const char *vertShaderText
=
193 " gl_Position = ftransform(); \n"
196 if (!ShadersSupported())
201 vertShader
= CompileShaderText(GL_VERTEX_SHADER
, vertShaderText
);
202 fragShader
= CompileShaderText(GL_FRAGMENT_SHADER
, fragShaderText
);
203 program
= LinkShaders(vertShader
, fragShader
);
205 glUseProgram_func(program
);
207 uv0
= glGetUniformLocation_func(program
, "v0");
208 uv1
= glGetUniformLocation_func(program
, "v1");
209 uv2
= glGetUniformLocation_func(program
, "v2");
210 printf("Uniforms: %d %d %d\n", uv0
, uv1
, uv2
);
212 /*assert(glGetError() == 0);*/
214 glClearColor(0.3f
, 0.3f
, 0.3f
, 0.0f
);
215 glEnable(GL_DEPTH_TEST
);
217 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER
));
219 assert(glIsProgram_func(program
));
220 assert(glIsShader_func(fragShader
));
221 assert(glIsShader_func(vertShader
));
228 ParseOptions(int argc
, char *argv
[])
231 for (i
= 1; i
< argc
; i
++) {
232 if (strcmp(argv
[i
], "-fs") == 0) {
233 FragProgFile
= argv
[i
+1];
235 else if (strcmp(argv
[i
], "-vs") == 0) {
236 VertProgFile
= argv
[i
+1];
243 main(int argc
, char *argv
[])
245 glutInit(&argc
, argv
);
246 glutInitWindowPosition( 0, 0);
247 glutInitWindowSize(WinWidth
, WinHeight
);
248 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
249 win
= glutCreateWindow(argv
[0]);
250 glutReshapeFunc(Reshape
);
251 glutKeyboardFunc(Key
);
252 glutDisplayFunc(Redisplay
);
255 ParseOptions(argc
, argv
);