1/* 2 * (C) Copyright IBM Corporation 2007 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * on the rights to use, copy, modify, merge, publish, distribute, sub 9 * license, and/or sell copies of the Software, and to permit persons to whom 10 * the Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25/** 26 * \file arraytexture.c 27 * 28 * 29 * \author Ian Romanick <idr@us.ibm.com> 30 */ 31 32#include <assert.h> 33#include <stdlib.h> 34#include <stdio.h> 35#include <string.h> 36#include <math.h> 37#include <GL/glew.h> 38#include "glut_wrap.h" 39 40#if !defined(GL_EXT_texture_array) && !defined(GL_MESA_texture_array) 41# error "This demo requires enums for either GL_EXT_texture_array or GL_MESA_texture_array to build." 42#endif 43 44#include "readtex.h" 45 46#define GL_CHECK_ERROR() \ 47 do { \ 48 GLenum err = glGetError(); \ 49 if (err) { \ 50 printf("%s:%u: %s (0x%04x)\n", __FILE__, __LINE__, \ 51 gluErrorString(err), err); \ 52 } \ 53 } while (0) 54 55static const char *const textures[] = { 56 DEMOS_DATA_DIR "girl.rgb", 57 DEMOS_DATA_DIR "girl2.rgb", 58 DEMOS_DATA_DIR "arch.rgb", 59 DEMOS_DATA_DIR "s128.rgb", 60 61 DEMOS_DATA_DIR "tree3.rgb", 62 DEMOS_DATA_DIR "bw.rgb", 63 DEMOS_DATA_DIR "reflect.rgb", 64 DEMOS_DATA_DIR "wrs_logo.rgb", 65 NULL 66}; 67 68static const char frag_prog[] = 69 "!!ARBfp1.0\n" 70 "OPTION MESA_texture_array;\n" 71 "TEX result.color, fragment.texcoord[0], texture[0], ARRAY2D;\n" 72 "END\n"; 73 74static GLfloat Xrot = 0, Yrot = -30, Zrot = 0; 75static GLfloat texZ = 0.0; 76static GLfloat texZ_dir = 0.01; 77static GLint num_layers; 78 79 80static void 81PrintString(const char *s) 82{ 83 while (*s) { 84 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 85 s++; 86 } 87} 88 89 90static void Idle(void) 91{ 92 static int lastTime = 0; 93 int t = glutGet(GLUT_ELAPSED_TIME); 94 95 if (lastTime == 0) 96 lastTime = t; 97 else if (t - lastTime < 10) 98 return; 99 100 lastTime = t; 101 102 texZ += texZ_dir; 103 if ((texZ < 0.0) || ((GLint) texZ > num_layers)) { 104 texZ_dir = -texZ_dir; 105 } 106 107 glutPostRedisplay(); 108} 109 110 111static void Display(void) 112{ 113 char str[100]; 114 115 glClear(GL_COLOR_BUFFER_BIT); 116 117 glMatrixMode(GL_PROJECTION); 118 glLoadIdentity(); 119 glOrtho(-1, 1, -1, 1, -1, 1); 120 glMatrixMode(GL_MODELVIEW); 121 glLoadIdentity(); 122 123 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); 124 glColor3f(1,1,1); 125 glRasterPos3f(-0.9, -0.9, 0.0); 126 sprintf(str, "Texture Z coordinate = %4.1f", texZ); 127 PrintString(str); 128 129 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 1); 130 GL_CHECK_ERROR(); 131 glEnable(GL_TEXTURE_2D_ARRAY_EXT); 132 GL_CHECK_ERROR(); 133 134 glMatrixMode(GL_PROJECTION); 135 glLoadIdentity(); 136 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); 137 glMatrixMode(GL_MODELVIEW); 138 glLoadIdentity(); 139 glTranslatef(0.0, 0.0, -8.0); 140 141 glPushMatrix(); 142 glRotatef(Xrot, 1, 0, 0); 143 glRotatef(Yrot, 0, 1, 0); 144 glRotatef(Zrot, 0, 0, 1); 145 146 glBegin(GL_QUADS); 147 glTexCoord3f(0.0, 0.0, texZ); glVertex2f(-1.0, -1.0); 148 glTexCoord3f(2.0, 0.0, texZ); glVertex2f(1.0, -1.0); 149 glTexCoord3f(2.0, 2.0, texZ); glVertex2f(1.0, 1.0); 150 glTexCoord3f(0.0, 2.0, texZ); glVertex2f(-1.0, 1.0); 151 glEnd(); 152 153 glPopMatrix(); 154 155 glDisable(GL_TEXTURE_2D_ARRAY_EXT); 156 GL_CHECK_ERROR(); 157 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); 158 GL_CHECK_ERROR(); 159 160 glutSwapBuffers(); 161} 162 163 164static void Reshape(int width, int height) 165{ 166 glViewport(0, 0, width, height); 167} 168 169 170static void Key(unsigned char key, int x, int y) 171{ 172 (void) x; 173 (void) y; 174 switch (key) { 175 case 27: 176 exit(0); 177 break; 178 } 179 glutPostRedisplay(); 180} 181 182 183static void SpecialKey(int key, int x, int y) 184{ 185 const GLfloat step = 3.0; 186 (void) x; 187 (void) y; 188 switch (key) { 189 case GLUT_KEY_UP: 190 Xrot -= step; 191 break; 192 case GLUT_KEY_DOWN: 193 Xrot += step; 194 break; 195 case GLUT_KEY_LEFT: 196 Yrot -= step; 197 break; 198 case GLUT_KEY_RIGHT: 199 Yrot += step; 200 break; 201 } 202 glutPostRedisplay(); 203} 204 205 206static int FindLine(const char *program, int position) 207{ 208 int i, line = 1; 209 for (i = 0; i < position; i++) { 210 if (program[i] == '\n') 211 line++; 212 } 213 return line; 214} 215 216 217static void 218compile_fragment_program(GLuint id, const char *prog) 219{ 220 int errorPos; 221 int err; 222 223 err = glGetError(); 224 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, id); 225 glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 226 strlen(prog), (const GLubyte *) prog); 227 228 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos); 229 err = glGetError(); 230 if (err != GL_NO_ERROR || errorPos != -1) { 231 int l = FindLine(prog, errorPos); 232 233 printf("Fragment Program Error (err=%d, pos=%d line=%d): %s\n", 234 err, errorPos, l, 235 (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB)); 236 exit(0); 237 } 238} 239 240 241static void require_extension(const char *ext) 242{ 243 if (!glutExtensionSupported(ext)) { 244 printf("Sorry, %s not supported by this renderer.\n", ext); 245 exit(1); 246 } 247} 248 249 250static void Init(void) 251{ 252 const char *const ver_string = (const char *) glGetString(GL_VERSION); 253 unsigned i; 254 255 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 256 printf("GL_VERSION = %s\n", ver_string); 257 258 require_extension("GL_ARB_fragment_program"); 259 require_extension("GL_MESA_texture_array"); 260 require_extension("GL_SGIS_generate_mipmap"); 261 262 for (num_layers = 0; textures[num_layers] != NULL; num_layers++) 263 /* empty */ ; 264 265 glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 1); 266 glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_RGB8, 267 256, 256, num_layers, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); 268 GL_CHECK_ERROR(); 269 270 glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_GENERATE_MIPMAP_SGIS, 271 GL_TRUE); 272 273 for (i = 0; textures[i] != NULL; i++) { 274 GLint width, height; 275 GLenum format; 276 277 GLubyte *image = LoadRGBImage(textures[i], &width, &height, &format); 278 if (!image) { 279 printf("Error: could not load texture image %s\n", textures[i]); 280 exit(1); 281 } 282 283 /* resize to 256 x 256 */ 284 if (width != 256 || height != 256) { 285 GLubyte *newImage = malloc(256 * 256 * 4); 286 gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image, 287 256, 256, GL_UNSIGNED_BYTE, newImage); 288 free(image); 289 image = newImage; 290 } 291 292 glTexSubImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, 293 0, 0, i, 256, 256, 1, 294 format, GL_UNSIGNED_BYTE, image); 295 free(image); 296 } 297 GL_CHECK_ERROR(); 298 299 glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_S, GL_REPEAT); 300 glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_T, GL_REPEAT); 301 glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 302 303 glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 304 GL_CHECK_ERROR(); 305 glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 306 GL_CHECK_ERROR(); 307 308 compile_fragment_program(1, frag_prog); 309 GL_CHECK_ERROR(); 310} 311 312 313int main(int argc, char *argv[]) 314{ 315 glutInit(&argc, argv); 316 glutInitWindowPosition(0, 0); 317 glutInitWindowSize(350, 350); 318 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 319 glutCreateWindow("Array texture test"); 320 glewInit(); 321 glutReshapeFunc(Reshape); 322 glutKeyboardFunc(Key); 323 glutSpecialFunc(SpecialKey); 324 glutDisplayFunc(Display); 325 glutIdleFunc(Idle); 326 Init(); 327 glutMainLoop(); 328 return 0; 329} 330