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