Clean up. This dir is still on experimental branch
[sdlgit/SDL_perl.git] / test / OpenGL / tutorial / lesson08.pl
CommitLineData
8fde61e3 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 SDL::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
48
49print STDERR "Use b to toggle blend, page up/down to zoom, and arrow keys to rotate\n";
50
51main();
52exit;
53
54
55sub main
56 {
57 my $done=0;
58 my $vidmode_flags= SDL_OPENGL;
59
60 $vidmode_flags|= SDL_FULLSCREEN if $arg_fullscreen;
61
62 my $app = new SDL::App ( -title => "Jeff Molofee's GL Code Tutorial ... NeHe '99",
63 -icon => "icon.png",
64 -flags => $vidmode_flags,
65 -width => $arg_screen_width,
66 -height =>$arg_screen_height,
67 -opengl => 1,
68 );
69
70 SDL::ShowCursor(0);
71
72 my $event = new SDL::Event;
73 $event->set(SDL_SYSWMEVENT,SDL_IGNORE);
74
75 InitGL($arg_screen_width, $arg_screen_height);
76
77 glEnable(GL_BLEND); # Turn Blending On
78 glEnable(GL_LIGHTING);
79 glDisable(GL_DEPTH_TEST); # Turn Depth Testing Off
80
81 while ( not $done )
82 {
83
84 DrawGLScene();
85
86 $app->sync();
87
88 $event->pump;
89 $event->poll;
90
91 $done = 1 if ( $event->type == SDL_QUIT ) ;
92
93 if ( $event->type == SDL_KEYDOWN )
94 {
95 my $key= $event->key_sym;
96
97 $done = 1 if ( $key == SDLK_ESCAPE ) ;
98
99 if ($key==SDLK_f)
100 {
101 printf("Filter was: %d\n", $filter);
102 $filter = 1+(($filter) % 3) ;
103 printf("Filter is now: %d\n", $filter);
104 $app->delay(100);
105 }
106 if ($key == SDLK_b)
107 {
108 printf("Blend was: %d\n", $blend);
109 $blend = $blend ? 0 : 1;
110 printf("Blend is now: %d\n", $blend);
111 $app->delay(100);
112 if ($blend)
113 {
114 glEnable(GL_BLEND); # Turn Blending On
115 glEnable(GL_LIGHTING);
116 glDisable(GL_DEPTH_TEST); # Turn Depth Testing Off
117 }
118 else
119 {
120 glDisable(GL_BLEND); # Turn Blending Off
121 glDisable(GL_LIGHTING);
122 glEnable(GL_DEPTH_TEST); # Turn Depth Testing On
123 }
124 }
125 #bit lax:
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 );
132
133 }
134 }
135 }
136
137
138
139
140
141
142#########################################################################
143#Pretty much in original form, but 'Perlised'
144
145
146
147
148sub InitGL
149 {
150 my ($Width, $Height) = @_;
151
152 glViewport(0, 0, $Width, $Height);
153
154 LoadGLTextures(); # Load The Texture(s)
155
156 glEnable(GL_TEXTURE_2D); # Enable Texture Mapping
157
158
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
164
165 glMatrixMode(GL_PROJECTION);
166 glLoadIdentity(); # Reset The Projection Matrix
167
168 gluPerspective(45.0, $Width/$Height, 0.1, 100.0); # Calculate The Aspect Ratio Of The Window
169
170 glMatrixMode(GL_MODELVIEW);
171
172
173 my $LightAmbient = [ 0.5, 0.5, 0.5, 1.0 ]; # white ambient light at half intensity (rgba) */
174
175 my $LightDiffuse = [ 1.0, 1.0, 1.0, 1.0 ]; # super bright, full intensity diffuse light. */
176
177 my $LightPosition = [ 0.0 , 0.0, 2.0, 1.0 ]; # position of light (x, y, z, (position of light)) */
178
179
180
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);
189
190
191 }
192
193
194
195# The main drawing function.
196sub DrawGLScene
197 {
198 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); # Clear The Screen And The Depth Buffer
199 glLoadIdentity(); # Reset The View
200
201 glTranslate(0.0,0.0,$z); # move z units out from the screen.
202
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
205
206 glBindTexture(GL_TEXTURE_2D, $filter); # choose the texture to use.
207
208 glBegin(GL_QUADS); # begin drawing a cube
209
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
216
217 # Back Face
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
223
224 # Top Face
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
230
231 # Bottom Face
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
237
238 # Right face
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
244
245 # Left Face
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
251
252 glEnd(); # done with the polygon.
253
254 $xrot+=$xspeed; # X Axis Rotation
255 $yrot+=$yspeed; # Y Axis Rotation
256
257
258
259 }
260
261
262
263
264sub LoadGLTextures
265 {
266 # Load Texture
267
268
269 my ($pixels, $width, $height, $size)=ImageLoad("Data/glass.bmp");
270
271 # Create Texture
272
273 glGenTextures(3);
274
275 # texture 1 (poor quality scaling)
276 glBindTexture(GL_TEXTURE_2D, 1); # 2d texture (x and y size)
277
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
280
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);
284
285 glTexImage2D(GL_TEXTURE_2D,
286 0, #level (0 normal, heighr is form mip-mapping)
287 3, #internal format (3=GL_RGB)
288 $width,$height,
289 0, # border
290 GL_RGB, #format RGB color data
291 GL_UNSIGNED_BYTE, #unsigned bye data
292 $pixels); #ptr to texture data
293
294
295
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);
301
302 glTexImage2D(GL_TEXTURE_2D,
303 0, #level (0 normal, heighr is form mip-mapping)
304 3, #internal format (3=GL_RGB)
305 $width,$height,
306 0, # border
307 GL_RGB, #format RGB color data
308 GL_UNSIGNED_BYTE, #unsigned bye data
309 $pixels); #ptr to texture data
310
311
312
313
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);
319
320 glTexImage2D(GL_TEXTURE_2D,
321 0, #level (0 normal, heighr is form mip-mapping)
322 3, #internal format (3=GL_RGB)
323 $width,$height,
324 0, # border
325 GL_RGB, #format RGB color data
326 GL_UNSIGNED_BYTE, #unsigned bye data
327 $pixels); #ptr to texture data
328
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);
331
332 my $glerr=glGetError();
333 die "Problem setting up 2d Texture (dimensions not a power of 2?)):".gluErrorString($glerr)."\n" if $glerr;
334
335 }
336
337
338
339
340
341
342
343
344
345
346
347#somthing needs to keep the ref count alive for objects which represents data in C space (they have no ref count):
348my @ref=();
349
350sub ImageLoad
351 {
352 my $filename=shift;
353
354 my $surface = new SDL::Surface( -name => $filename); #makes use of SDL: BMP loader.
355
356
357 my $width=$surface->width();
358 my $height=$surface->height();
359 my $bytespp= $surface->bytes_per_pixel();
360 my $size= $width*$height*$bytespp;
361
362 my $surface_pixels=$surface->pixels();
363 my $surface_size=$width*$height*$surface->bytes_per_pixel();
364 my $raw_pixels = reverse $surface_pixels;
365
366
367
368 #do a conversion (the pixel data is accessable as a simple string)
369
370 my $pixels=$raw_pixels;
371 my $pre_conv= $pixels;
372 my $new_pixels="";
373 for (my $y=0; $y< $height; $y++)
374 {
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;
379 }
380
381 $raw_pixels = $new_pixels; #put transformed data into C array.
382 push @ref, $raw_pixels, $surface;
383
384 #we could have created another SDL surface frm the '$raw_pixel's... oh well.
385 return ($raw_pixels, $width, $height, $size);
386 }