132001f49Smrg/** 232001f49Smrg * Demonstration of doing triangle rasterization with a fragment program. 332001f49Smrg * Basic idea: 432001f49Smrg * 1. Draw screen-aligned quad / bounding box around the triangle verts. 532001f49Smrg * 2. For each pixel in the quad, determine if pixel is inside/outside 632001f49Smrg * the triangle edges. 732001f49Smrg * 832001f49Smrg * Brian Paul 932001f49Smrg * 1 Aug 2007 1032001f49Smrg */ 1132001f49Smrg 1232001f49Smrg 1332001f49Smrg#include <assert.h> 1432001f49Smrg#include <string.h> 1532001f49Smrg#include <stdio.h> 1632001f49Smrg#include <stdlib.h> 1732001f49Smrg#include <math.h> 1832001f49Smrg#include <GL/glew.h> 1932001f49Smrg#include "glut_wrap.h" 2032001f49Smrg#include "shaderutil.h" 2132001f49Smrg 2232001f49Smrg 2332001f49Smrgstatic GLint WinWidth = 300, WinHeight = 300; 2432001f49Smrgstatic char *FragProgFile = NULL; 2532001f49Smrgstatic char *VertProgFile = NULL; 2632001f49Smrgstatic GLuint fragShader; 2732001f49Smrgstatic GLuint vertShader; 2832001f49Smrgstatic GLuint program; 2932001f49Smrgstatic GLint win = 0; 3032001f49Smrgstatic GLboolean anim = GL_TRUE; 3132001f49Smrgstatic GLfloat Zrot = 0.0f; 3232001f49Smrgstatic GLint uv0, uv1, uv2; 3332001f49Smrg 3432001f49Smrg 3532001f49Smrgstatic const GLfloat TriVerts[3][2] = { 3632001f49Smrg { 50, 50 }, 3732001f49Smrg { 250, 50 }, 3832001f49Smrg { 150, 250 } 3932001f49Smrg}; 4032001f49Smrg 4132001f49Smrg 4232001f49Smrgstatic void 4332001f49SmrgRotateVerts(GLfloat a, 4432001f49Smrg GLuint n, const GLfloat vertsIn[][2], GLfloat vertsOut[][2]) 4532001f49Smrg{ 4632001f49Smrg GLuint i; 4732001f49Smrg GLfloat cx = WinWidth / 2, cy = WinHeight / 2; 4832001f49Smrg for (i = 0; i < n; i++) { 4932001f49Smrg float x = vertsIn[i][0] - cx; 5032001f49Smrg float y = vertsIn[i][1] - cy; 5132001f49Smrg 5232001f49Smrg vertsOut[i][0] = x * cos(a) + y * sin(a) + cx; 5332001f49Smrg vertsOut[i][1] = -x * sin(a) + y * cos(a) + cy; 5432001f49Smrg } 5532001f49Smrg} 5632001f49Smrg 5732001f49Smrgstatic void 5832001f49SmrgComputeBounds(GLuint n, GLfloat vertsIn[][2], 5932001f49Smrg GLfloat *xmin, GLfloat *ymin, 6032001f49Smrg GLfloat *xmax, GLfloat *ymax) 6132001f49Smrg{ 6232001f49Smrg GLuint i; 6332001f49Smrg *xmin = *xmax = vertsIn[0][0]; 6432001f49Smrg *ymin = *ymax = vertsIn[0][1]; 6532001f49Smrg for (i = 1; i < n; i++) { 6632001f49Smrg if (vertsIn[i][0] < *xmin) 6732001f49Smrg *xmin = vertsIn[i][0]; 6832001f49Smrg else if (vertsIn[i][0] > *xmax) 6932001f49Smrg *xmax = vertsIn[i][0]; 7032001f49Smrg if (vertsIn[i][1] < *ymin) 7132001f49Smrg *ymin = vertsIn[i][1]; 7232001f49Smrg else if (vertsIn[i][1] > *ymax) 7332001f49Smrg *ymax = vertsIn[i][1]; 7432001f49Smrg } 7532001f49Smrg} 7632001f49Smrg 7732001f49Smrg 7832001f49Smrgstatic void 7932001f49SmrgRedisplay(void) 8032001f49Smrg{ 8132001f49Smrg GLfloat v[3][2], xmin, ymin, xmax, ymax; 8232001f49Smrg 8332001f49Smrg RotateVerts(Zrot, 3, TriVerts, v); 8432001f49Smrg ComputeBounds(3, v, &xmin, &ymin, &xmax, &ymax); 8532001f49Smrg 8632001f49Smrg glUniform2fv(uv0, 1, v[0]); 8732001f49Smrg glUniform2fv(uv1, 1, v[1]); 8832001f49Smrg glUniform2fv(uv2, 1, v[2]); 8932001f49Smrg 9032001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 9132001f49Smrg 9232001f49Smrg glPushMatrix(); 9332001f49Smrg glBegin(GL_POLYGON); 9432001f49Smrg glVertex2f(xmin, ymin); 9532001f49Smrg glVertex2f(xmax, ymin); 9632001f49Smrg glVertex2f(xmax, ymax); 9732001f49Smrg glVertex2f(xmin, ymax); 9832001f49Smrg glEnd(); 9932001f49Smrg glPopMatrix(); 10032001f49Smrg 10132001f49Smrg glutSwapBuffers(); 10232001f49Smrg} 10332001f49Smrg 10432001f49Smrg 10532001f49Smrgstatic void 10632001f49SmrgIdle(void) 10732001f49Smrg{ 10832001f49Smrg if (anim) { 10932001f49Smrg Zrot = glutGet(GLUT_ELAPSED_TIME) * 0.0005; 11032001f49Smrg glutPostRedisplay(); 11132001f49Smrg } 11232001f49Smrg else 11332001f49Smrg abort(); 11432001f49Smrg} 11532001f49Smrg 11632001f49Smrg 11732001f49Smrgstatic void 11832001f49SmrgReshape(int width, int height) 11932001f49Smrg{ 12032001f49Smrg glViewport(0, 0, width, height); 12132001f49Smrg glMatrixMode(GL_PROJECTION); 12232001f49Smrg glLoadIdentity(); 12332001f49Smrg glOrtho(0, width, 0, height, -1, 1); 12432001f49Smrg 12532001f49Smrg glMatrixMode(GL_MODELVIEW); 12632001f49Smrg glLoadIdentity(); 12732001f49Smrg} 12832001f49Smrg 12932001f49Smrg 13032001f49Smrgstatic void 13132001f49SmrgCleanUp(void) 13232001f49Smrg{ 13332001f49Smrg glDeleteShader(fragShader); 13432001f49Smrg glDeleteShader(vertShader); 13532001f49Smrg glDeleteProgram(program); 13632001f49Smrg glutDestroyWindow(win); 13732001f49Smrg} 13832001f49Smrg 13932001f49Smrg 14032001f49Smrgstatic void 14132001f49SmrgKey(unsigned char key, int x, int y) 14232001f49Smrg{ 14332001f49Smrg (void) x; 14432001f49Smrg (void) y; 14532001f49Smrg 14632001f49Smrg switch(key) { 14732001f49Smrg case ' ': 14832001f49Smrg case 'a': 14932001f49Smrg anim = !anim; 15032001f49Smrg if (anim) 15132001f49Smrg glutIdleFunc(Idle); 15232001f49Smrg else 15332001f49Smrg glutIdleFunc(NULL); 15432001f49Smrg break; 15532001f49Smrg case 'z': 15632001f49Smrg Zrot = 0; 15732001f49Smrg break; 15832001f49Smrg case 's': 15932001f49Smrg Zrot += 0.05; 16032001f49Smrg break; 16132001f49Smrg case 27: 16232001f49Smrg CleanUp(); 16332001f49Smrg exit(0); 16432001f49Smrg break; 16532001f49Smrg } 16632001f49Smrg glutPostRedisplay(); 16732001f49Smrg} 16832001f49Smrg 16932001f49Smrg 17032001f49Smrgstatic void 17132001f49SmrgInit(void) 17232001f49Smrg{ 17332001f49Smrg static const char *fragShaderText = 17432001f49Smrg "uniform vec2 v0, v1, v2; \n" 17532001f49Smrg "float crs(const vec2 u, const vec2 v) \n" 17632001f49Smrg "{ \n" 17732001f49Smrg " return u.x * v.y - u.y * v.x; \n" 17832001f49Smrg "} \n" 17932001f49Smrg "\n" 18032001f49Smrg "void main() {\n" 18132001f49Smrg " vec2 p = gl_FragCoord.xy; \n" 18232001f49Smrg " if (crs(v1 - v0, p - v0) >= 0.0 && \n" 18332001f49Smrg " crs(v2 - v1, p - v1) >= 0.0 && \n" 18432001f49Smrg " crs(v0 - v2, p - v2) >= 0.0) \n" 18532001f49Smrg " gl_FragColor = vec4(1.0); \n" 18632001f49Smrg " else \n" 18732001f49Smrg " gl_FragColor = vec4(0.5); \n" 18832001f49Smrg "}\n"; 18932001f49Smrg static const char *vertShaderText = 19032001f49Smrg "void main() {\n" 19132001f49Smrg " gl_Position = ftransform(); \n" 19232001f49Smrg "}\n"; 19332001f49Smrg 19432001f49Smrg if (!ShadersSupported()) 19532001f49Smrg exit(1); 19632001f49Smrg 19732001f49Smrg vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText); 19832001f49Smrg fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText); 19932001f49Smrg program = LinkShaders(vertShader, fragShader); 20032001f49Smrg 20132001f49Smrg glUseProgram(program); 20232001f49Smrg 20332001f49Smrg uv0 = glGetUniformLocation(program, "v0"); 20432001f49Smrg uv1 = glGetUniformLocation(program, "v1"); 20532001f49Smrg uv2 = glGetUniformLocation(program, "v2"); 20632001f49Smrg 20732001f49Smrg /*assert(glGetError() == 0);*/ 20832001f49Smrg 20932001f49Smrg glClearColor(0.3f, 0.3f, 0.3f, 0.0f); 21032001f49Smrg glEnable(GL_DEPTH_TEST); 21132001f49Smrg 21232001f49Smrg printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); 21332001f49Smrg 21432001f49Smrg assert(glIsProgram(program)); 21532001f49Smrg assert(glIsShader(fragShader)); 21632001f49Smrg assert(glIsShader(vertShader)); 21732001f49Smrg 21832001f49Smrg glColor3f(1, 0, 0); 21932001f49Smrg} 22032001f49Smrg 22132001f49Smrg 22232001f49Smrgstatic void 22332001f49SmrgParseOptions(int argc, char *argv[]) 22432001f49Smrg{ 22532001f49Smrg int i; 22632001f49Smrg for (i = 1; i < argc; i++) { 22732001f49Smrg if (strcmp(argv[i], "-fs") == 0) { 22832001f49Smrg FragProgFile = argv[i+1]; 22932001f49Smrg } 23032001f49Smrg else if (strcmp(argv[i], "-vs") == 0) { 23132001f49Smrg VertProgFile = argv[i+1]; 23232001f49Smrg } 23332001f49Smrg } 23432001f49Smrg} 23532001f49Smrg 23632001f49Smrg 23732001f49Smrgint 23832001f49Smrgmain(int argc, char *argv[]) 23932001f49Smrg{ 24032001f49Smrg glutInit(&argc, argv); 24132001f49Smrg glutInitWindowSize(WinWidth, WinHeight); 24232001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 24332001f49Smrg win = glutCreateWindow(argv[0]); 24432001f49Smrg glewInit(); 24532001f49Smrg glutReshapeFunc(Reshape); 24632001f49Smrg glutKeyboardFunc(Key); 24732001f49Smrg glutDisplayFunc(Redisplay); 24832001f49Smrg if (anim) 24932001f49Smrg glutIdleFunc(Idle); 25032001f49Smrg ParseOptions(argc, argv); 25132001f49Smrg Init(); 25232001f49Smrg glutMainLoop(); 25332001f49Smrg return 0; 25432001f49Smrg} 255