2 * Implement smooth (AA) points with shaders.
3 * A simple variation could be used for sprite points.
14 #include "glut_wrap.h"
15 #include "shaderutil.h"
18 static GLuint FragShader
;
19 static GLuint VertShader
;
20 static GLuint Program
;
23 static GLint WinWidth
= 500, WinHeight
= 200;
24 static GLfloat Xpos
= 0.0f
, Ypos
= 0.0f
;
25 static GLint uViewportInv
;
26 static GLboolean Smooth
= GL_TRUE
, Blend
= GL_TRUE
;
30 * Issue vertices for a "shader point".
31 * The position is duplicated, only texcoords (or other vertex attrib) change.
32 * The vertex program will compute the "real" quad corners.
35 PointVertex3f(GLfloat x
, GLfloat y
, GLfloat z
)
52 DrawPoints(GLboolean shaderPoints
)
55 for (i
= 0; i
< 9; i
++) {
56 GLfloat x
= i
- 4, y
= 0, z
= 0;
57 /* note: can't call glPointSize inside Begin/End :( */
58 glPointSize( 2 + i
* 5 );
61 PointVertex3f(x
, y
, z
);
74 * Top row of points is rendered conventionally with GL_POINT_SMOOTH.
75 * Bottom row is rendered with special vertex/fragment shaders (see Init()).
80 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
83 glEnable(GL_POINT_SMOOTH
);
85 glDisable(GL_POINT_SMOOTH
);
93 glTranslatef(Xpos
, Ypos
, 0);
99 glTranslatef(0, 1.2, 0);
101 DrawPoints(GL_FALSE
);
108 glTranslatef(0, -1.2, 0);
109 glUseProgram(Program
);
110 if (uViewportInv
!= -1) {
111 glUniform2f(uViewportInv
, 1.0 / WinWidth
, 1.0 / WinHeight
);
123 Reshape(int width
, int height
)
127 glViewport(0, 0, width
, height
);
128 glMatrixMode(GL_PROJECTION
);
130 glFrustum(-1.0, 1.0, -1.0, 1.0, 4.0, 30.0);
131 glMatrixMode(GL_MODELVIEW
);
133 glTranslatef(0.0f
, 0.0f
, -20.0f
);
138 Key(unsigned char key
, int x
, int y
)
151 glDeleteShader(FragShader
);
152 glDeleteShader(VertShader
);
153 glDeleteProgram(Program
);
154 glutDestroyWindow(Win
);
162 SpecialKey(int key
, int x
, int y
)
164 const GLfloat step
= 1/100.0;
186 /* Fragment shader: compute distance of fragment from center of point
187 * (we're using texcoords but another varying could be used).
188 * if dist > 1, discard (coverage==0)
189 * if dist < k, coverage = 1
190 * else, coverage = func(dist)
191 * Note: length() uses sqrt() and may be expensive. The distance could
192 * be squared instead (with adjustments to the threshold (k) test)
194 static const char *fragShaderText
=
197 " float k = 2.0 / gl_Point.size; \n"
198 " float d = length(gl_TexCoord[0].xy); \n"
201 " if (d < 1.0 - k) \n"
204 " cover = (1.0 - d) * 0.5 * gl_Point.size; \n"
205 " gl_FragColor.rgb = gl_Color.rgb; \n"
206 " gl_FragColor.a = cover; \n"
208 /* Vertex shader: compute new vertex position based on incoming vertex pos,
209 * texcoords, point size, and inverse viewport scale factor.
210 * Note: should compute point size attenuation here too.
212 static const char *vertShaderText
=
213 "uniform vec2 viewportInv; \n"
215 " vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
216 " gl_Position.xy = pos.xy + gl_MultiTexCoord0.xy * viewportInv \n"
217 " * gl_Point.size * pos.w; \n"
218 " gl_Position.zw = pos.zw; \n"
219 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
220 " gl_FrontColor = gl_Color; \n"
223 if (!ShadersSupported())
226 VertShader
= CompileShaderText(GL_VERTEX_SHADER
, vertShaderText
);
227 FragShader
= CompileShaderText(GL_FRAGMENT_SHADER
, fragShaderText
);
228 Program
= LinkShaders(VertShader
, FragShader
);
230 glUseProgram(Program
);
232 uViewportInv
= glGetUniformLocation(Program
, "viewportInv");
236 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
241 main(int argc
, char *argv
[])
243 glutInit(&argc
, argv
);
244 glutInitWindowSize(WinWidth
, WinHeight
);
245 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
246 Win
= glutCreateWindow(argv
[0]);
248 glutReshapeFunc(Reshape
);
249 glutKeyboardFunc(Key
);
250 glutSpecialFunc(SpecialKey
);
251 glutDisplayFunc(Redisplay
);