2 * Implement smooth (AA) points with shaders.
3 * A simple variation could be used for sprite points.
17 #include "shaderutil.h"
20 static GLuint FragShader
;
21 static GLuint VertShader
;
22 static GLuint Program
;
25 static GLint WinWidth
= 500, WinHeight
= 200;
26 static GLfloat Xpos
= 0.0f
, Ypos
= 0.0f
;
27 static GLint uViewportInv
;
28 static GLboolean Smooth
= GL_TRUE
, Blend
= GL_TRUE
;
32 * Issue vertices for a "shader point".
33 * The position is duplicated, only texcoords (or other vertex attrib) change.
34 * The vertex program will compute the "real" quad corners.
37 PointVertex3f(GLfloat x
, GLfloat y
, GLfloat z
)
54 DrawPoints(GLboolean shaderPoints
)
57 for (i
= 0; i
< 9; i
++) {
58 GLfloat x
= i
- 4, y
= 0, z
= 0;
59 /* note: can't call glPointSize inside Begin/End :( */
60 glPointSize( 2 + i
* 5 );
63 PointVertex3f(x
, y
, z
);
76 * Top row of points rendered convetionally,
77 * bottom row rendered with shaders.
82 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
85 glEnable(GL_POINT_SMOOTH
);
87 glDisable(GL_POINT_SMOOTH
);
95 glTranslatef(Xpos
, Ypos
, 0);
101 glTranslatef(0, 1.2, 0);
102 glUseProgram_func(0);
103 DrawPoints(GL_FALSE
);
110 glTranslatef(0, -1.2, 0);
111 glUseProgram_func(Program
);
112 if (uViewportInv
!= -1) {
113 glUniform2f_func(uViewportInv
, 1.0 / WinWidth
, 1.0 / WinHeight
);
125 Reshape(int width
, int height
)
129 glViewport(0, 0, width
, height
);
130 glMatrixMode(GL_PROJECTION
);
132 glFrustum(-1.0, 1.0, -1.0, 1.0, 4.0, 30.0);
133 glMatrixMode(GL_MODELVIEW
);
135 glTranslatef(0.0f
, 0.0f
, -20.0f
);
140 Key(unsigned char key
, int x
, int y
)
153 glDeleteShader_func(FragShader
);
154 glDeleteShader_func(VertShader
);
155 glDeleteProgram_func(Program
);
156 glutDestroyWindow(Win
);
164 SpecialKey(int key
, int x
, int y
)
166 const GLfloat step
= 1/100.0;
188 /* Fragment shader: compute distance of fragment from center of point
189 * (we're using texcoords but another varying could be used).
190 * if dist > 1, discard (coverage==0)
191 * if dist < k, coverage = 1
192 * else, coverage = func(dist)
193 * Note: length() uses sqrt() and may be expensive. The distance could
194 * be squared instead (with adjustments to the threshold (k) test)
196 static const char *fragShaderText
=
199 " float k = 2.0 / gl_Point.size; \n"
200 " float d = length(gl_TexCoord[0].xy); \n"
203 " if (d < 1.0 - k) \n"
206 " cover = (1.0 - d) * 0.5 * gl_Point.size; \n"
207 " gl_FragColor.rgb = gl_Color.rgb; \n"
208 " gl_FragColor.a = cover; \n"
210 /* Vertex shader: compute new vertex position based on incoming vertex pos,
211 * texcoords, point size, and inverse viewport scale factor.
212 * Note: should compute point size attenuation here too.
214 static const char *vertShaderText
=
215 "uniform vec2 viewportInv; \n"
217 " vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
218 " gl_Position.xy = pos.xy + gl_MultiTexCoord0.xy * viewportInv \n"
219 " * gl_Point.size * pos.w; \n"
220 " gl_Position.zw = pos.zw; \n"
221 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
222 " gl_FrontColor = gl_Color; \n"
225 if (!ShadersSupported())
230 VertShader
= CompileShaderText(GL_VERTEX_SHADER
, vertShaderText
);
231 FragShader
= CompileShaderText(GL_FRAGMENT_SHADER
, fragShaderText
);
232 Program
= LinkShaders(VertShader
, FragShader
);
234 glUseProgram_func(Program
);
236 uViewportInv
= glGetUniformLocation_func(Program
, "viewportInv");
238 glUseProgram_func(0);
240 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
245 main(int argc
, char *argv
[])
247 glutInit(&argc
, argv
);
248 glutInitWindowSize(WinWidth
, WinHeight
);
249 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
250 Win
= glutCreateWindow(argv
[0]);
251 glutReshapeFunc(Reshape
);
252 glutKeyboardFunc(Key
);
253 glutSpecialFunc(SpecialKey
);
254 glutDisplayFunc(Redisplay
);