2 # This code is based on the code by Jeff Molofee '99
3 # and ported to SDL by Sam Lantinga '2000
4 # Original ported to Perl/SDL by Wayne Keenan '2000
5 # And updated by David Goehrig '02
8 # Jeff's tutorials can be found at www.demonews.com/hosted/nehe
22 my $arg_screen_width =640;
23 my $arg_screen_height=512;
27 "width:i" => \$arg_screen_width,
28 "height:i" => \$arg_screen_height,
29 "fullscreen!" => \$arg_fullscreen,
32 ############################################################
36 my $xrot=0; # x rotation
37 my $yrot=0; # y rotation
38 my $xspeed=0; # x rotation speed
39 my $yspeed=0; # y rotation speed
41 my $z=-5.0; # depth into the screen.
43 my $filter = 1; # Which Filter To Use (nearest/linear/mipmapped) */
51 my $vidmode_flags= SDL_OPENGL;
53 $vidmode_flags|= SDL_FULLSCREEN if $arg_fullscreen;
55 my $app = new SDL::App ( -title => "Jeff Molofee's GL Code Tutorial ... NeHe '99",
57 -flags => $vidmode_flags,
58 -width => $arg_screen_width,
59 -height =>$arg_screen_height,
65 my $event = new SDL::Event;
66 $event->set(SDL_SYSWMEVENT,SDL_IGNORE);
68 InitGL($arg_screen_width, $arg_screen_height);
80 $done = 1 if ( $event->type == SDL_QUIT ) ;
83 if ( $event->type == SDL_KEYDOWN )
85 my $key= $event->key_sym;
87 $done = 1 if ( $key == SDLK_ESCAPE ) ;
92 printf("Light was: %d\n", $light);
93 $light = $light ? 0 : 1; # switch the current value of light, between 0 and 1.
94 printf("Light is now: %d\n", $light);
97 glDisable(GL_LIGHTING);
101 glEnable(GL_LIGHTING);
107 printf("Filter was: %d\n", $filter);
108 $filter = 1+(($filter) % 3) ;
109 printf("Filter is now: %d\n", $filter);
113 $z-=0.02 if ( $key == SDLK_PAGEUP );
114 $z+=0.02 if ( $key == SDLK_PAGEDOWN );
115 $xspeed+=0.02 if ( $key == SDLK_UP );
116 $xspeed-=0.02 if ( $key == SDLK_DOWN );
117 $yspeed-=0.01 if ( $key == SDLK_LEFT );
118 $yspeed+=0.01 if ( $key == SDLK_RIGHT );
129 #########################################################################
130 #Pretty much in original form, but 'Perlised'
137 my ($Width, $Height) = @_;
139 glViewport(0, 0, $Width, $Height);
141 LoadGLTextures(); # Load The Texture(s)
143 glEnable(GL_TEXTURE_2D); # Enable Texture Mapping
146 glClearColor(0.0, 0.0, 0.0, 0.0); # This Will Clear The Background Color To Black
147 glClearDepth(1.0); # Enables Clearing Of The Depth Buffer
148 glDepthFunc(GL_LESS); # The Type Of Depth Test To Do
149 glEnable(GL_DEPTH_TEST); # Enables Depth Testing
150 glShadeModel(GL_SMOOTH); # Enables Smooth Color Shading
152 glMatrixMode(GL_PROJECTION);
153 glLoadIdentity(); # Reset The Projection Matrix
155 gluPerspective(45.0, $Width/$Height, 0.1, 100.0); # Calculate The Aspect Ratio Of The Window
157 glMatrixMode(GL_MODELVIEW);
160 my $LightAmbient = [ 0.5, 0.5, 0.5, 1.0 ]; # white ambient light at half intensity (rgba) */
162 my $LightDiffuse = [ 1.0, 1.0, 1.0, 1.0 ]; # super bright, full intensity diffuse light. */
164 my $LightPosition = [ 0.0 , 0.0, 2.0, 1.0 ]; # position of light (x, y, z, (position of light)) */
169 glLight(GL_LIGHT1, GL_AMBIENT, @$LightAmbient); # add lighting. (ambient)
170 glLight(GL_LIGHT1, GL_DIFFUSE, @$LightDiffuse); # add lighting. (diffuse).
171 glLight(GL_LIGHT1, GL_POSITION,@$LightPosition); # set light position.
172 glEnable(GL_LIGHT1); # turn light 1 on.
177 # The main drawing function.
180 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); # Clear The Screen And The Depth Buffer
181 glLoadIdentity(); # Reset The View
183 glTranslate(0.0,0.0,$z); # move z units out from the screen.
185 glRotate($xrot,1.0,0.0,0.0); # Rotate On The X Axis
186 glRotate($yrot,0.0,1.0,0.0); # Rotate On The Y Axis
188 glBindTexture(GL_TEXTURE_2D, $filter); # choose the texture to use.
190 glBegin(GL_QUADS); # begin drawing a cube
192 # Front Face (note that the texture's corners have to match the quad's corners)
193 glNormal( 0.0, 0.0, 1.0); # front face points out of the screen on z.
194 glTexCoord(0.0, 0.0); glVertex(-1.0, -1.0, 1.0); # Bottom Left Of The Texture and Quad
195 glTexCoord(1.0, 0.0); glVertex( 1.0, -1.0, 1.0); # Bottom Right Of The Texture and Quad
196 glTexCoord(1.0, 1.0); glVertex( 1.0, 1.0, 1.0); # Top Right Of The Texture and Quad
197 glTexCoord(0.0, 1.0); glVertex(-1.0, 1.0, 1.0); # Top Left Of The Texture and Quad
200 glNormal( 0.0, 0.0,-1.0); # back face points into the screen on z.
201 glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0, -1.0); # Bottom Right Of The Texture and Quad
202 glTexCoord(1.0, 1.0); glVertex(-1.0, 1.0, -1.0); # Top Right Of The Texture and Quad
203 glTexCoord(0.0, 1.0); glVertex( 1.0, 1.0, -1.0); # Top Left Of The Texture and Quad
204 glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0, -1.0); # Bottom Left Of The Texture and Quad
207 glNormal( 0.0, 1.0, 0.0); # top face points up on y.
208 glTexCoord(0.0, 1.0); glVertex(-1.0, 1.0, -1.0); # Top Left Of The Texture and Quad
209 glTexCoord(0.0, 0.0); glVertex(-1.0, 1.0, 1.0); # Bottom Left Of The Texture and Quad
210 glTexCoord(1.0, 0.0); glVertex( 1.0, 1.0, 1.0); # Bottom Right Of The Texture and Quad
211 glTexCoord(1.0, 1.0); glVertex( 1.0, 1.0, -1.0); # Top Right Of The Texture and Quad
214 glNormal( 0.0, -1.0, 0.0); # bottom face points down on y.
215 glTexCoord(1.0, 1.0); glVertex(-1.0, -1.0, -1.0); # Top Right Of The Texture and Quad
216 glTexCoord(0.0, 1.0); glVertex( 1.0, -1.0, -1.0); # Top Left Of The Texture and Quad
217 glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0, 1.0); # Bottom Left Of The Texture and Quad
218 glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0, 1.0); # Bottom Right Of The Texture and Quad
221 glNormal( 1.0, 0.0, 0.0); # right face points right on x.
222 glTexCoord(1.0, 0.0); glVertex( 1.0, -1.0, -1.0); # Bottom Right Of The Texture and Quad
223 glTexCoord(1.0, 1.0); glVertex( 1.0, 1.0, -1.0); # Top Right Of The Texture and Quad
224 glTexCoord(0.0, 1.0); glVertex( 1.0, 1.0, 1.0); # Top Left Of The Texture and Quad
225 glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0, 1.0); # Bottom Left Of The Texture and Quad
228 glNormal(-1.0, 0.0, 0.0); # left face points left on x.
229 glTexCoord(0.0, 0.0); glVertex(-1.0, -1.0, -1.0); # Bottom Left Of The Texture and Quad
230 glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0, 1.0); # Bottom Right Of The Texture and Quad
231 glTexCoord(1.0, 1.0); glVertex(-1.0, 1.0, 1.0); # Top Right Of The Texture and Quad
232 glTexCoord(0.0, 1.0); glVertex(-1.0, 1.0, -1.0); # Top Left Of The Texture and Quad
234 glEnd(); # done with the polygon.
236 $xrot+=$xspeed; # X Axis Rotation
237 $yrot+=$yspeed; # Y Axis Rotation
251 my ($pixels, $width, $height, $size)=ImageLoad("Data/crate.png");
257 # texture 1 (poor quality scaling)
258 glBindTexture(GL_TEXTURE_2D, 1); # 2d texture (x and y size)
260 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); # cheap scaling when image bigger than texture
261 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); # cheap scaling when image smalled than texture
263 # 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
264 # border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
265 #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
267 glTexImage2D(GL_TEXTURE_2D,
268 0, #level (0 normal, heighr is form mip-mapping)
269 3, #internal format (3=GL_RGB)
272 GL_RGB, #format RGB color data
273 GL_UNSIGNED_BYTE, #unsigned bye data
274 $pixels); #ptr to texture data
278 # texture 2 (linear scaling)
279 glBindTexture(GL_TEXTURE_2D, 2); # 2d texture (x and y size)
280 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); # scale linearly when image bigger than texture
281 glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); # scale linearly when image smalled than texture
282 #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
284 glTexImage2D(GL_TEXTURE_2D,
285 0, #level (0 normal, heighr is form mip-mapping)
286 3, #internal format (3=GL_RGB)
289 GL_RGB, #format RGB color data
290 GL_UNSIGNED_BYTE, #unsigned bye data
291 $pixels); #ptr to texture data
296 # texture 3 (mipmapped scaling)
297 glBindTexture(GL_TEXTURE_2D, 3); # 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_MIPMAP_NEAREST); # scale linearly + mipmap 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
311 # 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data.
312 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, $width, $height, GL_RGB, GL_UNSIGNED_BYTE, $pixels);
314 my $glerr=glGetError();
315 die "Problem setting up 2d Texture (dimensions not a power of 2?)):".gluErrorString($glerr)."\n" if $glerr;
329 #somthing needs to keep the ref count alive for objects which represents data in C space (they have no ref count):
336 my $surface = new SDL::Surface( -name => $filename); #makes use of SDL: BMP loader.
339 my $width=$surface->width();
340 my $height=$surface->height();
341 my $bytespp= $surface->bytes_per_pixel();
342 my $size= $width*$height*$bytespp;
344 my $surface_pixels=$surface->pixels();
345 my $surface_size=$width*$height*$surface->bytes_per_pixel();
346 my $raw_pixels = $surface_pixels;
350 #do a conversion (the pixel data is accessable as a simple string)
352 my $pixels=$raw_pixels;
353 my $pre_conv= $pixels; #rotate image 180 degrees!
355 for (my $y=0; $y< $height; $y++)
357 my $y_pos=$y*$width*$bytespp; #calculate offset into the image (a string)
358 my $row=substr ($pre_conv, $y_pos, $width*$bytespp); #extract 1 pixel row
359 $row =~ s/\G(.)(.)(.)/$3$2$1/gms; #turn the BMP BGR order into OpenGL RGB order;
360 $new_pixels.= reverse $row;
363 $raw_pixels = $new_pixels; #put transformed data into C array.
364 push @ref, $raw_pixels, $surface;
366 #we could have created another SDL surface frm the '$raw_pixel's... oh well.
367 return ($raw_pixels, $width, $height, $size);