Merge commit 'origin/gallium-master-merge'
[mesa.git] / progs / glsl / trirast.c
1 /**
2 * Demonstration of doing triangle rasterization with a fragment program.
3 * Basic idea:
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
6 * the triangle edges.
7 *
8 * Brian Paul
9 * 1 Aug 2007
10 */
11
12
13 #include <assert.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <math.h>
18 #include <GL/gl.h>
19 #include <GL/glut.h>
20 #include <GL/glext.h>
21 #include "extfuncs.h"
22 #include "shaderutil.h"
23
24
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;
31 static GLint win = 0;
32 static GLboolean anim = GL_TRUE;
33 static GLfloat Zrot = 0.0f;
34 static GLint uv0, uv1, uv2;
35
36
37 static const GLfloat TriVerts[3][2] = {
38 { 50, 50 },
39 { 250, 50 },
40 { 150, 250 }
41 };
42
43
44 static void
45 RotateVerts(GLfloat a,
46 GLuint n, const GLfloat vertsIn[][2], GLfloat vertsOut[][2])
47 {
48 GLuint i;
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;
53
54 vertsOut[i][0] = x * cos(a) + y * sin(a) + cx;
55 vertsOut[i][1] = -x * sin(a) + y * cos(a) + cy;
56 }
57 }
58
59 static void
60 ComputeBounds(GLuint n, GLfloat vertsIn[][2],
61 GLfloat *xmin, GLfloat *ymin,
62 GLfloat *xmax, GLfloat *ymax)
63 {
64 GLuint i;
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];
76 }
77 }
78
79
80 static void
81 Redisplay(void)
82 {
83 GLfloat v[3][2], xmin, ymin, xmax, ymax;
84
85 RotateVerts(Zrot, 3, TriVerts, v);
86 ComputeBounds(3, v, &xmin, &ymin, &xmax, &ymax);
87
88 glUniform2fv_func(uv0, 1, v[0]);
89 glUniform2fv_func(uv1, 1, v[1]);
90 glUniform2fv_func(uv2, 1, v[2]);
91
92 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
93
94 glPushMatrix();
95 glBegin(GL_POLYGON);
96 glVertex2f(xmin, ymin);
97 glVertex2f(xmax, ymin);
98 glVertex2f(xmax, ymax);
99 glVertex2f(xmin, ymax);
100 glEnd();
101 glPopMatrix();
102
103 glutSwapBuffers();
104 }
105
106
107 static void
108 Idle(void)
109 {
110 if (anim) {
111 Zrot = glutGet(GLUT_ELAPSED_TIME) * 0.0005;
112 glutPostRedisplay();
113 }
114 else
115 abort();
116 }
117
118
119 static void
120 Reshape(int width, int height)
121 {
122 glViewport(0, 0, width, height);
123 glMatrixMode(GL_PROJECTION);
124 glLoadIdentity();
125 glOrtho(0, width, 0, height, -1, 1);
126
127 glMatrixMode(GL_MODELVIEW);
128 glLoadIdentity();
129 }
130
131
132 static void
133 CleanUp(void)
134 {
135 glDeleteShader_func(fragShader);
136 glDeleteShader_func(vertShader);
137 glDeleteProgram_func(program);
138 glutDestroyWindow(win);
139 }
140
141
142 static void
143 Key(unsigned char key, int x, int y)
144 {
145 (void) x;
146 (void) y;
147
148 switch(key) {
149 case ' ':
150 case 'a':
151 anim = !anim;
152 if (anim)
153 glutIdleFunc(Idle);
154 else
155 glutIdleFunc(NULL);
156 break;
157 case 'z':
158 Zrot = 0;
159 break;
160 case 's':
161 Zrot += 0.05;
162 break;
163 case 27:
164 CleanUp();
165 exit(0);
166 break;
167 }
168 glutPostRedisplay();
169 }
170
171
172 static void
173 Init(void)
174 {
175 static const char *fragShaderText =
176 "uniform vec2 v0, v1, v2; \n"
177 "float crs(const vec2 u, const vec2 v) \n"
178 "{ \n"
179 " return u.x * v.y - u.y * v.x; \n"
180 "} \n"
181 "\n"
182 "void main() {\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"
188 " else \n"
189 " gl_FragColor = vec4(0.5); \n"
190 "}\n";
191 static const char *vertShaderText =
192 "void main() {\n"
193 " gl_Position = ftransform(); \n"
194 "}\n";
195
196 if (!ShadersSupported())
197 exit(1);
198
199 GetExtensionFuncs();
200
201 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
202 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
203 program = LinkShaders(vertShader, fragShader);
204
205 glUseProgram_func(program);
206
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);
211
212 /*assert(glGetError() == 0);*/
213
214 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
215 glEnable(GL_DEPTH_TEST);
216
217 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
218
219 assert(glIsProgram_func(program));
220 assert(glIsShader_func(fragShader));
221 assert(glIsShader_func(vertShader));
222
223 glColor3f(1, 0, 0);
224 }
225
226
227 static void
228 ParseOptions(int argc, char *argv[])
229 {
230 int i;
231 for (i = 1; i < argc; i++) {
232 if (strcmp(argv[i], "-fs") == 0) {
233 FragProgFile = argv[i+1];
234 }
235 else if (strcmp(argv[i], "-vs") == 0) {
236 VertProgFile = argv[i+1];
237 }
238 }
239 }
240
241
242 int
243 main(int argc, char *argv[])
244 {
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);
253 if (anim)
254 glutIdleFunc(Idle);
255 ParseOptions(argc, argv);
256 Init();
257 glutMainLoop();
258 return 0;
259 }