blob: 3d4decaa2fb0d785a6004ee82823afc55184f43d [file] [log] [blame]
Brian261eac32007-08-01 11:13:25 -06001/**
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>
Keith Whitwellb799af92009-06-29 14:13:58 +010018#include <GL/glew.h>
Brian261eac32007-08-01 11:13:25 -060019#include <GL/gl.h>
20#include <GL/glut.h>
21#include <GL/glext.h>
22#include "extfuncs.h"
Brian2dca3372008-04-09 22:28:23 -060023#include "shaderutil.h"
Brian261eac32007-08-01 11:13:25 -060024
25
26static GLint WinWidth = 300, WinHeight = 300;
27static char *FragProgFile = NULL;
28static char *VertProgFile = NULL;
29static GLuint fragShader;
30static GLuint vertShader;
31static GLuint program;
32static GLint win = 0;
33static GLboolean anim = GL_TRUE;
34static GLfloat Zrot = 0.0f;
35static GLint uv0, uv1, uv2;
36
37
38static const GLfloat TriVerts[3][2] = {
39 { 50, 50 },
40 { 250, 50 },
41 { 150, 250 }
42};
43
44
45static void
46RotateVerts(GLfloat a,
47 GLuint n, const GLfloat vertsIn[][2], GLfloat vertsOut[][2])
48{
49 GLuint i;
50 GLfloat cx = WinWidth / 2, cy = WinHeight / 2;
51 for (i = 0; i < n; i++) {
52 float x = vertsIn[i][0] - cx;
53 float y = vertsIn[i][1] - cy;
54
55 vertsOut[i][0] = x * cos(a) + y * sin(a) + cx;
56 vertsOut[i][1] = -x * sin(a) + y * cos(a) + cy;
57 }
58}
59
60static void
61ComputeBounds(GLuint n, GLfloat vertsIn[][2],
62 GLfloat *xmin, GLfloat *ymin,
63 GLfloat *xmax, GLfloat *ymax)
64{
65 GLuint i;
66 *xmin = *xmax = vertsIn[0][0];
67 *ymin = *ymax = vertsIn[0][1];
68 for (i = 1; i < n; i++) {
69 if (vertsIn[i][0] < *xmin)
70 *xmin = vertsIn[i][0];
71 else if (vertsIn[i][0] > *xmax)
72 *xmax = vertsIn[i][0];
73 if (vertsIn[i][1] < *ymin)
74 *ymin = vertsIn[i][1];
75 else if (vertsIn[i][1] > *ymax)
76 *ymax = vertsIn[i][1];
77 }
78}
79
80
81static void
82Redisplay(void)
83{
84 GLfloat v[3][2], xmin, ymin, xmax, ymax;
85
86 RotateVerts(Zrot, 3, TriVerts, v);
87 ComputeBounds(3, v, &xmin, &ymin, &xmax, &ymax);
88
89 glUniform2fv_func(uv0, 1, v[0]);
90 glUniform2fv_func(uv1, 1, v[1]);
91 glUniform2fv_func(uv2, 1, v[2]);
92
93 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
94
95 glPushMatrix();
96 glBegin(GL_POLYGON);
97 glVertex2f(xmin, ymin);
98 glVertex2f(xmax, ymin);
99 glVertex2f(xmax, ymax);
100 glVertex2f(xmin, ymax);
101 glEnd();
102 glPopMatrix();
103
104 glutSwapBuffers();
105}
106
107
108static void
109Idle(void)
110{
Brian8211b202007-11-16 15:18:30 -0700111 if (anim) {
112 Zrot = glutGet(GLUT_ELAPSED_TIME) * 0.0005;
113 glutPostRedisplay();
114 }
115 else
116 abort();
Brian261eac32007-08-01 11:13:25 -0600117}
118
119
120static void
121Reshape(int width, int height)
122{
123 glViewport(0, 0, width, height);
124 glMatrixMode(GL_PROJECTION);
125 glLoadIdentity();
126 glOrtho(0, width, 0, height, -1, 1);
127
128 glMatrixMode(GL_MODELVIEW);
129 glLoadIdentity();
130}
131
132
133static void
134CleanUp(void)
135{
136 glDeleteShader_func(fragShader);
137 glDeleteShader_func(vertShader);
138 glDeleteProgram_func(program);
139 glutDestroyWindow(win);
140}
141
142
143static void
144Key(unsigned char key, int x, int y)
145{
146 (void) x;
147 (void) y;
148
149 switch(key) {
150 case ' ':
151 case 'a':
152 anim = !anim;
153 if (anim)
154 glutIdleFunc(Idle);
155 else
156 glutIdleFunc(NULL);
157 break;
Brian8211b202007-11-16 15:18:30 -0700158 case 'z':
159 Zrot = 0;
160 break;
161 case 's':
162 Zrot += 0.05;
163 break;
Brian261eac32007-08-01 11:13:25 -0600164 case 27:
165 CleanUp();
166 exit(0);
167 break;
168 }
169 glutPostRedisplay();
170}
171
172
173static void
Brian261eac32007-08-01 11:13:25 -0600174Init(void)
175{
176 static const char *fragShaderText =
177 "uniform vec2 v0, v1, v2; \n"
178 "float crs(const vec2 u, const vec2 v) \n"
179 "{ \n"
180 " return u.x * v.y - u.y * v.x; \n"
181 "} \n"
182 "\n"
183 "void main() {\n"
184 " vec2 p = gl_FragCoord.xy; \n"
185 " if (crs(v1 - v0, p - v0) >= 0 && \n"
186 " crs(v2 - v1, p - v1) >= 0 && \n"
187 " crs(v0 - v2, p - v2) >= 0) \n"
188 " gl_FragColor = vec4(1.0); \n"
189 " else \n"
190 " gl_FragColor = vec4(0.5); \n"
191 "}\n";
192 static const char *vertShaderText =
193 "void main() {\n"
Brian Paul8f1d5ca2008-08-20 15:32:33 -0600194 " gl_Position = ftransform(); \n"
Brian261eac32007-08-01 11:13:25 -0600195 "}\n";
Brian261eac32007-08-01 11:13:25 -0600196
Brian2dca3372008-04-09 22:28:23 -0600197 if (!ShadersSupported())
Brian261eac32007-08-01 11:13:25 -0600198 exit(1);
Brian261eac32007-08-01 11:13:25 -0600199
200 GetExtensionFuncs();
201
Brian2dca3372008-04-09 22:28:23 -0600202 vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
203 fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
204 program = LinkShaders(vertShader, fragShader);
Brian261eac32007-08-01 11:13:25 -0600205
Brian261eac32007-08-01 11:13:25 -0600206 glUseProgram_func(program);
207
208 uv0 = glGetUniformLocation_func(program, "v0");
209 uv1 = glGetUniformLocation_func(program, "v1");
210 uv2 = glGetUniformLocation_func(program, "v2");
211 printf("Uniforms: %d %d %d\n", uv0, uv1, uv2);
212
213 /*assert(glGetError() == 0);*/
214
215 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
216 glEnable(GL_DEPTH_TEST);
217
218 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
219
220 assert(glIsProgram_func(program));
221 assert(glIsShader_func(fragShader));
222 assert(glIsShader_func(vertShader));
223
224 glColor3f(1, 0, 0);
225}
226
227
228static void
229ParseOptions(int argc, char *argv[])
230{
231 int i;
232 for (i = 1; i < argc; i++) {
233 if (strcmp(argv[i], "-fs") == 0) {
234 FragProgFile = argv[i+1];
235 }
236 else if (strcmp(argv[i], "-vs") == 0) {
237 VertProgFile = argv[i+1];
238 }
239 }
240}
241
242
243int
244main(int argc, char *argv[])
245{
246 glutInit(&argc, argv);
247 glutInitWindowPosition( 0, 0);
248 glutInitWindowSize(WinWidth, WinHeight);
249 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
250 win = glutCreateWindow(argv[0]);
Keith Whitwellb799af92009-06-29 14:13:58 +0100251 glewInit();
Brian261eac32007-08-01 11:13:25 -0600252 glutReshapeFunc(Reshape);
253 glutKeyboardFunc(Key);
254 glutDisplayFunc(Redisplay);
255 if (anim)
256 glutIdleFunc(Idle);
257 ParseOptions(argc, argv);
258 Init();
259 glutMainLoop();
260 return 0;
261}