TexturedCube.pp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. program TexturedCube;
  2. {$L build/texture.bin.o}
  3. {$mode objfpc}
  4. uses
  5. ctypes, nds9;
  6. //texture_bin.h is created automagicaly from the texture.bin placed in arm9/resources
  7. //texture.bin is a raw 128x128 16 bit image. I will release a tool for texture conversion
  8. //later
  9. {$include inc/texture.bin.inc}
  10. var
  11. CubeVectors: array [0..23] of v16;
  12. CubeFaces: array [0..23] of u8;
  13. uv: array [0..3] of u32;
  14. normals: array [0..5] of u32;
  15. procedure Initialize();
  16. begin
  17. //verticies for the cube
  18. CubeVectors[0] := floattov16(-0.5); CubeVectors[1] := floattov16(-0.5); CubeVectors[2] := floattov16(0.5);
  19. CubeVectors[3] := floattov16(0.5); CubeVectors[4] := floattov16(-0.5); CubeVectors[5] := floattov16(0.5);
  20. CubeVectors[6] := floattov16(0.5); CubeVectors[7] := floattov16(-0.5); CubeVectors[8] := floattov16(-0.5);
  21. CubeVectors[9] := floattov16(-0.5); CubeVectors[10] := floattov16(-0.5); CubeVectors[11] := floattov16(-0.5);
  22. CubeVectors[12] := floattov16(-0.5); CubeVectors[13] := floattov16(0.5); CubeVectors[14] := floattov16(0.5);
  23. CubeVectors[15] := floattov16(0.5); CubeVectors[16] := floattov16(0.5); CubeVectors[17] := floattov16(0.5);
  24. CubeVectors[18] := floattov16(0.5); CubeVectors[19] := floattov16(0.5); CubeVectors[20] := floattov16(-0.5);
  25. CubeVectors[21] := floattov16(-0.5); CubeVectors[22] := floattov16(0.5); CubeVectors[23] := floattov16(-0.5);
  26. //polys
  27. CubeFaces[0] := 3; CubeFaces[1] := 2; CubeFaces[2] := 1; CubeFaces[3] := 0;
  28. CubeFaces[4] := 0; CubeFaces[5] := 1; CubeFaces[6] := 5; CubeFaces[7] := 4;
  29. CubeFaces[8] := 1; CubeFaces[9] := 2; CubeFaces[10] := 6; CubeFaces[11] := 5;
  30. CubeFaces[12] := 2; CubeFaces[13] := 3; CubeFaces[14] := 7; CubeFaces[15] := 6;
  31. CubeFaces[16] := 3; CubeFaces[17] := 0; CubeFaces[18] := 4; CubeFaces[19] := 7;
  32. CubeFaces[20] := 5; CubeFaces[21] := 6; CubeFaces[22] := 7; CubeFaces[23] := 4;
  33. //texture coordinates
  34. uv[0] := TEXTURE_PACK(inttot16(128), 0);
  35. uv[1] := TEXTURE_PACK(inttot16(128),inttot16(128));
  36. uv[2] := TEXTURE_PACK(0, inttot16(128));
  37. uv[3] := TEXTURE_PACK(0,0);
  38. normals[0] := NORMAL_PACK(0,floattov10(-0.97),0);
  39. normals[1] := NORMAL_PACK(0,0,floattov10(0.97));
  40. normals[2] := NORMAL_PACK(floattov10(0.97),0,0);
  41. normals[3] := NORMAL_PACK(0,0,floattov10(-0.97));
  42. normals[4] := NORMAL_PACK(floattov10(-0.97),0,0);
  43. normals[5] := NORMAL_PACK(0,floattov10(0.97),0);
  44. end;
  45. //draw a cube face at the specified color
  46. procedure drawQuad(poly: integer);
  47. var
  48. f1, f2, f3, f4: u32;
  49. begin
  50. f1 := CubeFaces[poly * 4] ;
  51. f2 := CubeFaces[poly * 4 + 1] ;
  52. f3 := CubeFaces[poly * 4 + 2] ;
  53. f4 := CubeFaces[poly * 4 + 3] ;
  54. glNormal(normals[poly]);
  55. GFX_TEX_COORD^ := (uv[0]);
  56. glVertex3v16(CubeVectors[f1*3], CubeVectors[f1*3 + 1], CubeVectors[f1*3 + 2] );
  57. GFX_TEX_COORD^ := (uv[1]);
  58. glVertex3v16(CubeVectors[f2*3], CubeVectors[f2*3 + 1], CubeVectors[f2*3 + 2] );
  59. GFX_TEX_COORD^ := (uv[2]);
  60. glVertex3v16(CubeVectors[f3*3], CubeVectors[f3*3 + 1], CubeVectors[f3*3 + 2] );
  61. GFX_TEX_COORD^ := (uv[3]);
  62. glVertex3v16(CubeVectors[f4*3], CubeVectors[f4*3 + 1], CubeVectors[f4*3 + 2] );
  63. end;
  64. procedure DisplayEnableMotionBlur();
  65. var
  66. dispcnt: cuint32;
  67. begin
  68. dispcnt := REG_DISPCNT^;
  69. //set main display to display from VRAM
  70. dispcnt := dispcnt and ($00030000 xor $FFFFFFFF);
  71. dispcnt := dispcnt or (2 shl 16); //choose to display screen from VRAM
  72. dispcnt := dispcnt and ($000C0000 xor $FFFFFFFF);
  73. dispcnt := dispcnt or (1 shl 18); //choose to display screen from VRAM_B
  74. REG_DISPCNT^ := dispcnt;
  75. end;
  76. procedure DisplayEnableNormal();
  77. var
  78. dispcnt: cuint32;
  79. begin
  80. dispcnt := REG_DISPCNT^;
  81. dispcnt := dispcnt and ($00030000 xor $FFFFFFFF);
  82. dispcnt := dispcnt or (1 shl 16); //choose to display screen from normal layer composition
  83. REG_DISPCNT^ := dispcnt;
  84. end;
  85. var
  86. textureID: integer;
  87. i: integer;
  88. rotateX: cfloat = 0.0;
  89. rotateY: cfloat = 0.0;
  90. keys: cuint16;
  91. displayBlurred: boolean;
  92. begin
  93. Initialize();
  94. //set mode 0, enable BG0 and set it to 3D
  95. videoSetMode(MODE_0_3D);
  96. // initialize gl
  97. glInit();
  98. //enable textures
  99. glEnable(GL_TEXTURE_2D);
  100. //this should work the same as the normal gl call
  101. glViewport(0,0,255,191);
  102. // enable antialiasing
  103. glEnable(GL_ANTIALIAS);
  104. // setup the rear plane
  105. glClearColor(0,0,0,31); // BG must be opaque for AA to work
  106. glClearPolyID(63); // BG must have a unique polygon ID for AA to work
  107. glClearDepth($7FFF);
  108. vramSetBankB(VRAM_B_LCD);
  109. REG_DISPCAPCNT^ := DCAP_MODE(DCAP_MODE_BLEND) //blend source A and source B
  110. //or DCAP_SRC_ADDR //this is not used since we are setting the display to render from VRAM
  111. or DCAP_SRC_B(DCAP_SRC_B_VRAM)
  112. or DCAP_SRC_A(DCAP_SRC_A_3DONLY)
  113. or DCAP_SIZE(DCAP_SIZE_256x192)
  114. or DCAP_OFFSET(0) //where to write the captured data within our chosen VRAM bank
  115. or DCAP_BANK(DCAP_BANK_VRAM_B)
  116. or DCAP_B(12) //blend mostly from B to make a very dramatic effect
  117. or DCAP_A(4) //and blend only a little bit from the new scene
  118. ;
  119. //but, dramatic effects tend to leave some garbage on the screen since the precision of the math is low,
  120. //and we're not putting a lot of dampening on the effect.
  121. //a more realistic value might be 8 and 8, but perhaps in a more complex 3d scene the garbage isn't such a bad thing
  122. //since the scene is changing constantly
  123. DisplayEnableMotionBlur();
  124. displayBlurred := true;
  125. vramSetBankA(VRAM_A_TEXTURE);
  126. glGenTextures(1, @textureID);
  127. glBindTexture(0, textureID);
  128. glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_128 , TEXTURE_SIZE_128, 0, TEXGEN_TEXCOORD, pcuint8(@texture_bin));
  129. //any floating point gl call is being converted to fixed prior to being implemented
  130. glMatrixMode(GL_PROJECTION);
  131. glLoadIdentity();
  132. gluPerspective(70, 256.0 / 192.0, 0.1, 40);
  133. gluLookAt( 0.0, 0.0, 1.0, //camera possition
  134. 0.0, 0.0, 0.0, //look at
  135. 0.0, 1.0, 0.0); //up
  136. while true do
  137. begin
  138. glLight(0, RGB15(31,31,31) , 0, floattov10(-1.0), 0);
  139. glLight(1, RGB15(31,0,31), 0, floattov10(1) - 1, 0);
  140. glLight(2, RGB15(0,31,0) , floattov10(-1.0), 0, 0);
  141. glLight(3, RGB15(0,0,31) , floattov10(1.0) - 1, 0, 0);
  142. glPushMatrix();
  143. //move it away from the camera
  144. glTranslatef32(0, 0, floattof32(-1));
  145. glRotateX(rotateX);
  146. glRotateY(rotateY);
  147. glMatrixMode(GL_TEXTURE);
  148. glLoadIdentity();
  149. glMatrixMode(GL_MODELVIEW);
  150. glMaterialf(GL_AMBIENT, RGB15(8,8,8));
  151. glMaterialf(GL_DIFFUSE, RGB15(16,16,16));
  152. glMaterialf(GL_SPECULAR, BIT(15) or RGB15(8,8,8));
  153. glMaterialf(GL_EMISSION, RGB15(5,5,5));
  154. //ds uses a table for shinyness..this generates a half-ass one
  155. glMaterialShinyness();
  156. //not a real gl function and will likely change
  157. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_BACK or POLY_FORMAT_LIGHT0 or POLY_FORMAT_LIGHT1 or
  158. POLY_FORMAT_LIGHT2 or POLY_FORMAT_LIGHT3 ) ;
  159. scanKeys();
  160. keys := keysHeld();
  161. if((keys and KEY_UP)) <> 0 then rotateX := rotateX +3;
  162. if((keys and KEY_DOWN)) <> 0 then rotateX := rotateX -3;
  163. if((keys and KEY_LEFT)) <> 0 then rotateY := rotateY +3;
  164. if((keys and KEY_RIGHT)) <> 0 then rotateY := rotateY -3;
  165. if (keysDown() and KEY_A) <> 0 then
  166. begin
  167. displayBlurred := not displayBlurred;
  168. if displayBlurred then
  169. DisplayEnableMotionBlur()
  170. else
  171. DisplayEnableNormal();
  172. end;
  173. glBindTexture(0, textureID);
  174. //draw the obj
  175. glBegin(GL_QUAD);
  176. for i := 0 to 5 do
  177. drawQuad(i);
  178. glEnd();
  179. glPopMatrix(1);
  180. glFlush(0);
  181. swiWaitForVBlank();
  182. if (keys and KEY_START) <> 0 then break;
  183. //the display capture enable bit must be set again each frame if you want to continue capturing.
  184. REG_DISPCAPCNT^ := REG_DISPCAPCNT^ or DCAP_ENABLE;
  185. end;
  186. end.