2 * Test using a geometry shader to implement wide lines.
13 #include <glad/glad.h>
14 #include "glut_wrap.h"
15 #include "shaderutil.h"
18 static GLint WinWidth
= 500, WinHeight
= 500;
20 static GLuint VertShader
, GeomShader
, FragShader
, Program
;
21 static GLboolean Anim
= GL_TRUE
;
22 static GLboolean UseGeomShader
= GL_TRUE
;
23 static GLfloat LineWidth
= 10.0;
24 static GLfloat MaxLineWidth
;
25 static GLfloat Xrot
= 0, Yrot
= 0;
26 static int uLineWidth
= -1, uInverseViewportSize
= -1;
28 static int NumPoints
= 50;
33 GLenum err
= glGetError();
35 printf("GL Error %s (0x%x) at line %d\n",
36 gluErrorString(err
), (int) err
, line
);
44 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
47 glRotatef(Xrot
, 1, 0, 0);
48 glRotatef(Yrot
, 0, 0, 1);
51 glUseProgram(Program
);
52 glUniform1f(uLineWidth
, LineWidth
);
56 glLineWidth(LineWidth
);
59 glDrawArrays(GL_LINES
, 0, NumPoints
/ 2);
70 int curTime
= glutGet(GLUT_ELAPSED_TIME
);
71 Xrot
= curTime
* 0.02;
72 Yrot
= curTime
* 0.05;
78 Reshape(int width
, int height
)
80 float ar
= (float) width
/ height
;
81 glViewport(0, 0, width
, height
);
82 glMatrixMode(GL_PROJECTION
);
84 glFrustum(-ar
, ar
, -1, 1, 3, 25);
85 glMatrixMode(GL_MODELVIEW
);
87 glTranslatef(0, 0, -10);
91 glGetFloatv(GL_VIEWPORT
, viewport
);
92 glUniform2f(uInverseViewportSize
, 1.0F
/ viewport
[2], 1.0F
/ viewport
[3]);
100 glDeleteShader(FragShader
);
101 glDeleteShader(VertShader
);
102 glDeleteShader(GeomShader
);
103 glDeleteProgram(Program
);
104 glutDestroyWindow(Win
);
109 Key(unsigned char key
, int x
, int y
)
125 UseGeomShader
= !UseGeomShader
;
126 printf("Use geometry shader? %d\n", UseGeomShader
);
132 printf("Line width: %f\n", LineWidth
);
136 if (LineWidth
> MaxLineWidth
)
137 LineWidth
= MaxLineWidth
;
138 printf("Line width: %f\n", LineWidth
);
161 glGenBuffers(1, &vbo
);
162 glBindBuffer(GL_ARRAY_BUFFER
, vbo
);
163 glBufferData(GL_ARRAY_BUFFER
, NumPoints
* sizeof(struct vert
),
164 NULL
, GL_STATIC_DRAW
);
166 v
= glMapBuffer(GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
167 for (i
= 0; i
< NumPoints
; i
++) {
168 v
[i
].color
[0] = (rand() % 1000) / 1000.0;
169 v
[i
].color
[1] = (rand() % 1000) / 1000.0;
170 v
[i
].color
[2] = (rand() % 1000) / 1000.0;
171 v
[i
].pos
[0] = ((rand() % 2000) - 1000.0) / 500.0;
172 v
[i
].pos
[1] = ((rand() % 2000) - 1000.0) / 500.0;
173 v
[i
].pos
[2] = ((rand() % 2000) - 1000.0) / 500.0;
175 glUnmapBuffer(GL_ARRAY_BUFFER
);
177 glVertexPointer(3, GL_FLOAT
, sizeof(struct vert
), (void *) 0);
178 glEnable(GL_VERTEX_ARRAY
);
179 glColorPointer(3, GL_FLOAT
, sizeof(struct vert
), (void *) sizeof(float[3]));
180 glEnable(GL_COLOR_ARRAY
);
187 static const char *fragShaderText
=
190 " gl_FragColor = gl_Color; \n"
192 static const char *vertShaderText
=
195 " gl_FrontColor = gl_Color; \n"
196 " gl_Position = ftransform(); \n"
198 static const char *geomShaderText
=
200 "#extension GL_ARB_geometry_shader4: enable \n"
201 "uniform vec2 InverseViewportSize; \n"
202 "uniform float LineWidth; \n"
205 " vec4 pos0 = gl_PositionIn[0]; \n"
206 " vec4 pos1 = gl_PositionIn[1]; \n"
207 " vec4 dir = abs(pos1 - pos0); \n"
208 " vec2 d0 = vec2(LineWidth * pos0.w) * InverseViewportSize; \n"
209 " vec2 d1 = vec2(LineWidth * pos1.w) * InverseViewportSize; \n"
210 " // this conditional could be avoided \n"
211 " if (dir.x > dir.y) { \n"
212 " // X-major line \n"
217 " // Y-major line \n"
221 " gl_FrontColor = gl_FrontColorIn[0]; \n"
222 " gl_TexCoord[0] = vec4(0, 0, 0, 1); \n"
223 " gl_Position = pos0 + vec4( d0.x, -d0.y, 0, 0); \n"
225 " gl_FrontColor = gl_FrontColorIn[1]; \n"
226 " gl_TexCoord[0] = vec4(1, 0, 0, 1); \n"
227 " gl_Position = pos1 + vec4( d1.x, -d1.y, 0, 0); \n"
229 " gl_FrontColor = gl_FrontColorIn[0]; \n"
230 " gl_TexCoord[0] = vec4(0, 1, 0, 1); \n"
231 " gl_Position = pos0 + vec4(-d0.x, d0.y, 0, 0); \n"
233 " gl_FrontColor = gl_FrontColorIn[1]; \n"
234 " gl_TexCoord[0] = vec4(1, 1, 0, 1); \n"
235 " gl_Position = pos1 + vec4(-d1.x, d1.y, 0, 0); \n"
239 if (!ShadersSupported())
242 if (!glutExtensionSupported("GL_ARB_geometry_shader4")) {
243 fprintf(stderr
, "Sorry, GL_ARB_geometry_shader4 is not supported.\n");
247 VertShader
= CompileShaderText(GL_VERTEX_SHADER
, vertShaderText
);
248 FragShader
= CompileShaderText(GL_FRAGMENT_SHADER
, fragShaderText
);
249 GeomShader
= CompileShaderText(GL_GEOMETRY_SHADER_ARB
, geomShaderText
);
252 Program
= LinkShaders3(VertShader
, GeomShader
, FragShader
);
254 CheckError(__LINE__
);
257 * The geometry shader will convert incoming lines to quads (4-vertex
260 glProgramParameteriARB(Program
, GL_GEOMETRY_INPUT_TYPE_ARB
,
262 glProgramParameteriARB(Program
, GL_GEOMETRY_OUTPUT_TYPE_ARB
,
264 glProgramParameteriARB(Program
,GL_GEOMETRY_VERTICES_OUT_ARB
, 4);
265 CheckError(__LINE__
);
267 glLinkProgramARB(Program
);
272 GetProgramiv(Program
, GL_LINK_STATUS
, &stat
);
276 GetProgramInfoLog(Program
, 1000, &len
, log
);
277 fprintf(stderr
, "Shader link error:\n%s\n", log
);
281 CheckError(__LINE__
);
283 glUseProgram(Program
);
284 CheckError(__LINE__
);
286 uInverseViewportSize
= glGetUniformLocation(Program
, "InverseViewportSize");
287 uLineWidth
= glGetUniformLocation(Program
, "LineWidth");
289 glClearColor(0.3f
, 0.3f
, 0.3f
, 0.0f
);
291 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER
));
293 assert(glIsProgram(Program
));
294 assert(glIsShader(FragShader
));
295 assert(glIsShader(VertShader
));
296 assert(glIsShader(GeomShader
));
298 glEnable(GL_DEPTH_TEST
);
302 glGetFloatv(GL_LINE_WIDTH_RANGE
, r
);
311 main(int argc
, char *argv
[])
313 glutInit(&argc
, argv
);
316 int n
= atoi(argv
[1]);
321 printf("Invalid number of points\n");
326 glutInitWindowSize(WinWidth
, WinHeight
);
327 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
328 Win
= glutCreateWindow(argv
[0]);
330 glutReshapeFunc(Reshape
);
331 glutKeyboardFunc(Key
);
332 glutDisplayFunc(Redisplay
);