2 # This code was created by Jeff Molofee '99
3 # (ported to SDL by Sam Lantinga '2000)
4 # (ported to Perl/SDL by Wayne Keenan '2000)
6 # If you've found this code useful, please let me know.
8 # Visit me at www.demonews.com/hosted/nehe
23 my $arg_screen_width =640;
24 my $arg_screen_height=512;
28 "width:i" => \$arg_screen_width,
29 "height:i" => \$arg_screen_height,
30 "fullscreen!" => \$arg_fullscreen,
34 ############################################################
38 my $xrot=0; # x rotation
39 my $yrot=0; # y rotation
40 my $xspeed=0; # x rotation speed
41 my $yspeed=0; # y rotation speed
43 my $z=-5.0; # depth into the screen.
45 my $filter = 1; # Which Filter To Use (nearest/linear/mipmapped) */
49 print STDERR "Use b to toggle blend, page up/down to zoom, and arrow keys to rotate\n";
58 my $vidmode_flags= SDL_OPENGL;
60 $vidmode_flags|= SDL_FULLSCREEN if $arg_fullscreen;
62 my $app = new SDL::App ( -title => "Jeff Molofee's GL Code Tutorial ... NeHe '99",
64 -flags => $vidmode_flags,
65 -width => $arg_screen_width,
66 -height =>$arg_screen_height,
72 my $event = new SDL::Event;
73 $event->set(SDL_SYSWMEVENT,SDL_IGNORE);
75 InitGL($arg_screen_width, $arg_screen_height);
77 glEnable(GL_BLEND); # Turn Blending On
78 glEnable(GL_LIGHTING);
79 glDisable(GL_DEPTH_TEST); # Turn Depth Testing Off
91 $done = 1 if ( $event->type == SDL_QUIT ) ;
93 if ( $event->type == SDL_KEYDOWN )
95 my $key= $event->key_sym;
97 $done = 1 if ( $key == SDLK_ESCAPE ) ;
101 printf("Filter was: %d\n", $filter);
102 $filter = 1+(($filter) % 3) ;
103 printf("Filter is now: %d\n", $filter);
108 printf("Blend was: %d\n", $blend);
109 $blend = $blend ? 0 : 1;
110 printf("Blend is now: %d\n", $blend);
114 glEnable(GL_BLEND); # Turn Blending On
115 glEnable(GL_LIGHTING);
116 glDisable(GL_DEPTH_TEST); # Turn Depth Testing Off
120 glDisable(GL_BLEND); # Turn Blending Off
121 glDisable(GL_LIGHTING);
122 glEnable(GL_DEPTH_TEST); # Turn Depth Testing On
126 $z-=0.02 if ( $key == SDLK_PAGEUP );
127 $z+=0.02 if ( $key == SDLK_PAGEDOWN );
128 $xspeed+=0.02 if ( $key == SDLK_UP );
129 $xspeed-=0.02 if ( $key == SDLK_DOWN );
130 $yspeed-=0.01 if ( $key == SDLK_LEFT );
131 $yspeed+=0.01 if ( $key == SDLK_RIGHT );
142 #########################################################################
143 #Pretty much in original form, but 'Perlised'
150 my ($Width, $Height) = @_;
152 glViewport(0, 0, $Width, $Height);
154 LoadGLTextures(); # Load The Texture(s)
156 glEnable(GL_TEXTURE_2D); # Enable Texture Mapping
159 glClearColor(0.0, 0.0, 0.0, 0.0); # This Will Clear The Background Color To Black
160 glClearDepth(1.0); # Enables Clearing Of The Depth Buffer
161 glDepthFunc(GL_LESS); # The Type Of Depth Test To Do
162 glEnable(GL_DEPTH_TEST); # Enables Depth Testing
163 glShadeModel(GL_SMOOTH); # Enables Smooth Color Shading
165 glMatrixMode(GL_PROJECTION);
166 glLoadIdentity(); # Reset The Projection Matrix
168 gluPerspective(45.0, $Width/$Height, 0.1, 100.0); # Calculate The Aspect Ratio Of The Window
170 glMatrixMode(GL_MODELVIEW);
173 my $LightAmbient = [ 0.5, 0.5, 0.5, 1.0 ]; # white ambient light at half intensity (rgba) */
175 my $LightDiffuse = [ 1.0, 1.0, 1.0, 1.0 ]; # super bright, full intensity diffuse light. */
177 my $LightPosition = [ 0.0 , 0.0, 2.0, 1.0 ]; # position of light (x, y, z, (position of light)) */
181 #setup light number 1
182 glLight(GL_LIGHT1, GL_AMBIENT, @$LightAmbient); # add lighting. (ambient)
183 glLight(GL_LIGHT1, GL_DIFFUSE, @$LightDiffuse); # add lighting. (diffuse).
184 glLight(GL_LIGHT1, GL_POSITION,@$LightPosition); # set light position.
185 glEnable(GL_LIGHT1); # turn light 1 on.
186 #/* setup blending */
187 glBlendFunc(GL_SRC_ALPHA,GL_ONE); # Set The Blending Function For Translucency
188 glColor(1.0, 1.0, 1.0, 0.5);
195 # The main drawing function.
198 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); # Clear The Screen And The Depth Buffer
199 glLoadIdentity(); # Reset The View
201 glTranslate(0.0,0.0,$z); # move z units out from the screen.
203 glRotate($xrot,1.0,0.0,0.0); # Rotate On The X Axis
204 glRotate($yrot,0.0,1.0,0.0); # Rotate On The Y Axis
206 glBindTexture(GL_TEXTURE_2D, $filter); # choose the texture to use.
208 glBegin(GL_QUADS); # begin drawing a cube
210 # Front Face (note that the texture's corners have to match the quad's corners)
211 glNormal( 0.0, 0.0, 1.0); # front face points out of the screen on z.
212 glTexCoord(0.0, 0.0); glVertex(-1.0, -1.0, 1.0); # Bottom Left Of The Texture and Quad
213 glTexCoord(1.0, 0.0); glVertex( 1.0, -1.0, 1.0); # Bottom Right Of The Texture and Quad
214 glTexCoord(1.0, 1.0); glVertex( 1.0, 1.0, 1.0); # Top Right Of The Texture and Quad
215 glTexCoord(0.0, 1.0); glVertex(-1.0, 1.0, 1.0); # Top Left Of The Texture and Quad
218 glNormal( 0.0, 0.0,-1.0); # back face points into the screen on z.
219 glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0, -1.0); # Bottom Right Of The Texture and Quad
220 glTexCoord(1.0, 1.0); glVertex(-1.0, 1.0, -1.0); # Top Right Of The Texture and Quad
221 glTexCoord(0.0, 1.0); glVertex( 1.0, 1.0, -1.0); # Top Left Of The Texture and Quad
222 glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0, -1.0); # Bottom Left Of The Texture and Quad
225 glNormal( 0.0, 1.0, 0.0); # top face points up on y.
226 glTexCoord(0.0, 1.0); glVertex(-1.0, 1.0, -1.0); # Top Left Of The Texture and Quad
227 glTexCoord(0.0, 0.0); glVertex(-1.0, 1.0, 1.0); # Bottom Left Of The Texture and Quad
228 glTexCoord(1.0, 0.0); glVertex( 1.0, 1.0, 1.0); # Bottom Right Of The Texture and Quad
229 glTexCoord(1.0, 1.0); glVertex( 1.0, 1.0, -1.0); # Top Right Of The Texture and Quad
232 glNormal( 0.0, -1.0, 0.0); # bottom face points down on y.
233 glTexCoord(1.0, 1.0); glVertex(-1.0, -1.0, -1.0); # Top Right Of The Texture and Quad
234 glTexCoord(0.0, 1.0); glVertex( 1.0, -1.0, -1.0); # Top Left Of The Texture and Quad
235 glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0, 1.0); # Bottom Left Of The Texture and Quad
236 glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0, 1.0); # Bottom Right Of The Texture and Quad
239 glNormal( 1.0, 0.0, 0.0); # right face points right on x.
240 glTexCoord(1.0, 0.0); glVertex( 1.0, -1.0, -1.0); # Bottom Right Of The Texture and Quad
241 glTexCoord(1.0, 1.0); glVertex( 1.0, 1.0, -1.0); # Top Right Of The Texture and Quad
242 glTexCoord(0.0, 1.0); glVertex( 1.0, 1.0, 1.0); # Top Left Of The Texture and Quad
243 glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0, 1.0); # Bottom Left Of The Texture and Quad
246 glNormal(-1.0, 0.0, 0.0); # left face points left on x.
247 glTexCoord(0.0, 0.0); glVertex(-1.0, -1.0, -1.0); # Bottom Left Of The Texture and Quad
248 glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0, 1.0); # Bottom Right Of The Texture and Quad
249 glTexCoord(1.0, 1.0); glVertex(-1.0, 1.0, 1.0); # Top Right Of The Texture and Quad
250 glTexCoord(0.0, 1.0); glVertex(-1.0, 1.0, -1.0); # Top Left Of The Texture and Quad
252 glEnd(); # done with the polygon.
254 $xrot+=$xspeed; # X Axis Rotation
255 $yrot+=$yspeed; # Y Axis Rotation
269 my ($pixels, $width, $height, $size)=ImageLoad("Data/glass.bmp");
275 # texture 1 (poor quality scaling)
276 glBindTexture(GL_TEXTURE_2D, 1); # 2d texture (x and y size)
278 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); # cheap scaling when image bigger than texture
279 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); # cheap scaling when image smalled than texture
281 # 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
282 # border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
283 #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
285 glTexImage2D(GL_TEXTURE_2D,
286 0, #level (0 normal, heighr is form mip-mapping)
287 3, #internal format (3=GL_RGB)
290 GL_RGB, #format RGB color data
291 GL_UNSIGNED_BYTE, #unsigned bye data
292 $pixels); #ptr to texture data
296 # texture 2 (linear scaling)
297 glBindTexture(GL_TEXTURE_2D, 2); # 2d texture (x and y size)
298 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); # scale linearly when image bigger than texture
299 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); # scale linearly when image smalled than texture
300 #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
302 glTexImage2D(GL_TEXTURE_2D,
303 0, #level (0 normal, heighr is form mip-mapping)
304 3, #internal format (3=GL_RGB)
307 GL_RGB, #format RGB color data
308 GL_UNSIGNED_BYTE, #unsigned bye data
309 $pixels); #ptr to texture data
314 # texture 3 (mipmapped scaling)
315 glBindTexture(GL_TEXTURE_2D, 3); # 2d texture (x and y size)
316 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); # scale linearly when image bigger than texture
317 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); # scale linearly + mipmap when image smalled than texture
318 #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
320 glTexImage2D(GL_TEXTURE_2D,
321 0, #level (0 normal, heighr is form mip-mapping)
322 3, #internal format (3=GL_RGB)
325 GL_RGB, #format RGB color data
326 GL_UNSIGNED_BYTE, #unsigned bye data
327 $pixels); #ptr to texture data
329 # 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data.
330 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, $width, $height, GL_RGB, GL_UNSIGNED_BYTE, $pixels);
332 my $glerr=glGetError();
333 die "Problem setting up 2d Texture (dimensions not a power of 2?)):".gluErrorString($glerr)."\n" if $glerr;
347 #somthing needs to keep the ref count alive for objects which represents data in C space (they have no ref count):
354 my $surface = new SDL::Surface( -name => $filename); #makes use of SDL: BMP loader.
357 my $width=$surface->width();
358 my $height=$surface->height();
359 my $bytespp= $surface->bytes_per_pixel();
360 my $size= $width*$height*$bytespp;
362 my $surface_pixels=$surface->pixels();
363 my $surface_size=$width*$height*$surface->bytes_per_pixel();
364 my $raw_pixels = reverse $surface_pixels;
368 #do a conversion (the pixel data is accessable as a simple string)
370 my $pixels=$raw_pixels;
371 my $pre_conv= $pixels;
373 for (my $y=0; $y< $height; $y++)
375 my $y_pos=$y*$width*$bytespp; #calculate offset into the image (a string)
376 my $row=substr ($pre_conv, $y_pos, $width*$bytespp); #extract 1 pixel row
377 $row =~ s/\G(.)(.)(.)/$3$2$1/gms; #turn the BMP BGR order into OpenGL RGB order;
378 $new_pixels.= reverse $row;
381 $raw_pixels = $new_pixels; #put transformed data into C array.
382 push @ref, $raw_pixels, $surface;
384 #we could have created another SDL surface frm the '$raw_pixel's... oh well.
385 return ($raw_pixels, $width, $height, $size);