blob: c6e0b10b49d77dc8373bfacc99bd3ab70537fe0b [file] [log] [blame]
Brian Paul49789532008-05-20 11:01:17 -06001/**
2 * Test multi-texturing with GL shading language.
3 *
4 * Copyright (C) 2008 Brian Paul All Rights Reserved.
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
22 */
23
24
25
26#include <assert.h>
27#include <math.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
Keith Whitwellb799af92009-06-29 14:13:58 +010031#include <GL/glew.h>
Brian Paul49789532008-05-20 11:01:17 -060032#include "GL/glut.h"
33#include "readtex.h"
34#include "extfuncs.h"
35#include "shaderutil.h"
36
37static const char *Demo = "multitex";
38
Brian Paulc0dd9122008-08-16 09:36:46 -060039static const char *VertFile = "multitex.vert";
40static const char *FragFile = "multitex.frag";
Brian Paul49789532008-05-20 11:01:17 -060041
42static const char *TexFiles[2] =
43 {
44 "../images/tile.rgb",
45 "../images/tree2.rgba"
46 };
47
48
49static GLuint Program;
50
Brian Paul8e8b25c2009-02-02 16:50:45 -070051static GLfloat Xrot = 0.0, Yrot = .0, Zrot = 0.0;
Brian Paul49789532008-05-20 11:01:17 -060052static GLfloat EyeDist = 10;
53static GLboolean Anim = GL_TRUE;
Brian Paul8e8b25c2009-02-02 16:50:45 -070054static GLboolean UseArrays = GL_TRUE;
Brian Paul891a2bd2009-05-22 13:12:28 -060055static GLboolean UseVBO = GL_TRUE;
56static GLuint VBO = 0;
Brian Paul8e8b25c2009-02-02 16:50:45 -070057
58static GLint VertCoord_attr = -1, TexCoord0_attr = -1, TexCoord1_attr = -1;
Brian Paul49789532008-05-20 11:01:17 -060059
60
61/* value[0] = tex unit */
62static struct uniform_info Uniforms[] = {
63 { "tex1", 1, GL_INT, { 0, 0, 0, 0 }, -1 },
64 { "tex2", 1, GL_INT, { 1, 0, 0, 0 }, -1 },
65 END_OF_UNIFORMS
66};
67
68
Brian Paul8e8b25c2009-02-02 16:50:45 -070069static const GLfloat Tex0Coords[4][2] = {
70 { 0.0, 0.0 }, { 2.0, 0.0 }, { 2.0, 2.0 }, { 0.0, 2.0 }
71};
72
73static const GLfloat Tex1Coords[4][2] = {
74 { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 }
75};
76
77static const GLfloat VertCoords[4][2] = {
78 { -3.0, -3.0 }, { 3.0, -3.0 }, { 3.0, 3.0 }, { -3.0, 3.0 }
79};
80
81
Brian Paul891a2bd2009-05-22 13:12:28 -060082
83static void
84SetupVertexBuffer(void)
85{
86 glGenBuffersARB_func(1, &VBO);
87 glBindBufferARB_func(GL_ARRAY_BUFFER_ARB, VBO);
88
89 glBufferDataARB_func(GL_ARRAY_BUFFER_ARB,
90 sizeof(VertCoords) +
91 sizeof(Tex0Coords) +
92 sizeof(Tex1Coords),
93 NULL,
94 GL_STATIC_DRAW_ARB);
95
96 /* non-interleaved vertex arrays */
97
98 glBufferSubDataARB_func(GL_ARRAY_BUFFER_ARB,
99 0, /* offset */
100 sizeof(VertCoords), /* size */
101 VertCoords); /* data */
102
103 glBufferSubDataARB_func(GL_ARRAY_BUFFER_ARB,
104 sizeof(VertCoords), /* offset */
105 sizeof(Tex0Coords), /* size */
106 Tex0Coords); /* data */
107
108 glBufferSubDataARB_func(GL_ARRAY_BUFFER_ARB,
109 sizeof(VertCoords) +
110 sizeof(Tex0Coords), /* offset */
111 sizeof(Tex1Coords), /* size */
112 Tex1Coords); /* data */
113
114 glBindBufferARB_func(GL_ARRAY_BUFFER_ARB, 0);
115}
116
117
Brian Paul49789532008-05-20 11:01:17 -0600118static void
Brian Paul8e8b25c2009-02-02 16:50:45 -0700119DrawPolygonArray(void)
Brian Paul49789532008-05-20 11:01:17 -0600120{
Brian Paul891a2bd2009-05-22 13:12:28 -0600121 void *vertPtr, *tex0Ptr, *tex1Ptr;
122
123 if (UseVBO) {
124 glBindBufferARB_func(GL_ARRAY_BUFFER_ARB, VBO);
125 vertPtr = (void *) 0;
126 tex0Ptr = (void *) sizeof(VertCoords);
127 tex1Ptr = (void *) (sizeof(VertCoords) + sizeof(Tex0Coords));
128 }
129 else {
130 glBindBufferARB_func(GL_ARRAY_BUFFER_ARB, 0);
131 vertPtr = VertCoords;
132 tex0Ptr = Tex0Coords;
133 tex1Ptr = Tex1Coords;
134 }
135
Brian Paul8e8b25c2009-02-02 16:50:45 -0700136 if (VertCoord_attr >= 0) {
137 glVertexAttribPointer_func(VertCoord_attr, 2, GL_FLOAT, GL_FALSE,
Brian Paul891a2bd2009-05-22 13:12:28 -0600138 0, vertPtr);
Brian Paul8e8b25c2009-02-02 16:50:45 -0700139 glEnableVertexAttribArray_func(VertCoord_attr);
140 }
141 else {
Brian Paul891a2bd2009-05-22 13:12:28 -0600142 glVertexPointer(2, GL_FLOAT, 0, vertPtr);
Brian Paul820436f2009-07-08 13:58:30 -0600143 glEnableClientState(GL_VERTEX_ARRAY);
Brian Paul8e8b25c2009-02-02 16:50:45 -0700144 }
Brian Paul49789532008-05-20 11:01:17 -0600145
Brian Paul8e8b25c2009-02-02 16:50:45 -0700146 glVertexAttribPointer_func(TexCoord0_attr, 2, GL_FLOAT, GL_FALSE,
Brian Paul891a2bd2009-05-22 13:12:28 -0600147 0, tex0Ptr);
Brian Paul8e8b25c2009-02-02 16:50:45 -0700148 glEnableVertexAttribArray_func(TexCoord0_attr);
Brian Paul49789532008-05-20 11:01:17 -0600149
Brian Paul8e8b25c2009-02-02 16:50:45 -0700150 glVertexAttribPointer_func(TexCoord1_attr, 2, GL_FLOAT, GL_FALSE,
Brian Paul891a2bd2009-05-22 13:12:28 -0600151 0, tex1Ptr);
Brian Paul8e8b25c2009-02-02 16:50:45 -0700152 glEnableVertexAttribArray_func(TexCoord1_attr);
Brian Paul49789532008-05-20 11:01:17 -0600153
Brian Paul8e8b25c2009-02-02 16:50:45 -0700154 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
Brian Paul891a2bd2009-05-22 13:12:28 -0600155
Brian Paulf742f2c2009-07-08 13:59:03 -0600156 glBindBufferARB_func(GL_ARRAY_BUFFER_ARB, 0);
Brian Paul8e8b25c2009-02-02 16:50:45 -0700157}
Brian Paul49789532008-05-20 11:01:17 -0600158
Brian Paul8e8b25c2009-02-02 16:50:45 -0700159
160static void
161DrawPolygonVert(void)
162{
163 GLuint i;
164
165 glBegin(GL_TRIANGLE_FAN);
166
167 for (i = 0; i < 4; i++) {
168 glVertexAttrib2fv_func(TexCoord0_attr, Tex0Coords[i]);
169 glVertexAttrib2fv_func(TexCoord1_attr, Tex1Coords[i]);
170
171 if (VertCoord_attr >= 0)
172 glVertexAttrib2fv_func(VertCoord_attr, VertCoords[i]);
173 else
174 glVertex2fv(VertCoords[i]);
175 }
Brian Paul49789532008-05-20 11:01:17 -0600176
177 glEnd();
Brian Paul49789532008-05-20 11:01:17 -0600178}
179
180
181static void
182draw(void)
183{
184 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
185
186 glPushMatrix(); /* modelview matrix */
187 glTranslatef(0.0, 0.0, -EyeDist);
188 glRotatef(Zrot, 0, 0, 1);
189 glRotatef(Yrot, 0, 1, 0);
190 glRotatef(Xrot, 1, 0, 0);
191
Brian Paul8e8b25c2009-02-02 16:50:45 -0700192 if (UseArrays)
193 DrawPolygonArray();
194 else
195 DrawPolygonVert();
Brian Paul49789532008-05-20 11:01:17 -0600196
197 glPopMatrix();
198
199 glutSwapBuffers();
200}
201
202
203static void
204idle(void)
205{
206 GLfloat t = 0.05 * glutGet(GLUT_ELAPSED_TIME);
207 Yrot = t;
208 glutPostRedisplay();
209}
210
211
212static void
213key(unsigned char k, int x, int y)
214{
215 (void) x;
216 (void) y;
217 switch (k) {
Brian Paul49789532008-05-20 11:01:17 -0600218 case 'a':
Brian Paul8e8b25c2009-02-02 16:50:45 -0700219 UseArrays = !UseArrays;
220 printf("Arrays: %d\n", UseArrays);
221 break;
Brian Paul891a2bd2009-05-22 13:12:28 -0600222 case 'v':
223 UseVBO = !UseVBO;
224 printf("Use VBO: %d\n", UseVBO);
225 break;
Brian Paul8e8b25c2009-02-02 16:50:45 -0700226 case ' ':
Brian Paul49789532008-05-20 11:01:17 -0600227 Anim = !Anim;
228 if (Anim)
229 glutIdleFunc(idle);
230 else
231 glutIdleFunc(NULL);
232 break;
233 case 'z':
234 EyeDist -= 0.5;
235 if (EyeDist < 3.0)
236 EyeDist = 3.0;
237 break;
238 case 'Z':
239 EyeDist += 0.5;
240 if (EyeDist > 90.0)
241 EyeDist = 90;
242 break;
243 case 27:
244 exit(0);
245 }
246 glutPostRedisplay();
247}
248
249
250static void
251specialkey(int key, int x, int y)
252{
253 GLfloat step = 2.0;
254 (void) x;
255 (void) y;
256 switch (key) {
257 case GLUT_KEY_UP:
258 Xrot += step;
259 break;
260 case GLUT_KEY_DOWN:
261 Xrot -= step;
262 break;
263 case GLUT_KEY_LEFT:
264 Yrot -= step;
265 break;
266 case GLUT_KEY_RIGHT:
267 Yrot += step;
268 break;
269 }
270 glutPostRedisplay();
271}
272
273
274/* new window size or exposure */
275static void
276Reshape(int width, int height)
277{
278 GLfloat ar = (float) width / (float) height;
279 glViewport(0, 0, (GLint)width, (GLint)height);
280 glMatrixMode(GL_PROJECTION);
281 glLoadIdentity();
282 glFrustum(-2.0*ar, 2.0*ar, -2.0, 2.0, 4.0, 100.0);
283 glMatrixMode(GL_MODELVIEW);
284 glLoadIdentity();
285}
286
287
288static void
289InitTextures(void)
290{
291 GLenum filter = GL_LINEAR;
292 int i;
293
294 for (i = 0; i < 2; i++) {
295 GLint imgWidth, imgHeight;
296 GLenum imgFormat;
297 GLubyte *image = NULL;
298
299 image = LoadRGBImage(TexFiles[i], &imgWidth, &imgHeight, &imgFormat);
300 if (!image) {
301 printf("Couldn't read %s\n", TexFiles[i]);
302 exit(0);
303 }
304
305 glActiveTexture(GL_TEXTURE0 + i);
306 glBindTexture(GL_TEXTURE_2D, 42 + i);
307 gluBuild2DMipmaps(GL_TEXTURE_2D, 4, imgWidth, imgHeight,
308 imgFormat, GL_UNSIGNED_BYTE, image);
309 free(image);
310
311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
314 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
315 }
316}
317
318
319static GLuint
320CreateProgram(const char *vertProgFile, const char *fragProgFile,
321 struct uniform_info *uniforms)
322{
323 GLuint fragShader, vertShader, program;
324
325 vertShader = CompileShaderFile(GL_VERTEX_SHADER, vertProgFile);
326 fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, fragProgFile);
327 assert(vertShader);
328 program = LinkShaders(vertShader, fragShader);
329
330 glUseProgram_func(program);
331
332 InitUniforms(program, uniforms);
333
Brian Paul891a2bd2009-05-22 13:12:28 -0600334 VertCoord_attr = glGetAttribLocation_func(program, "VertCoord");
335 if (VertCoord_attr > 0) {
336 /* We want the VertCoord attrib to have position zero so that
337 * the call to glVertexAttrib(0, xyz) triggers vertex processing.
338 * Otherwise, if TexCoord0 or TexCoord1 gets position 0 we'd have
339 * to set that attribute last (which is a PITA to manage).
340 */
341 glBindAttribLocation_func(program, 0, "VertCoord");
342 /* re-link */
343 glLinkProgram_func(program);
344 /* VertCoord_attr should be zero now */
345 VertCoord_attr = glGetAttribLocation_func(program, "VertCoord");
346 assert(VertCoord_attr == 0);
347 }
348
Brian Paul8e8b25c2009-02-02 16:50:45 -0700349 TexCoord0_attr = glGetAttribLocation_func(program, "TexCoord0");
350 TexCoord1_attr = glGetAttribLocation_func(program, "TexCoord1");
Brian Paul891a2bd2009-05-22 13:12:28 -0600351
Brian Paul8e8b25c2009-02-02 16:50:45 -0700352 printf("TexCoord0_attr = %d\n", TexCoord0_attr);
353 printf("TexCoord1_attr = %d\n", TexCoord1_attr);
354 printf("VertCoord_attr = %d\n", VertCoord_attr);
355
Brian Paul49789532008-05-20 11:01:17 -0600356 return program;
357}
358
359
360static void
361InitPrograms(void)
362{
363 Program = CreateProgram(VertFile, FragFile, Uniforms);
364}
365
366
367static void
368InitGL(void)
369{
370 const char *version = (const char *) glGetString(GL_VERSION);
371
372 if (version[0] != '2' || version[1] != '.') {
373 printf("Warning: this program expects OpenGL 2.0\n");
374 /*exit(1);*/
375 }
376 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
Brian Paul891a2bd2009-05-22 13:12:28 -0600377 printf("Usage:\n");
378 printf(" a - toggle arrays vs. immediate mode rendering\n");
379 printf(" v - toggle VBO usage for array rendering\n");
380 printf(" z/Z - change viewing distance\n");
381 printf(" SPACE - toggle animation\n");
382 printf(" Esc - exit\n");
Brian Paul49789532008-05-20 11:01:17 -0600383 GetExtensionFuncs();
384
385 InitTextures();
386 InitPrograms();
387
Brian Paul891a2bd2009-05-22 13:12:28 -0600388 SetupVertexBuffer();
389
Brian Paul49789532008-05-20 11:01:17 -0600390 glEnable(GL_DEPTH_TEST);
391
392 glClearColor(.6, .6, .9, 0);
393 glColor3f(1.0, 1.0, 1.0);
394}
395
396
397int
398main(int argc, char *argv[])
399{
400 glutInit(&argc, argv);
401 glutInitWindowSize(500, 400);
402 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
403 glutCreateWindow(Demo);
Keith Whitwellb799af92009-06-29 14:13:58 +0100404 glewInit();
Brian Paul49789532008-05-20 11:01:17 -0600405 glutReshapeFunc(Reshape);
406 glutKeyboardFunc(key);
407 glutSpecialFunc(specialkey);
408 glutDisplayFunc(draw);
409 if (Anim)
410 glutIdleFunc(idle);
411 InitGL();
412 glutMainLoop();
413 return 0;
414}