PageRenderTime 57ms CodeModel.GetById 13ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 1ms

/t_backcompat/OpenGL/tutorial/lesson08.pl

http://github.com/PerlGameDev/SDL
Perl | 367 lines | 250 code | 82 blank | 35 comment | 28 complexity | f945af147d8f1641e385d18d8955506e MD5 | raw file
  1#!/usr/bin/perl -w
  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)
  5#
  6# If you've found this code useful, please let me know.
  7#
  8# Visit me at www.demonews.com/hosted/nehe
  9
 10use strict;
 11use Getopt::Long;
 12use Data::Dumper;
 13use Benchmark;
 14
 15use SDL;
 16use SDLx::App;
 17use SDL::OpenGL;
 18use SDL::Event;
 19use SDL::Surface;
 20use SDL::Cursor;
 21use SDL::OpenGL;
 22
 23my $arg_screen_width  = 640;
 24my $arg_screen_height = 512;
 25my $arg_fullscreen    = 0;
 26
 27GetOptions(
 28	"width:i"     => \$arg_screen_width,
 29	"height:i"    => \$arg_screen_height,
 30	"fullscreen!" => \$arg_fullscreen,
 31
 32) or die $!;
 33
 34############################################################
 35
 36my $light = 0;
 37
 38my $xrot   = 0; # x rotation
 39my $yrot   = 0; # y rotation
 40my $xspeed = 0; # x rotation speed
 41my $yspeed = 0; # y rotation speed
 42
 43my $z = -5.0;   # depth into the screen.
 44
 45my $filter = 1; # Which Filter To Use (nearest/linear/mipmapped) */
 46my $blend  = 1;
 47
 48print STDERR "Use b to toggle blend, page up/down to zoom, and arrow keys to rotate\n";
 49
 50main();
 51exit;
 52
 53sub main {
 54	my $done          = 0;
 55	my $vidmode_flags = SDL_OPENGL;
 56
 57	$vidmode_flags |= SDL_FULLSCREEN if $arg_fullscreen;
 58
 59	my $app = SDLx::App->new(
 60		-title  => "Jeff Molofee's GL Code Tutorial ... NeHe '99",
 61		-icon   => "icon.png",
 62		-flags  => $vidmode_flags,
 63		-width  => $arg_screen_width,
 64		-height => $arg_screen_height,
 65		-opengl => 1,
 66	);
 67
 68	SDL::ShowCursor(0);
 69
 70	my $event = SDL::Event->new;
 71	$event->set( SDL_SYSWMEVENT, SDL_IGNORE );
 72
 73	InitGL( $arg_screen_width, $arg_screen_height );
 74
 75	glEnable(GL_BLEND); # Turn Blending On
 76	glEnable(GL_LIGHTING);
 77	glDisable(GL_DEPTH_TEST); # Turn Depth Testing Off
 78
 79	while ( not $done ) {
 80
 81		DrawGLScene();
 82
 83		$app->sync();
 84
 85		$event->pump;
 86		$event->poll;
 87
 88		$done = 1 if ( $event->type == SDL_QUIT );
 89
 90		if ( $event->type == SDL_KEYDOWN ) {
 91			my $key = $event->key_sym;
 92
 93			$done = 1 if ( $key == SDLK_ESCAPE );
 94
 95			if ( $key == SDLK_f ) {
 96				printf( "Filter was: %d\n", $filter );
 97				$filter = 1 + ( ($filter) % 3 );
 98				printf( "Filter is now: %d\n", $filter );
 99				$app->delay(100);
100			}
101			if ( $key == SDLK_b ) {
102				printf( "Blend was: %d\n", $blend );
103				$blend = $blend ? 0 : 1;
104				printf( "Blend is now: %d\n", $blend );
105				$app->delay(100);
106				if ($blend) {
107					glEnable(GL_BLEND); # Turn Blending On
108					glEnable(GL_LIGHTING);
109					glDisable(GL_DEPTH_TEST); # Turn Depth Testing Off
110				} else {
111					glDisable(GL_BLEND);      # Turn Blending Off
112					glDisable(GL_LIGHTING);
113					glEnable(GL_DEPTH_TEST);  # Turn Depth Testing On
114				}
115			}
116
117			#bit lax:
118			$z -= 0.02 if ( $key == SDLK_PAGEUP );
119			$z      += 0.02 if ( $key == SDLK_PAGEDOWN );
120			$xspeed += 0.02 if ( $key == SDLK_UP );
121			$xspeed -= 0.02 if ( $key == SDLK_DOWN );
122			$yspeed -= 0.01 if ( $key == SDLK_LEFT );
123			$yspeed += 0.01 if ( $key == SDLK_RIGHT );
124
125		}
126	}
127}
128
129#########################################################################
130#Pretty much in original form, but 'Perlised'
131
132sub InitGL {
133	my ( $Width, $Height ) = @_;
134
135	glViewport( 0, 0, $Width, $Height );
136
137	LoadGLTextures(); # Load The Texture(s)
138
139	glEnable(GL_TEXTURE_2D); # Enable Texture Mapping
140
141	glClearColor( 0.0, 0.0, 0.0, 0.0 ); # This Will Clear The Background Color To Black
142	glClearDepth(1.0);                  # Enables Clearing Of The Depth Buffer
143	glDepthFunc(GL_LESS);               # The Type Of Depth Test To Do
144	glEnable(GL_DEPTH_TEST);            # Enables Depth Testing
145	glShadeModel(GL_SMOOTH);            # Enables Smooth Color Shading
146
147	glMatrixMode(GL_PROJECTION);
148	glLoadIdentity();                   # Reset The Projection Matrix
149
150	gluPerspective( 45.0, $Width / $Height, 0.1, 100.0 ); # Calculate The Aspect Ratio Of The Window
151
152	glMatrixMode(GL_MODELVIEW);
153
154	my $LightAmbient = [ 0.5, 0.5, 0.5, 1.0 ];            # white ambient light at half intensity (rgba) */
155
156	my $LightDiffuse = [ 1.0, 1.0, 1.0, 1.0 ];            # super bright, full intensity diffuse light. */
157
158	my $LightPosition = [ 0.0, 0.0, 2.0, 1.0 ];           # position of light (x, y, z, (position of light)) */
159
160	#setup light number 1
161	glLight( GL_LIGHT1, GL_AMBIENT,  @$LightAmbient );    # add lighting. (ambient)
162	glLight( GL_LIGHT1, GL_DIFFUSE,  @$LightDiffuse );    # add lighting. (diffuse).
163	glLight( GL_LIGHT1, GL_POSITION, @$LightPosition );   # set light position.
164	glEnable(GL_LIGHT1);                                  # turn light 1 on.
165	                                                      #/* setup blending */
166	glBlendFunc( GL_SRC_ALPHA, GL_ONE );                  # Set The Blending Function For Translucency
167	glColor( 1.0, 1.0, 1.0, 0.5 );
168
169}
170
171# The main drawing function.
172sub DrawGLScene {
173	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); # Clear The Screen And The Depth Buffer
174	glLoadIdentity();                                     # Reset The View
175
176	glTranslate( 0.0, 0.0, $z );                          # move z units out from the screen.
177
178	glRotate( $xrot, 1.0, 0.0, 0.0 );                     # Rotate On The X Axis
179	glRotate( $yrot, 0.0, 1.0, 0.0 );                     # Rotate On The Y Axis
180
181	glBindTexture( GL_TEXTURE_2D, $filter );              # choose the texture to use.
182
183	glBegin(GL_QUADS);                                    # begin drawing a cube
184
185	# Front Face (note that the texture's corners have to match the quad's corners)
186	glNormal( 0.0, 0.0, 1.0 );                            # front face points out of the screen on z.
187	glTexCoord( 0.0, 0.0 );
188	glVertex( -1.0, -1.0, 1.0 );                          # Bottom Left Of The Texture and Quad
189	glTexCoord( 1.0, 0.0 );
190	glVertex( 1.0, -1.0, 1.0 );                           # Bottom Right Of The Texture and Quad
191	glTexCoord( 1.0, 1.0 );
192	glVertex( 1.0, 1.0, 1.0 );                            # Top Right Of The Texture and Quad
193	glTexCoord( 0.0, 1.0 );
194	glVertex( -1.0, 1.0, 1.0 );                           # Top Left Of The Texture and Quad
195
196	# Back Face
197	glNormal( 0.0, 0.0, -1.0 );                           # back face points into the screen on z.
198	glTexCoord( 1.0, 0.0 );
199	glVertex( -1.0, -1.0, -1.0 );                         # Bottom Right Of The Texture and Quad
200	glTexCoord( 1.0, 1.0 );
201	glVertex( -1.0, 1.0, -1.0 );                          # Top Right Of The Texture and Quad
202	glTexCoord( 0.0, 1.0 );
203	glVertex( 1.0, 1.0, -1.0 );                           # Top Left Of The Texture and Quad
204	glTexCoord( 0.0, 0.0 );
205	glVertex( 1.0, -1.0, -1.0 );                          # Bottom Left Of The Texture and Quad
206
207	# Top Face
208	glNormal( 0.0, 1.0, 0.0 );                            # top face points up on y.
209	glTexCoord( 0.0, 1.0 );
210	glVertex( -1.0, 1.0, -1.0 );                          # Top Left Of The Texture and Quad
211	glTexCoord( 0.0, 0.0 );
212	glVertex( -1.0, 1.0, 1.0 );                           # Bottom Left Of The Texture and Quad
213	glTexCoord( 1.0, 0.0 );
214	glVertex( 1.0, 1.0, 1.0 );                            # Bottom Right Of The Texture and Quad
215	glTexCoord( 1.0, 1.0 );
216	glVertex( 1.0, 1.0, -1.0 );                           # Top Right Of The Texture and Quad
217
218	# Bottom Face
219	glNormal( 0.0, -1.0, 0.0 );                           # bottom face points down on y.
220	glTexCoord( 1.0, 1.0 );
221	glVertex( -1.0, -1.0, -1.0 );                         # Top Right Of The Texture and Quad
222	glTexCoord( 0.0, 1.0 );
223	glVertex( 1.0, -1.0, -1.0 );                          # Top Left Of The Texture and Quad
224	glTexCoord( 0.0, 0.0 );
225	glVertex( 1.0, -1.0, 1.0 );                           # Bottom Left Of The Texture and Quad
226	glTexCoord( 1.0, 0.0 );
227	glVertex( -1.0, -1.0, 1.0 );                          # Bottom Right Of The Texture and Quad
228
229	# Right face
230	glNormal( 1.0, 0.0, 0.0 );                            # right face points right on x.
231	glTexCoord( 1.0, 0.0 );
232	glVertex( 1.0, -1.0, -1.0 );                          # Bottom Right Of The Texture and Quad
233	glTexCoord( 1.0, 1.0 );
234	glVertex( 1.0, 1.0, -1.0 );                           # Top Right Of The Texture and Quad
235	glTexCoord( 0.0, 1.0 );
236	glVertex( 1.0, 1.0, 1.0 );                            # Top Left Of The Texture and Quad
237	glTexCoord( 0.0, 0.0 );
238	glVertex( 1.0, -1.0, 1.0 );                           # Bottom Left Of The Texture and Quad
239
240	# Left Face
241	glNormal( -1.0, 0.0, 0.0 );                           # left face points left on x.
242	glTexCoord( 0.0, 0.0 );
243	glVertex( -1.0, -1.0, -1.0 );                         # Bottom Left Of The Texture and Quad
244	glTexCoord( 1.0, 0.0 );
245	glVertex( -1.0, -1.0, 1.0 );                          # Bottom Right Of The Texture and Quad
246	glTexCoord( 1.0, 1.0 );
247	glVertex( -1.0, 1.0, 1.0 );                           # Top Right Of The Texture and Quad
248	glTexCoord( 0.0, 1.0 );
249	glVertex( -1.0, 1.0, -1.0 );                          # Top Left Of The Texture and Quad
250
251	glEnd();                                              # done with the polygon.
252
253	$xrot += $xspeed;                                     # X Axis Rotation
254	$yrot += $yspeed;                                     # Y Axis Rotation
255
256}
257
258sub LoadGLTextures {
259
260	# Load Texture
261
262	my ( $pixels, $width, $height, $size ) = ImageLoad("Data/glass.bmp");
263
264	# Create Texture
265
266	glGenTextures(3);
267
268	# texture 1 (poor quality scaling)
269	glBindTexture( GL_TEXTURE_2D, 1 ); # 2d texture (x and y size)
270
271	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); # cheap scaling when image bigger than texture
272	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); # cheap scaling when image smalled than texture
273
274	# 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
275	# border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
276	#glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
277
278	glTexImage2D( GL_TEXTURE_2D,
279		0,                                                              #level (0 normal, heighr is form mip-mapping)
280		3,                                                              #internal format (3=GL_RGB)
281		$width, $height,
282		0,                                                              # border
283		GL_RGB,                                                         #format RGB color data
284		GL_UNSIGNED_BYTE,                                               #unsigned bye data
285		$pixels
286	);                                                                  #ptr to texture data
287
288	# texture 2 (linear scaling)
289	glBindTexture( GL_TEXTURE_2D, 2 );                                  # 2d texture (x and y size)
290	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );  # scale linearly when image bigger than texture
291	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );  # scale linearly when image smalled than texture
292	   #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
293
294	glTexImage2D( GL_TEXTURE_2D,
295		0, #level (0 normal, heighr is form mip-mapping)
296		3, #internal format (3=GL_RGB)
297		$width, $height,
298		0,                # border
299		GL_RGB,           #format RGB color data
300		GL_UNSIGNED_BYTE, #unsigned bye data
301		$pixels
302	);                    #ptr to texture data
303
304	# texture 3 (mipmapped scaling)
305	glBindTexture( GL_TEXTURE_2D, 3 ); # 2d texture (x and y size)
306	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); # scale linearly when image bigger than texture
307	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
308		GL_LINEAR_MIPMAP_NEAREST
309	); # scale linearly + mipmap when image smalled than texture
310	   #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
311
312	glTexImage2D( GL_TEXTURE_2D,
313		0, #level (0 normal, heighr is form mip-mapping)
314		3, #internal format (3=GL_RGB)
315		$width, $height,
316		0,                # border
317		GL_RGB,           #format RGB color data
318		GL_UNSIGNED_BYTE, #unsigned bye data
319		$pixels
320	);                    #ptr to texture data
321
322	# 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data.
323	gluBuild2DMipmaps( GL_TEXTURE_2D, 3, $width, $height, GL_RGB,
324		GL_UNSIGNED_BYTE, $pixels
325	);
326
327	my $glerr = glGetError();
328	die "Problem setting up 2d Texture (dimensions not a power of 2?)):" . gluErrorString($glerr) . "\n"
329		if $glerr;
330
331}
332
333#somthing needs to keep the ref count alive for objects which represents data in C space (they have no ref count):
334my @ref = ();
335
336sub ImageLoad {
337	my $filename = shift;
338
339	my $surface = SDL::Surface->new( -name => $filename ); #makes use of SDL: BMP loader.
340
341	my $width   = $surface->width();
342	my $height  = $surface->height();
343	my $bytespp = $surface->bytes_per_pixel();
344	my $size    = $width * $height * $bytespp;
345
346	my $surface_pixels = $surface->pixels();
347	my $surface_size   = $width * $height * $surface->bytes_per_pixel();
348	my $raw_pixels     = reverse $surface_pixels;
349
350	#do a conversion (the pixel data is accessable as a simple string)
351
352	my $pixels     = $raw_pixels;
353	my $pre_conv   = $pixels;
354	my $new_pixels = "";
355	for ( my $y = 0; $y < $height; $y++ ) {
356		my $y_pos = $y * $width * $bytespp;                       #calculate offset into the image (a string)
357		my $row = substr( $pre_conv, $y_pos, $width * $bytespp ); #extract 1 pixel row
358		$row =~ s/\G(.)(.)(.)/$3$2$1/gms;                         #turn the BMP BGR order into OpenGL RGB order;
359		$new_pixels .= reverse $row;
360	}
361
362	$raw_pixels = $new_pixels;                                    #put transformed data into C array.
363	push @ref, $raw_pixels, $surface;
364
365	#we could have created another SDL surface frm the '$raw_pixel's... oh well.
366	return ( $raw_pixels, $width, $height, $size );
367}