progs/glsl: compile with scons and glew
[mesa.git] / progs / glsl / points.c
1 /**
2 * Implement smooth (AA) points with shaders.
3 * A simple variation could be used for sprite points.
4 * Brian Paul
5 * 29 July 2007
6 */
7
8 #include <assert.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <math.h>
13 #include <GL/glew.h>
14 #include <GL/gl.h>
15 #include <GL/glut.h>
16 #include <GL/glext.h>
17 #include "extfuncs.h"
18 #include "shaderutil.h"
19
20
21 static GLuint FragShader;
22 static GLuint VertShader;
23 static GLuint Program;
24
25 static GLint Win = 0;
26 static GLint WinWidth = 500, WinHeight = 200;
27 static GLfloat Xpos = 0.0f, Ypos = 0.0f;
28 static GLint uViewportInv;
29 static GLboolean Smooth = GL_TRUE, Blend = GL_TRUE;
30
31
32 /**
33 * Issue vertices for a "shader point".
34 * The position is duplicated, only texcoords (or other vertex attrib) change.
35 * The vertex program will compute the "real" quad corners.
36 */
37 static void
38 PointVertex3f(GLfloat x, GLfloat y, GLfloat z)
39 {
40 glTexCoord2f(-1, -1);
41 glVertex3f(x, y, z);
42
43 glTexCoord2f( 1, -1);
44 glVertex3f(x, y, z);
45
46 glTexCoord2f( 1, 1);
47 glVertex3f(x, y, z);
48
49 glTexCoord2f(-1, 1);
50 glVertex3f(x, y, z);
51 }
52
53
54 static void
55 DrawPoints(GLboolean shaderPoints)
56 {
57 int i;
58 for (i = 0; i < 9; i++) {
59 GLfloat x = i - 4, y = 0, z = 0;
60 /* note: can't call glPointSize inside Begin/End :( */
61 glPointSize( 2 + i * 5 );
62 if (shaderPoints) {
63 glBegin(GL_QUADS);
64 PointVertex3f(x, y, z);
65 glEnd();
66 }
67 else {
68 glBegin(GL_POINTS);
69 glVertex3f(x, y, z);
70 glEnd();
71 }
72 }
73 }
74
75
76 /**
77 * Top row of points rendered convetionally,
78 * bottom row rendered with shaders.
79 */
80 static void
81 Redisplay(void)
82 {
83 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
84
85 if (Smooth)
86 glEnable(GL_POINT_SMOOTH);
87 else
88 glDisable(GL_POINT_SMOOTH);
89
90 if (Blend)
91 glEnable(GL_BLEND);
92 else
93 glDisable(GL_BLEND);
94
95 glPushMatrix();
96 glTranslatef(Xpos, Ypos, 0);
97
98 /*
99 * regular points
100 */
101 glPushMatrix();
102 glTranslatef(0, 1.2, 0);
103 glUseProgram_func(0);
104 DrawPoints(GL_FALSE);
105 glPopMatrix();
106
107 /*
108 * shader points
109 */
110 glPushMatrix();
111 glTranslatef(0, -1.2, 0);
112 glUseProgram_func(Program);
113 if (uViewportInv != -1) {
114 glUniform2f_func(uViewportInv, 1.0 / WinWidth, 1.0 / WinHeight);
115 }
116 DrawPoints(GL_TRUE);
117 glPopMatrix();
118
119 glPopMatrix();
120
121 glutSwapBuffers();
122 }
123
124
125 static void
126 Reshape(int width, int height)
127 {
128 WinWidth = width;
129 WinHeight = height;
130 glViewport(0, 0, width, height);
131 glMatrixMode(GL_PROJECTION);
132 glLoadIdentity();
133 glFrustum(-1.0, 1.0, -1.0, 1.0, 4.0, 30.0);
134 glMatrixMode(GL_MODELVIEW);
135 glLoadIdentity();
136 glTranslatef(0.0f, 0.0f, -20.0f);
137 }
138
139
140 static void
141 Key(unsigned char key, int x, int y)
142 {
143 (void) x;
144 (void) y;
145
146 switch(key) {
147 case 'b':
148 Blend = !Blend;
149 break;
150 case 's':
151 Smooth = !Smooth;
152 break;
153 case 27:
154 glDeleteShader_func(FragShader);
155 glDeleteShader_func(VertShader);
156 glDeleteProgram_func(Program);
157 glutDestroyWindow(Win);
158 exit(0);
159 }
160 glutPostRedisplay();
161 }
162
163
164 static void
165 SpecialKey(int key, int x, int y)
166 {
167 const GLfloat step = 1/100.0;
168 switch(key) {
169 case GLUT_KEY_UP:
170 Ypos += step;
171 break;
172 case GLUT_KEY_DOWN:
173 Ypos -= step;
174 break;
175 case GLUT_KEY_LEFT:
176 Xpos -= step;
177 break;
178 case GLUT_KEY_RIGHT:
179 Xpos += step;
180 break;
181 }
182 glutPostRedisplay();
183 }
184
185
186 static void
187 Init(void)
188 {
189 /* Fragment shader: compute distance of fragment from center of point
190 * (we're using texcoords but another varying could be used).
191 * if dist > 1, discard (coverage==0)
192 * if dist < k, coverage = 1
193 * else, coverage = func(dist)
194 * Note: length() uses sqrt() and may be expensive. The distance could
195 * be squared instead (with adjustments to the threshold (k) test)
196 */
197 static const char *fragShaderText =
198 "void main() {\n"
199 " float cover; \n"
200 " float k = 2.0 / gl_Point.size; \n"
201 " float d = length(gl_TexCoord[0].xy); \n"
202 " if (d >= 1.0) \n"
203 " discard; \n"
204 " if (d < 1.0 - k) \n"
205 " cover = 1.0; \n"
206 " else \n"
207 " cover = (1.0 - d) * 0.5 * gl_Point.size; \n"
208 " gl_FragColor.rgb = gl_Color.rgb; \n"
209 " gl_FragColor.a = cover; \n"
210 "}\n";
211 /* Vertex shader: compute new vertex position based on incoming vertex pos,
212 * texcoords, point size, and inverse viewport scale factor.
213 * Note: should compute point size attenuation here too.
214 */
215 static const char *vertShaderText =
216 "uniform vec2 viewportInv; \n"
217 "void main() {\n"
218 " vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
219 " gl_Position.xy = pos.xy + gl_MultiTexCoord0.xy * viewportInv \n"
220 " * gl_Point.size * pos.w; \n"
221 " gl_Position.zw = pos.zw; \n"
222 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
223 " gl_FrontColor = gl_Color; \n"
224 "}\n";
225
226 if (!ShadersSupported())
227 exit(1);
228
229 GetExtensionFuncs();
230
231 VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText);
232 FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText);
233 Program = LinkShaders(VertShader, FragShader);
234
235 glUseProgram_func(Program);
236
237 uViewportInv = glGetUniformLocation_func(Program, "viewportInv");
238
239 glUseProgram_func(0);
240
241 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
242 }
243
244
245 int
246 main(int argc, char *argv[])
247 {
248 glutInit(&argc, argv);
249 glutInitWindowSize(WinWidth, WinHeight);
250 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
251 Win = glutCreateWindow(argv[0]);
252 glewInit();
253 glutReshapeFunc(Reshape);
254 glutKeyboardFunc(Key);
255 glutSpecialFunc(SpecialKey);
256 glutDisplayFunc(Redisplay);
257 Init();
258 glutMainLoop();
259 return 0;
260 }
261
262