Преглед изворни кода

Textured raycaster is now fast enough for a demo.

bart пре 1 година
родитељ
комит
55b5818582
1 измењених фајлова са 202 додато и 111 уклоњено
  1. 202 111
      BCC/userBDOS/RAYCAST.C

+ 202 - 111
BCC/userBDOS/RAYCAST.C

@@ -10,11 +10,18 @@
 #include "LIB/GFX.C"
 #include "LIB/FP.C"
 
+// Note: these are also hardcoded in the render assembly, so update there as well!
+#define FB_ADDR 0xD00000
 #define screenWidth 320
 #define screenHeight 240
+#define texWidth 64
+#define texHeight 64
+
+// Map
 #define mapWidth 24
 #define mapHeight 24
 
+// Input
 #define BTN_LEFT 256
 #define BTN_RIGHT 257
 #define BTN_UP 258
@@ -32,11 +39,6 @@
 #define COLOR_YELLOW      0xFC
 #define COLOR_DARK_YELLOW 0x90
 
-#define texWidth 64
-#define texHeight 64
-
-#define FB_ADDR 0xD00000
-#define TEX_ADDR 0x440000
 
 // Framebuffer. fb[Y][X] (bottom right is [239][319])
 char (*fb)[screenWidth] = (char (*)[screenWidth]) FB_ADDR;
@@ -181,95 +183,6 @@ word LUTplaneY[360] = {
 42459, 42597, 42721, 42833, 42931, 43017, 43089, 43148, 43194, 43227, 43247, 43254
 };
 
