/t_backcompat/OpenGL/tutorial/lesson07.pl

http://github.com/PerlGameDev/SDL · Perl · 352 lines · 239 code · 79 blank · 34 comment · 28 complexity · 8aafb3097db8d6abd365436f8638a891 MD5 · raw file

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