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
45 #include "shaderutil.h"
48 #define MAX_SAMPLERS 128
51 static const char *Demo
= "samplers";
53 static GLuint Program
;
54 static GLint NumSamplers
;
55 static GLuint Textures
[MAX_SAMPLERS
];
56 static GLfloat Xrot
= 0.0, Yrot
= .0, Zrot
= 0.0;
57 static GLfloat EyeDist
= 10;
58 static GLboolean Anim
= GL_FALSE
;
62 DrawPolygon(GLfloat size
)
68 glMultiTexCoord2f(GL_TEXTURE0
, 0, 0);
69 glVertex2f(-size
, -size
);
71 glMultiTexCoord2f(GL_TEXTURE0
, 1, 0);
72 glVertex2f( size
, -size
);
74 glMultiTexCoord2f(GL_TEXTURE0
, 1, 1);
75 glVertex2f( size
, size
);
77 glMultiTexCoord2f(GL_TEXTURE0
, 0, 1);
78 glVertex2f(-size
, size
);
88 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
91 glTranslatef(0.0, 0.0, -EyeDist
);
92 glRotatef(Zrot
, 0, 0, 1);
93 glRotatef(Yrot
, 0, 1, 0);
94 glRotatef(Xrot
, 1, 0, 0);
107 GLfloat t
= 0.05 * glutGet(GLUT_ELAPSED_TIME
);
114 key(unsigned char k
, int x
, int y
)
145 specialkey(int key
, int x
, int y
)
168 /* new window size or exposure */
170 Reshape(int width
, int height
)
172 GLfloat ar
= (float) width
/ (float) height
;
173 glViewport(0, 0, (GLint
)width
, (GLint
)height
);
174 glMatrixMode(GL_PROJECTION
);
176 glFrustum(-2.0*ar
, 2.0*ar
, -2.0, 2.0, 4.0, 100.0);
177 glMatrixMode(GL_MODELVIEW
);
185 const GLint size
= MAX_SAMPLERS
;
187 GLenum filter
= GL_NEAREST
;
191 texImage
= (GLubyte
*) malloc(size
* size
* 4);
193 glGenTextures(NumSamplers
, Textures
);
195 /* size of texels stripe */
196 stripeSize
= size
/ NumSamplers
;
198 /* create a texture for each sampler */
199 for (s
= 0; s
< NumSamplers
; s
++) {
201 GLubyte intensity
= 31 + s
* (256-32) / (NumSamplers
- 1);
203 printf("Texture %d: color = %d, %d, %d\n", s
,
204 (int) intensity
, 0, (int) intensity
);
206 /* initialize the texture to black */
207 memset(texImage
, 0, size
* size
* 4);
209 /* set a stripe of texels to the intensity value */
210 ypos
= s
* stripeSize
;
211 for (y
= 0; y
< stripeSize
; y
++) {
212 for (x
= 0; x
< size
; x
++) {
213 GLint k
= 4 * ((ypos
+ y
) * size
+ x
);
214 texImage
[k
+ 0] = intensity
;
215 texImage
[k
+ 1] = intensity
;
217 texImage
[k
+ 3] = 255;
221 glActiveTexture(GL_TEXTURE0
+ s
);
222 glBindTexture(GL_TEXTURE_2D
, Textures
[s
]);
223 gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, size
, size
,
224 GL_RGBA
, GL_UNSIGNED_BYTE
, texImage
);
226 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
227 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
228 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, filter
);
229 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, filter
);
237 * Generate a fragment shader that uses the given number of samplers.
240 GenFragmentShader(GLint numSamplers
)
242 const int maxLen
= 10 * 1000;
243 char *prog
= (char *) malloc(maxLen
);
247 p
+= sprintf(p
, "// Generated fragment shader:\n");
248 #ifndef SAMPLERS_ARRAY
249 for (s
= 0; s
< numSamplers
; s
++) {
250 p
+= sprintf(p
, "uniform sampler2D tex%d;\n", s
);
253 p
+= sprintf(p
, "uniform sampler2D tex[%d];\n", numSamplers
);
255 p
+= sprintf(p
, "void main()\n");
256 p
+= sprintf(p
, "{\n");
257 p
+= sprintf(p
, " vec4 color = vec4(0.0);\n");
258 for (s
= 0; s
< numSamplers
; s
++) {
259 #ifndef SAMPLERS_ARRAY
260 p
+= sprintf(p
, " color += texture2D(tex%d, gl_TexCoord[0].xy);\n", s
);
262 p
+= sprintf(p
, " color += texture2D(tex[%d], gl_TexCoord[0].xy);\n", s
);
265 p
+= sprintf(p
, " gl_FragColor = color;\n");
266 p
+= sprintf(p
, "}\n");
268 assert(p
- prog
< maxLen
);
273 /** Create & bind shader program */
277 GLuint fragShader
, vertShader
, program
;
278 const char *vertShaderText
=
281 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
282 " gl_Position = ftransform(); \n"
284 char *fragShaderText
= GenFragmentShader(NumSamplers
);
286 printf("%s", fragShaderText
);
288 vertShader
= CompileShaderText(GL_VERTEX_SHADER
, vertShaderText
);
289 fragShader
= CompileShaderText(GL_FRAGMENT_SHADER
, fragShaderText
);
291 program
= LinkShaders(vertShader
, fragShader
);
293 glUseProgram_func(program
);
295 free(fragShaderText
);
306 Program
= CreateProgram();
308 /* init sampler uniforms */
309 for (s
= 0; s
< NumSamplers
; s
++) {
313 #ifndef SAMPLERS_ARRAY
314 sprintf(uname
, "tex%d", s
);
316 sprintf(uname
, "tex[%d]", s
);
318 loc
= glGetUniformLocation_func(Program
, uname
);
321 glUniform1i_func(loc
, s
);
329 if (!ShadersSupported()) {
330 printf("GLSL not supported!\n");
334 printf("GL_RENDERER = %s\n", (const char *) glGetString(GL_RENDERER
));
338 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &NumSamplers
);
339 if (NumSamplers
> MAX_SAMPLERS
)
340 NumSamplers
= MAX_SAMPLERS
;
341 printf("Testing %d samplers\n", NumSamplers
);
346 glClearColor(.6, .6, .9, 0);
347 glColor3f(1.0, 1.0, 1.0);
349 printf("Each color corresponds to a separate sampler/texture.\n");
354 main(int argc
, char *argv
[])
356 glutInit(&argc
, argv
);
357 glutInitWindowSize(500, 400);
358 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
359 glutCreateWindow(Demo
);
360 glutReshapeFunc(Reshape
);
361 glutKeyboardFunc(key
);
362 glutSpecialFunc(specialkey
);
363 glutDisplayFunc(draw
);