diff options
Diffstat (limited to 'progs/glsl/trirast.c')
-rw-r--r-- | progs/glsl/trirast.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/progs/glsl/trirast.c b/progs/glsl/trirast.c new file mode 100644 index 00000000000..89df64fc718 --- /dev/null +++ b/progs/glsl/trirast.c @@ -0,0 +1,259 @@ +/** + * Demonstration of doing triangle rasterization with a fragment program. + * Basic idea: + * 1. Draw screen-aligned quad / bounding box around the triangle verts. + * 2. For each pixel in the quad, determine if pixel is inside/outside + * the triangle edges. + * + * Brian Paul + * 1 Aug 2007 + */ + + +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <GL/gl.h> +#include <GL/glut.h> +#include <GL/glext.h> +#include "extfuncs.h" +#include "shaderutil.h" + + +static GLint WinWidth = 300, WinHeight = 300; +static char *FragProgFile = NULL; +static char *VertProgFile = NULL; +static GLuint fragShader; +static GLuint vertShader; +static GLuint program; +static GLint win = 0; +static GLboolean anim = GL_TRUE; +static GLfloat Zrot = 0.0f; +static GLint uv0, uv1, uv2; + + +static const GLfloat TriVerts[3][2] = { + { 50, 50 }, + { 250, 50 }, + { 150, 250 } +}; + + +static void +RotateVerts(GLfloat a, + GLuint n, const GLfloat vertsIn[][2], GLfloat vertsOut[][2]) +{ + GLuint i; + GLfloat cx = WinWidth / 2, cy = WinHeight / 2; + for (i = 0; i < n; i++) { + float x = vertsIn[i][0] - cx; + float y = vertsIn[i][1] - cy; + + vertsOut[i][0] = x * cos(a) + y * sin(a) + cx; + vertsOut[i][1] = -x * sin(a) + y * cos(a) + cy; + } +} + +static void +ComputeBounds(GLuint n, GLfloat vertsIn[][2], + GLfloat *xmin, GLfloat *ymin, + GLfloat *xmax, GLfloat *ymax) +{ + GLuint i; + *xmin = *xmax = vertsIn[0][0]; + *ymin = *ymax = vertsIn[0][1]; + for (i = 1; i < n; i++) { + if (vertsIn[i][0] < *xmin) + *xmin = vertsIn[i][0]; + else if (vertsIn[i][0] > *xmax) + *xmax = vertsIn[i][0]; + if (vertsIn[i][1] < *ymin) + *ymin = vertsIn[i][1]; + else if (vertsIn[i][1] > *ymax) + *ymax = vertsIn[i][1]; + } +} + + +static void +Redisplay(void) +{ + GLfloat v[3][2], xmin, ymin, xmax, ymax; + + RotateVerts(Zrot, 3, TriVerts, v); + ComputeBounds(3, v, &xmin, &ymin, &xmax, &ymax); + + glUniform2fv_func(uv0, 1, v[0]); + glUniform2fv_func(uv1, 1, v[1]); + glUniform2fv_func(uv2, 1, v[2]); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glBegin(GL_POLYGON); + glVertex2f(xmin, ymin); + glVertex2f(xmax, ymin); + glVertex2f(xmax, ymax); + glVertex2f(xmin, ymax); + glEnd(); + glPopMatrix(); + + glutSwapBuffers(); +} + + +static void +Idle(void) +{ + if (anim) { + Zrot = glutGet(GLUT_ELAPSED_TIME) * 0.0005; + glutPostRedisplay(); + } + else + abort(); +} + + +static void +Reshape(int width, int height) +{ + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, 0, height, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +static void +CleanUp(void) +{ + glDeleteShader_func(fragShader); + glDeleteShader_func(vertShader); + glDeleteProgram_func(program); + glutDestroyWindow(win); +} + + +static void +Key(unsigned char key, int x, int y) +{ + (void) x; + (void) y; + + switch(key) { + case ' ': + case 'a': + anim = !anim; + if (anim) + glutIdleFunc(Idle); + else + glutIdleFunc(NULL); + break; + case 'z': + Zrot = 0; + break; + case 's': + Zrot += 0.05; + break; + case 27: + CleanUp(); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void +Init(void) +{ + static const char *fragShaderText = + "uniform vec2 v0, v1, v2; \n" + "float crs(const vec2 u, const vec2 v) \n" + "{ \n" + " return u.x * v.y - u.y * v.x; \n" + "} \n" + "\n" + "void main() {\n" + " vec2 p = gl_FragCoord.xy; \n" + " if (crs(v1 - v0, p - v0) >= 0 && \n" + " crs(v2 - v1, p - v1) >= 0 && \n" + " crs(v0 - v2, p - v2) >= 0) \n" + " gl_FragColor = vec4(1.0); \n" + " else \n" + " gl_FragColor = vec4(0.5); \n" + "}\n"; + static const char *vertShaderText = + "void main() {\n" + " gl_Position = ftransform(); \n" + "}\n"; + + if (!ShadersSupported()) + exit(1); + + GetExtensionFuncs(); + + vertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText); + fragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText); + program = LinkShaders(vertShader, fragShader); + + glUseProgram_func(program); + + uv0 = glGetUniformLocation_func(program, "v0"); + uv1 = glGetUniformLocation_func(program, "v1"); + uv2 = glGetUniformLocation_func(program, "v2"); + printf("Uniforms: %d %d %d\n", uv0, uv1, uv2); + + /*assert(glGetError() == 0);*/ + + glClearColor(0.3f, 0.3f, 0.3f, 0.0f); + glEnable(GL_DEPTH_TEST); + + printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); + + assert(glIsProgram_func(program)); + assert(glIsShader_func(fragShader)); + assert(glIsShader_func(vertShader)); + + glColor3f(1, 0, 0); +} + + +static void +ParseOptions(int argc, char *argv[]) +{ + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-fs") == 0) { + FragProgFile = argv[i+1]; + } + else if (strcmp(argv[i], "-vs") == 0) { + VertProgFile = argv[i+1]; + } + } +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition( 0, 0); + glutInitWindowSize(WinWidth, WinHeight); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + win = glutCreateWindow(argv[0]); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Redisplay); + if (anim) + glutIdleFunc(Idle); + ParseOptions(argc, argv); + Init(); + glutMainLoop(); + return 0; +} |