2 * Exercise all available GLSL texture samplers.
4 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * We generate a fragment shader which uses the maximum number of supported
27 * For each sampler we create a separate texture. Each texture has a
28 * single strip of color at a different intensity. The fragment shader
29 * samples all the textures at the same coordinate and sums the values.
30 * The result should be a quad with rows of colors of increasing intensity
46 #include "shaderutil.h"
49 #define MAX_SAMPLERS 128
52 static const char *Demo
= "samplers";
54 static GLuint Program
;
55 static GLint NumSamplers
;
56 static GLuint Textures
[MAX_SAMPLERS
];
57 static GLfloat Xrot
= 0.0, Yrot
= .0, Zrot
= 0.0;
58 static GLfloat EyeDist
= 10;
59 static GLboolean Anim
= GL_FALSE
;
63 DrawPolygon(GLfloat size
)
69 glMultiTexCoord2f(GL_TEXTURE0
, 0, 0);
70 glVertex2f(-size
, -size
);
72 glMultiTexCoord2f(GL_TEXTURE0
, 1, 0);
73 glVertex2f( size
, -size
);
75 glMultiTexCoord2f(GL_TEXTURE0
, 1, 1);
76 glVertex2f( size
, size
);
78 glMultiTexCoord2f(GL_TEXTURE0
, 0, 1);
79 glVertex2f(-size
, size
);
89 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
92 glTranslatef(0.0, 0.0, -EyeDist
);
93 glRotatef(Zrot
, 0, 0, 1);
94 glRotatef(Yrot
, 0, 1, 0);
95 glRotatef(Xrot
, 1, 0, 0);
108 GLfloat t
= 0.05 * glutGet(GLUT_ELAPSED_TIME
);
115 key(unsigned char k
, int x
, int y
)
146 specialkey(int key
, int x
, int y
)
169 /* new window size or exposure */
171 Reshape(int width
, int height
)
173 GLfloat ar
= (float) width
/ (float) height
;
174 glViewport(0, 0, (GLint
)width
, (GLint
)height
);
175 glMatrixMode(GL_PROJECTION
);
177 glFrustum(-2.0*ar
, 2.0*ar
, -2.0, 2.0, 4.0, 100.0);
178 glMatrixMode(GL_MODELVIEW
);
186 const GLint size
= MAX_SAMPLERS
;
188 GLenum filter
= GL_NEAREST
;
192 texImage
= (GLubyte
*) malloc(size
* size
* 4);
194 glGenTextures(NumSamplers
, Textures
);
196 /* size of texels stripe */
197 stripeSize
= size
/ NumSamplers
;
199 /* create a texture for each sampler */
200 for (s
= 0; s
< NumSamplers
; s
++) {
202 GLubyte intensity
= 31 + s
* (256-32) / (NumSamplers
- 1);
204 printf("Texture %d: color = %d, %d, %d\n", s
,
205 (int) intensity
, 0, (int) intensity
);
207 /* initialize the texture to black */
208 memset(texImage
, 0, size
* size
* 4);
210 /* set a stripe of texels to the intensity value */
211 ypos
= s
* stripeSize
;
212 for (y
= 0; y
< stripeSize
; y
++) {
213 for (x
= 0; x
< size
; x
++) {
214 GLint k
= 4 * ((ypos
+ y
) * size
+ x
);
215 texImage
[k
+ 0] = intensity
;
216 texImage
[k
+ 1] = intensity
;
218 texImage
[k
+ 3] = 255;
222 glActiveTexture(GL_TEXTURE0
+ s
);
223 glBindTexture(GL_TEXTURE_2D
, Textures
[s
]);
224 gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, size
, size
,
225 GL_RGBA
, GL_UNSIGNED_BYTE
, texImage
);
227 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
228 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
229 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, filter
);
230 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, filter
);
238 * Generate a fragment shader that uses the given number of samplers.
241 GenFragmentShader(GLint numSamplers
)
243 const int maxLen
= 10 * 1000;
244 char *prog
= (char *) malloc(maxLen
);
248 p
+= sprintf(p
, "// Generated fragment shader:\n");
249 #ifndef SAMPLERS_ARRAY
250 for (s
= 0; s
< numSamplers
; s
++) {
251 p
+= sprintf(p
, "uniform sampler2D tex%d;\n", s
);
254 p
+= sprintf(p
, "uniform sampler2D tex[%d];\n", numSamplers
);
256 p
+= sprintf(p
, "void main()\n");
257 p
+= sprintf(p
, "{\n");
258 p
+= sprintf(p
, " vec4 color = vec4(0.0);\n");
259 for (s
= 0; s
< numSamplers
; s
++) {
260 #ifndef SAMPLERS_ARRAY
261 p
+= sprintf(p
, " color += texture2D(tex%d, gl_TexCoord[0].xy);\n", s
);
263 p
+= sprintf(p
, " color += texture2D(tex[%d], gl_TexCoord[0].xy);\n", s
);
266 p
+= sprintf(p
, " gl_FragColor = color;\n");
267 p
+= sprintf(p
, "}\n");
269 assert(p
- prog
< maxLen
);
274 /** Create & bind shader program */
278 GLuint fragShader
, vertShader
, program
;
279 const char *vertShaderText
=
282 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
283 " gl_Position = ftransform(); \n"
285 char *fragShaderText
= GenFragmentShader(NumSamplers
);
287 printf("%s", fragShaderText
);
289 vertShader
= CompileShaderText(GL_VERTEX_SHADER
, vertShaderText
);
290 fragShader
= CompileShaderText(GL_FRAGMENT_SHADER
, fragShaderText
);
292 program
= LinkShaders(vertShader
, fragShader
);
294 glUseProgram_func(program
);
296 free(fragShaderText
);
307 Program
= CreateProgram();
309 /* init sampler uniforms */
310 for (s
= 0; s
< NumSamplers
; s
++) {
314 #ifndef SAMPLERS_ARRAY
315 sprintf(uname
, "tex%d", s
);
317 sprintf(uname
, "tex[%d]", s
);
319 loc
= glGetUniformLocation_func(Program
, uname
);
322 glUniform1i_func(loc
, s
);
330 if (!ShadersSupported()) {
331 printf("GLSL not supported!\n");
335 printf("GL_RENDERER = %s\n", (const char *) glGetString(GL_RENDERER
));
339 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &NumSamplers
);
340 if (NumSamplers
> MAX_SAMPLERS
)
341 NumSamplers
= MAX_SAMPLERS
;
342 printf("Testing %d samplers\n", NumSamplers
);
347 glClearColor(.6, .6, .9, 0);
348 glColor3f(1.0, 1.0, 1.0);
350 printf("Each color corresponds to a separate sampler/texture.\n");
355 main(int argc
, char *argv
[])
357 glutInit(&argc
, argv
);
358 glutInitWindowSize(500, 400);
359 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
360 glutCreateWindow(Demo
);
362 glutReshapeFunc(Reshape
);
363 glutKeyboardFunc(key
);
364 glutSpecialFunc(specialkey
);
365 glutDisplayFunc(draw
);