sr.c (6141B)
1 /* Based software renderer in one file */ 2 3 #include <stdio.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <SDL2/SDL.h> 7 8 #include "types.h" 9 #include "sr.h" 10 #include "util.h" 11 12 ivec2 13 POSITION_from_gp0(u32 val) 14 { 15 ivec2 pos; 16 pos.x = (i16)val; 17 pos.y = (i16)(val >> 16); 18 19 return pos; 20 } 21 22 C 23 COLOR_from_gp0(u32 val) 24 { 25 C c; 26 c.r = (u8)val; 27 c.g = (u8)(val >> 8); 28 c.b = (u8)(val >> 16); 29 return c; 30 } 31 32 void 33 FB_flip_vert(u32 *data) 34 { 35 u64 bytes_per_line; u32 *line; i32 half, j; 36 37 bytes_per_line = W; 38 line = (u32 *)malloc(bytes_per_line * sizeof(u32)); 39 half = H>>1; 40 41 for (j=0; j<half; j++) { 42 u64 l1 = j*bytes_per_line; 43 u64 l2 = (H-1-j)*bytes_per_line; 44 memmove((void *)line, (void *)(data+l1), bytes_per_line* sizeof(u32)); 45 memmove((void *)(data+l1), (void *)(data+l2), bytes_per_line* sizeof(u32)); 46 memmove((void *)(data+l2), (void *)line, bytes_per_line* sizeof(u32)); 47 } 48 free(line); 49 } 50 51 C 52 C_new(u32 b) 53 { 54 C c; 55 c.r = (u8)(b & 0xff); 56 c.g = (u8)((b >> 8) & 0xff); 57 c.b = (u8)((b >> 16) & 0xff); 58 return c; 59 } 60 61 void 62 REN_FB_set(REN* ren, i32 x, i32 y, u8 r, u8 g, u8 b) { 63 64 u32 *fb; 65 66 if (!ren->fb || x < 0 || y < 0 || x >= W || y >= H) return; 67 68 r = r > 255 ? 255 : r; 69 g = g > 255 ? 255 : g; 70 b = b > 255 ? 255 : b; 71 72 fb = ren->fb + (x + y * W); 73 *fb = r | (g << 8) | (b << 16); 74 } 75 76 REN* 77 REN_new(void) 78 { 79 REN* ren; 80 ren = (REN*)malloc(sizeof(REN)); 81 ren->window = SDL_CreateWindow("Ultimecia", 400 , 300, WIN_W, WIN_H, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); 82 ren->renderer = SDL_CreateRenderer(ren->window, -1, 0); 83 ren->tex = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, W, H); 84 ren->verts = (ivec2*)malloc(sizeof(ivec2) * 10000); 85 ren->colors = (C*)malloc(sizeof(C) * 10000); 86 ren->fb = (u32*)malloc(W*H*sizeof(u32)); 87 memset(ren->fb, 0, (u32)(W*H)*sizeof(u32)); 88 ren->nvertices = 0; 89 90 return ren; 91 } 92 93 void 94 draw_scanline(REN* ren, int y, int x1, C c1, int x2, C c2) 95 { 96 int dx, x; 97 float r, g, b, dr, dg, db; 98 if (x1 > x2) { 99 swap_int(&x1, &x2); 100 swap_color(&c1, &c2); 101 } 102 103 dx = x2 - x1; 104 if (dx == 0) return; 105 106 dr = (c2.r - c1.r) / (float)dx; 107 dg = (c2.g - c1.g) / (float)dx; 108 db = (c2.b - c1.b) / (float)dx; 109 110 r = c1.r, g = c1.g, b = c1.b; 111 for (x = x1; x <= x2; x++) { 112 REN_FB_set(ren, x, y, (u8)r,(u8)g,(u8)b); 113 r += dr; g += dg; b += db; 114 } 115 } 116 117 void 118 REN_triangle(REN* ren, ivec2 verts[3], C colors[3]) 119 { 120 121 i32 y, dx01, dx02, dx12, dr01, dr02, dg02, db02, dg01, db01, dr12, dg12, db12, xL, xR; 122 u32 rL, rR, gL, bL, gR, bR; 123 124 125 /* Check for degenerate triangles */ 126 if (verts[0].x == verts[1].x && verts[0].y == verts[1].y) return; 127 if (verts[1].x == verts[2].x && verts[1].y == verts[2].y) return; 128 if (verts[2].x == verts[0].x && verts[2].y == verts[0].y) return; 129 130 /* Sort vertices by y-coordinate to ensure we process from top to bottom */ 131 if (verts[0].y > verts[1].y) { swap_vec2(&verts[0], &verts[1]); swap_color(&colors[0], &colors[1]); } 132 if (verts[0].y > verts[2].y) { swap_vec2(&verts[0], &verts[2]); swap_color(&colors[0], &colors[2]); } 133 if (verts[1].y > verts[2].y) { swap_vec2(&verts[1], &verts[2]); swap_color(&colors[1], &colors[2]); } 134 135 /* Calculate edge slopes using fixed-point arithmetic */ 136 dx01 = ((verts[1].x - verts[0].x) << 16) / (verts[1].y - verts[0].y + 1); 137 dx02 = ((verts[2].x - verts[0].x) << 16) / (verts[2].y - verts[0].y + 1); 138 dx12 = ((verts[2].x - verts[1].x) << 16) / (verts[2].y - verts[1].y + 1); 139 140 /* Calculate color slopes using fixed-point arithmetic */ 141 dr01 = ((colors[1].r - colors[0].r) << 16) / (verts[1].y - verts[0].y + 1); 142 dg01 = ((colors[1].g - colors[0].g) << 16) / (verts[1].y - verts[0].y + 1); 143 db01 = ((colors[1].b - colors[0].b) << 16) / (verts[1].y - verts[0].y + 1); 144 145 dr02 = ((colors[2].r - colors[0].r) << 16) / (verts[2].y - verts[0].y + 1); 146 dg02 = ((colors[2].g - colors[0].g) << 16) / (verts[2].y - verts[0].y + 1); 147 db02 = ((colors[2].b - colors[0].b) << 16) / (verts[2].y - verts[0].y + 1); 148 149 dr12 = ((colors[2].r - colors[1].r) << 16) / (verts[2].y - verts[1].y + 1); 150 dg12 = ((colors[2].g - colors[1].g) << 16) / (verts[2].y - verts[1].y + 1); 151 db12 = ((colors[2].b - colors[1].b) << 16) / (verts[2].y - verts[1].y + 1); 152 153 /* Rasterize top part */ 154 xL = verts[0].x << 16; 155 rL = colors[0].r << 16, gL = colors[0].g << 16, bL = colors[0].b << 16; 156 xR = verts[0].x << 16; 157 rR = colors[0].r << 16, gR = colors[0].g << 16, bR = colors[0].b << 16; 158 159 for (y = verts[0].y; y < verts[1].y; y++) { 160 draw_scanline(ren, y, xL >> 16, (C){(rL >> 16), (gL >> 16), (bL >> 16)}, 161 xR >> 16, (C){(rR >> 16), (gR >> 16), (bR >> 16)}); 162 xL += dx01; rL += dr01; gL += dg01; bL += db01; 163 xR += dx02; rR += dr02; gR += dg02; bR += db02; 164 } 165 166 /* Rasterize bottom part */ 167 xL = verts[1].x << 16, rL = colors[1].r << 16, gL = colors[1].g << 16, bL = colors[1].b << 16; 168 for (y = verts[1].y; y < verts[2].y; y++) { 169 draw_scanline(ren, y, xL >> 16, (C){(u8)(rL >> 16), (u8)(gL >> 16), (u8)(bL >> 16)}, 170 xR >> 16, (C){(u8)(rR >> 16), (u8)(gR >> 16), (u8)(bR >> 16)}); 171 xL += dx12; rL += dr12; gL += dg12; bL += db12; 172 xR += dx02; rR += dr02; gR += dg02; bR += db02; 173 } 174 } 175 176 void 177 REN_push_triangle(REN* ren, ivec2 verts[3], C colors[3]) 178 { 179 u8 i; 180 181 REN_flush(ren); 182 183 for (i = 0; i < 3; i++) { 184 ren->verts[ren->nvertices] = verts[i]; 185 ren->colors[ren->nvertices] = colors[i]; 186 ren->nvertices++; 187 } 188 } 189 190 void 191 REN_push_quad(REN* ren, ivec2 verts[4], C colors[4]) 192 { 193 u8 i; 194 195 REN_flush(ren); 196 197 /* First triangle: vertices 0,1,2 */ 198 for (i = 0; i < 3; i++) { 199 ren->verts[ren->nvertices] = verts[i]; 200 ren->colors[ren->nvertices] = colors[i]; 201 ren->nvertices++; 202 } 203 for (i = 1; i < 4; i++) { 204 ren->verts[ren->nvertices] = verts[i]; 205 ren->colors[ren->nvertices] = colors[i]; 206 ren->nvertices++; 207 } 208 } 209 210 void 211 REN_flush(REN* ren) { 212 u32 i; 213 for (i = 0; i < ren->nvertices; i += 3) 214 REN_triangle(ren, ren->verts + i, ren->colors + i); 215 ren->nvertices = 0; 216 } 217 218 void 219 REN_draw(REN* ren) 220 { 221 SDL_UpdateTexture(ren->tex, NULL, ren->fb, W * sizeof(u32)); 222 SDL_RenderCopy(ren->renderer, ren->tex, NULL, NULL); 223 } 224 225 void 226 REN_display(REN* ren) 227 { 228 if (ren->nvertices > 0) 229 REN_flush(ren); 230 231 REN_draw(ren); 232 SDL_RenderPresent(ren->renderer); 233 }