2 * Implement smooth (AA) points with shaders.
3 * A simple variation could be used for sprite points.
18 #include "shaderutil.h"
21 static GLuint FragShader
;
22 static GLuint VertShader
;
23 static GLuint Program
;
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
;
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.
38 PointVertex3f(GLfloat x
, GLfloat y
, GLfloat z
)
55 DrawPoints(GLboolean shaderPoints
)
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 );
64 PointVertex3f(x
, y
, z
);
77 * Top row of points rendered convetionally,
78 * bottom row rendered with shaders.
83 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
86 glEnable(GL_POINT_SMOOTH
);
88 glDisable(GL_POINT_SMOOTH
);
96 glTranslatef(Xpos
, Ypos
, 0);
102 glTranslatef(0, 1.2, 0);
103 glUseProgram_func(0);
104 DrawPoints(GL_FALSE
);
111 glTranslatef(0, -1.2, 0);
112 glUseProgram_func(Program
);
113 if (uViewportInv
!= -1) {
114 glUniform2f_func(uViewportInv
, 1.0 / WinWidth
, 1.0 / WinHeight
);
126 Reshape(int width
, int height
)
130 glViewport(0, 0, width
, height
);
131 glMatrixMode(GL_PROJECTION
);
133 glFrustum(-1.0, 1.0, -1.0, 1.0, 4.0, 30.0);
134 glMatrixMode(GL_MODELVIEW
);
136 glTranslatef(0.0f
, 0.0f
, -20.0f
);
141 Key(unsigned char key
, int x
, int y
)
154 glDeleteShader_func(FragShader
);
155 glDeleteShader_func(VertShader
);
156 glDeleteProgram_func(Program
);
157 glutDestroyWindow(Win
);
165 SpecialKey(int key
, int x
, int y
)
167 const GLfloat step
= 1/100.0;
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)
197 static const char *fragShaderText
=
200 " float k = 2.0 / gl_Point.size; \n"
201 " float d = length(gl_TexCoord[0].xy); \n"
204 " if (d < 1.0 - k) \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"
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.
215 static const char *vertShaderText
=
216 "uniform vec2 viewportInv; \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"
226 if (!ShadersSupported())
231 VertShader
= CompileShaderText(GL_VERTEX_SHADER
, vertShaderText
);
232 FragShader
= CompileShaderText(GL_FRAGMENT_SHADER
, fragShaderText
);
233 Program
= LinkShaders(VertShader
, FragShader
);
235 glUseProgram_func(Program
);
237 uViewportInv
= glGetUniformLocation_func(Program
, "viewportInv");
239 glUseProgram_func(0);
241 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
246 main(int argc
, char *argv
[])
248 glutInit(&argc
, argv
);
249 glutInitWindowSize(WinWidth
, WinHeight
);
250 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
251 Win
= glutCreateWindow(argv
[0]);
253 glutReshapeFunc(Reshape
);
254 glutKeyboardFunc(Key
);
255 glutSpecialFunc(SpecialKey
);
256 glutDisplayFunc(Redisplay
);