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