-word worldMap[mapWidth][mapHeight]=
-{
-  {4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,7,7,7,7,7,7,7},
-  {4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,7},
-  {4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},
-  {4,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},
-  {4,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,7},
-  {4,0,4,0,0,0,0,5,5,5,5,5,5,5,5,5,7,7,0,7,7,7,7,7},
-  {4,0,5,0,0,0,0,5,0,5,0,5,0,5,0,5,7,0,0,0,7,7,7,1},
-  {4,0,6,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,0,0,0,8},
-  {4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,7,1},
-  {4,0,8,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,0,0,0,8},
-  {4,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,7,7,7,1},
-  {4,0,0,0,0,0,0,5,5,5,5,0,5,5,5,5,7,7,7,7,7,7,7,1},
-  {6,6,6,6,6,6,6,6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6},
-  {8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
-  {6,6,6,6,6,6,0,6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6},
-  {4,4,4,4,4,4,0,4,4,4,6,0,6,2,2,2,2,2,2,2,3,3,3,3},
-  {4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,0,0,0,2},
-  {4,0,0,0,0,0,0,0,0,0,0,0,6,2,0,0,5,0,0,2,0,0,0,2},
-  {4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,2,0,2,2},
-  {4,0,6,0,6,0,0,0,0,4,6,0,0,0,0,0,5,0,0,0,0,0,0,2},
-  {4,0,0,5,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,2,0,2,2},
-  {4,0,6,0,6,0,0,0,0,4,6,0,6,2,0,0,5,0,0,2,0,0,0,2},
-  {4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,0,0,0,2},
-  {4,4,4,4,4,4,4,4,4,4,1,1,1,2,2,2,2,2,2,3,3,3,3,3}
-};
-
-// Render vertical line in pixel plane
-// INPUT:
-//   r4 = x (which vertical line)
-//   r5 = y when to start drawing line
-//   r6 = y when to stop drawing line
-//   r7 = color of line
-void RAYFX_drawVertLine(word x, word start, word end, char color)
-{
-  // reg 4 5 6 7 and 2 (retval) are safe
-  asm(
-  "; backup registers\n"
-  "push r9\n"
-  );
-
-  asm(
-
-  "load32 0xD00000 r9   ; r9 = framebuffer addr\n"
-  "add r9 r4 r4         ; r4 = first pixel in line\n"
-
-  "multu r5 320 r9      ; r9 = start with line offset\n"
-  "add r9 r4 r5         ; r5 = fb addr of start\n"
-  
-  "multu r6 320 r9      ; r9 = end with line offset\n"
-  "add r9 r4 r6         ; r6 = fb addr of start\n"
-
-  "load 239 r2          ; r2 = y endloop\n"
-  "multu r2 320 r9      ; r9 = start line offset\n"
-  "add r9 r4 r2         ; r2 = fb addr of final pixel\n"
-
-  "; draw until start\n"
-  "RAYFX_drawVlineLoopCeiling:\n"
-  "  write 0 r4 r0     ; write black pixel\n"
-  "  add r4 320 r4     ; go to next line pixel\n"
-
-  "  bge r4 r5 2       ; keep looping until reached start\n"
-  "  jump RAYFX_drawVlineLoopCeiling\n"
-
-  "; draw until end\n"
-  "RAYFX_drawVlineLoopWall:\n"
-  "  write 0 r4 r7     ; write color pixel\n"
-  "  add r4 320 r4     ; go to next line pixel\n"
-
-  "  bge r4 r6 2       ; keep looping until reached end\n"
-  "  jump RAYFX_drawVlineLoopWall\n"
-
-
-  "; draw until final pixel\n"
-  "RAYFX_drawVlineLoopFloor:\n"
-  "  write 0 r4 r0     ; write black pixel\n"
-  "  add r4 320 r4     ; go to next line pixel\n"
-
-  "  bge r4 r2 2       ; keep looping until reached end of screen\n"
-  "  jump RAYFX_drawVlineLoopFloor\n"
-  );
-
-  asm(
-  "; restore registers\n"
-  "pop r9\n"
-  );
-
-}
 
 word texture[8][texWidth*texHeight]=
 {
@@ -820,6 +733,191 @@ word texture[8][texWidth*texHeight]=
 }
 ;
 
+
+
+word worldMap[mapWidth][mapHeight]=
+{
+  {4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,7,7,7,7,7,7,7},
+  {4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,7},
+  {4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},
+  {4,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},
+  {4,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,7},
+  {4,0,4,0,0,0,0,2,2,2,2,2,2,2,2,2,7,7,0,7,7,7,7,7},
+  {4,0,5,0,0,0,0,2,0,1,0,1,0,1,0,2,7,0,0,0,7,7,7,1},
+  {4,0,6,0,0,0,0,2,0,0,0,0,0,0,0,2,7,0,0,0,0,0,0,8},
+  {4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,7,1},
+  {4,0,8,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,0,0,0,8},
+  {4,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,7,7,7,1},
+  {4,0,0,0,0,0,0,5,5,5,5,0,5,5,5,5,7,7,7,7,7,7,7,1},
+  {6,6,6,6,6,6,6,6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6},
+  {8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
+  {6,6,6,6,6,6,0,6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6},
+  {4,4,4,4,4,4,0,4,4,4,6,0,6,2,2,2,2,2,2,2,3,3,3,3},
+  {4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,0,0,0,2},
+  {4,0,0,0,0,0,0,0,0,0,0,0,6,2,0,0,5,0,0,2,0,0,0,2},
+  {4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,2,0,2,2},
+  {4,0,6,0,6,0,0,0,0,4,6,0,0,0,0,0,5,0,0,0,0,0,0,2},
+  {4,0,0,5,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,2,0,2,2},
+  {4,0,6,0,6,0,0,0,0,4,6,0,6,2,0,0,5,0,0,2,0,0,0,2},
+  {4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,0,0,0,2},
+  {4,4,4,4,4,4,4,4,4,4,1,1,1,2,2,2,2,2,2,3,3,3,3,3}
+};
+
+// Global variables, so render function can access it
+word drawStart = 0;
+word drawEnd = 0;
+word texNum = 0;
+
+// Render vertical line in pixel plane with textures
+// INPUT:
+//   r1        first pixel addr   VRAM addr of first pixel in line (top pixel)
+//   r2 (a2r)  drawStart          Starting pixel of wall
+//   r3 (a2r)  drawEnd            Ending pixel of wall
+//   r4        texPos             Starting texture coordinate
+//   r5        step               How much to increase the texture coordinate per screen pixel
+//   r6        texX               X coordinate on the texture
+//   r7        x                  X position of line to render
+//   r8        current FB pos     Current framebuffer position in VRAM (top to bottom)
+//   r9        end loop FB pos    Last framebuffer position in VRAM of current loop
+//   r10       texY               Y coordinate on the texture
+//   r11       gp                 Used as temp reg in calculations
+//   r12       texture[texNum]    Texture array of texture to draw
+//   r13       color              Pixel color
+//   r14       ceil or floor col  Ceiling or floor color
+//   side TODO North South or East West wall side
+void RAYFX_drawTextureVertLine(fixed_point_t texPos, fixed_point_t step, word texX, word x)
+{
+  // reg 4 5 6 7 (args) and 2 3 (retval) are safe
+  asm(
+  "; backup registers\n"
+  "push r1\n"
+  "push r8\n"
+  "push r9\n"
+  "push r10\n"
+  "push r11\n"
+  "push r12\n"
+  "push r13\n"
+  "push r14\n"
+  "push r15\n"
+  );
+
+  // setup registers
+  asm(
+  "addr2reg drawStart r2  ; r2 = drawStart addr\n"
+  "read 0 r2 r2           ; r2 = drawStart value\n"
+
+  "addr2reg drawEnd r3    ; r2 = drawEnd addr\n"
+  "read 0 r3 r3           ; r2 = drawEnd value\n"
+
+  "load32 0xD00000 r1     ; r1 = framebuffer addr\n"
+  "add r1 r7 r1           ; r1 = first pixel in line (fb+x)\n"
+
+  "or r0 r1 r8            ; r8 = current pixel\n"
+
+  "multu r2 320 r9        ; r9 = drawStart VRAM offset\n"
+  "add r9 r1 r9           ; r9 = last FB pos of before wall\n"
+
+  "addr2reg texNum r12    ; r12 = texNum addr\n"
+  "read 0 r12 r12         ; r12 = texNum value\n"
+  "multu r12 4096 r12     ; r12 = texture offset (64*64 per texture)\n"
+
+  "addr2reg texture r11   ; r11 = texture array\n"
+  "add r12 r11 r12        ; r12 = texture[texNum]\n"
+
+  "load32 151 r14         ; r14 = ceiling color\n"
+
+  "; draw until start\n"
+  "RAYFX_drawVlineLoopCeiling:\n"
+  "  write 0 r8 r14     ; write ceiling pixel\n"
+  "  add r8 320 r8     ; go to next line pixel\n"
+
+  "  bge r8 r9 2       ; keep looping until reached wall\n"
+  "  jump RAYFX_drawVlineLoopCeiling\n"
+
+
+
+
+  "multu r3 320 r9        ; r9 = drawEnd VRAM offset\n"
+  "add r9 r1 r9           ; r9 = last FB pos of wall\n"
+
+  "; draw until floor\n"
+  "RAYFX_drawVlineLoopWall:\n"
+  "  shiftrs r4 16 r11  ; r11 = texY = FPtoInt(texPos)\n"
+  "  and r11 63 r11     ; r11 = r11 & (texHeight-1)\n"
+  "  add r4 r5 r4       ; texPos += step\n"
+
+  "  multu r11 64 r11   ; r11 = texHeight * texY \n"
+  "  add r11 r6 r11     ; r11 += texX\n"
+
+  "  add r11 r12 r13    ; r13 = addr of color in texture array\n"
+  "  read 0 r13 r13     ; r13 = pixel color\n"
+
+  "  write 0 r8 r13     ; write texture pixel\n"
+  "  add r8 320 r8      ; go to next line pixel\n"
+
+  "  bge r8 r9 2        ; keep looping until reached floor\n"
+  "  jump RAYFX_drawVlineLoopWall\n"
+
+
+
+
+  "load 239 r9            ; r9 = last y position\n"
+  "multu r9 320 r9        ; r9 = screen end VRAM offset\n"
+  "add r9 r1 r9           ; r9 = last FB pos of line\n"
+
+  "load32 182 r14         ; r14 = floor color\n"
+
+  "; draw until end of screen\n"
+  "RAYFX_drawVlineLoopFloor:\n"
+  "  write 0 r8 r14    ; write floor pixel\n"
+  "  add r8 320 r8     ; go to next line pixel\n"
+
+  "  bgt r8 r9 2       ; keep looping until reached end of screen\n"
+  "  jump RAYFX_drawVlineLoopFloor\n"
+
+  );
+
+  asm(
+  "; restore registers\n"
+  "pop r15\n"
+  "pop r14\n"
+  "pop r13\n"
+  "pop r12\n"
+  "pop r11\n"
+  "pop r10\n"
+  "pop r9\n"
+  "pop r8\n"
+  "pop r1\n"
+  );
+}
+
+
+// TO ASSEMBLY:
+/*
+word y;
+for(y = 0; y < screenHeight; y++)
+{
+  if (y < drawStart)
+  {
+    fb[y][x] = 0;
+  }
+  else if (y >= drawEnd)
+  {
+    fb[y][x] = COLOR_GREY;
+  }
+  else
+  {
+    // Cast the texture coordinate to integer, and mask with (texHeight - 1) in case of overflow
+    word texY = FP_FPtoInt(texPos) & (texHeight - 1);
+    texPos += step;
+    word color = texture[texNum][texHeight * texY + texX];
+    //make color darker for y-sides: R, G and B byte each divided through two with a "shift" and an "and"
+    //if(side == 1) color = (color >> 1) & 109;
+    fb[y][x] = color;
+  }
+}
+*/
+
 int main() 
 {
   // clear screen from text
@@ -850,7 +948,7 @@ int main()
   */
 
   //x and y start position
-  fixed_point_t posX = FP_intToFP(22);
+  fixed_point_t posX = FP_intToFP(15);
   fixed_point_t posY = FP_StringToFP("11.5");
 
   //initial direction vector
@@ -863,7 +961,7 @@ int main()
 
   // rotation angle (loops at 360)
   word rotationAngle = 0;
-  word rotationSpeed = 3; // degrees per frame
+  word rotationSpeed = 5; // degrees per frame
 
   fixed_point_t moveSpeed = FP_StringToFP("0.15");
 
@@ -906,7 +1004,7 @@ int main()
       word stepY;
 
       word hit = 0; //was there a wall hit?
-      word side; //was a NS or a EW wall hit?
+      word side; //was a NorthSouth or a EastWest wall hit?
 
       //calculate step and initial sideDist
       if(rayDirX < 0)
@@ -963,9 +1061,9 @@ int main()
       word lineHeight = FP_FPtoInt(FP_Div(FP_intToFP(screenHeight), perpWallDist));
 
       //calculate lowest and highest pixel to fill in current stripe
-      word drawStart = - (lineHeight >> 1) + (screenHeight >> 1);
+      drawStart = - (lineHeight >> 1) + (screenHeight >> 1);
       if(drawStart < 0) drawStart = 0;
-      word drawEnd = (lineHeight >> 1) + (screenHeight >> 1);
+      drawEnd = (lineHeight >> 1) + (screenHeight >> 1);
       if(drawEnd >= screenHeight) drawEnd = screenHeight - 1;
 
       /*
@@ -992,7 +1090,7 @@ int main()
       */
 
       //texturing calculations
-      word texNum = worldMap[mapX][mapY] - 1; //1 subtracted from it so that texture 0 can be used!
+      texNum = worldMap[mapX][mapY] - 1; //1 subtracted from it so that texture 0 can be used!
 
       //calculate value of wallX
       fixed_point_t wallX; //where exactly the wall was hit
@@ -1011,21 +1109,14 @@ int main()
       fixed_point_t step = FP_Div(FP_intToFP(texHeight), FP_intToFP(lineHeight));
       // Starting texture coordinate
       fixed_point_t texPos = FP_Mult(FP_intToFP(drawStart - (screenHeight >> 1) + (lineHeight >> 1)), step);
-      word y;
-      for(y = drawStart; y < drawEnd; y++)
+
+      // TMP fix for first line not rendering correctly
+      if (x > 0)
       {
-        // Cast the texture coordinate to integer, and mask with (texHeight - 1) in case of overflow
-        word texY = FP_FPtoInt(texPos) & (texHeight - 1);
-        texPos += step;
-        word color = texture[texNum][texHeight * texY + texX];
-        //make color darker for y-sides: R, G and B byte each divided through two with a "shift" and an "and"
-        if(side == 1) color = (color >> 1) & 109;
-        fb[y][x] = color;
+        RAYFX_drawTextureVertLine(texPos, step, texX, x); // TODO side
       }
     }
 
-    GFX_clearPXframebuffer();
-
     // check which button is held
     if (BDOS_USBkeyHeld(BTN_LEFT))
     {