|
|
@ -69,6 +69,7 @@ |
|
|
|
#define GL_TEXTURE_2D 0x0DE1 |
|
|
|
#define GL_DEPTH_TEST 0x0B71 |
|
|
|
#define GL_CULL_FACE 0x0B44 |
|
|
|
#define GL_BLEND 0x0BE2 |
|
|
|
|
|
|
|
#define GL_MODELVIEW 0x1700 |
|
|
|
#define GL_PROJECTION 0x1701 |
|
|
@ -97,6 +98,18 @@ |
|
|
|
#define GL_FRONT 0x0404 |
|
|
|
#define GL_BACK 0x0405 |
|
|
|
|
|
|
|
#define GL_ZERO 0 |
|
|
|
#define GL_ONE 1 |
|
|
|
#define GL_SRC_COLOR 0x0300 |
|
|
|
#define GL_ONE_MINUS_SRC_COLOR 0x0301 |
|
|
|
#define GL_SRC_ALPHA 0x0302 |
|
|
|
#define GL_ONE_MINUS_SRC_ALPHA 0x0303 |
|
|
|
#define GL_DST_ALPHA 0x0304 |
|
|
|
#define GL_ONE_MINUS_DST_ALPHA 0x0305 |
|
|
|
#define GL_DST_COLOR 0x0306 |
|
|
|
#define GL_ONE_MINUS_DST_COLOR 0x0307 |
|
|
|
#define GL_SRC_ALPHA_SATURATE 0x0308 |
|
|
|
|
|
|
|
#define GL_NEAREST 0x2600 |
|
|
|
#define GL_LINEAR 0x2601 |
|
|
|
|
|
|
@ -124,7 +137,8 @@ |
|
|
|
typedef enum { |
|
|
|
SW_TEXTURE_2D = GL_TEXTURE_2D, |
|
|
|
SW_DEPTH_TEST = GL_DEPTH_TEST, |
|
|
|
SW_CULL_FACE = GL_CULL_FACE |
|
|
|
SW_CULL_FACE = GL_CULL_FACE, |
|
|
|
SW_BLEND = GL_BLEND |
|
|
|
} SWstate; |
|
|
|
|
|
|
|
typedef enum { |
|
|
@ -152,6 +166,20 @@ typedef enum { |
|
|
|
SW_BACK = GL_BACK, |
|
|
|
} SWface; |
|
|
|
|
|
|
|
typedef enum { |
|
|
|
SW_ZERO = GL_ZERO, |
|
|
|
SW_ONE = GL_ONE, |
|
|
|
SW_SRC_COLOR = GL_SRC_COLOR, |
|
|
|
SW_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR, |
|
|
|
SW_SRC_ALPHA = GL_SRC_ALPHA, |
|
|
|
SW_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA, |
|
|
|
SW_DST_ALPHA = GL_DST_ALPHA, |
|
|
|
SW_ONE_MINUS_DST_ALPHA = GL_ONE_MINUS_DST_ALPHA, |
|
|
|
SW_DST_COLOR = GL_DST_COLOR, |
|
|
|
SW_ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_COLOR, |
|
|
|
SW_SRC_ALPHA_SATURATE = GL_SRC_ALPHA_SATURATE |
|
|
|
} SWfactor; |
|
|
|
|
|
|
|
typedef enum { |
|
|
|
SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) |
|
|
|
SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels) |
|
|
@ -206,6 +234,7 @@ typedef enum { |
|
|
|
SW_INVALID_OPERATION = GL_INVALID_OPERATION, |
|
|
|
} SWerrcode; |
|
|
|
|
|
|
|
|
|
|
|
/* === Public API === */ |
|
|
|
|
|
|
|
void swInit(int w, int h); |
|
|
@ -232,6 +261,7 @@ void swViewport(int x, int y, int width, int height); |
|
|
|
void swClearColor(float r, float g, float b, float a); |
|
|
|
void swClear(void); |
|
|
|
|
|
|
|
void swBlendFunc(SWfactor sfactor, SWfactor dfactor); |
|
|
|
void swCullFace(SWface face); |
|
|
|
|
|
|
|
void swBegin(SWdraw mode); |
|
|
@ -294,9 +324,12 @@ void swBindTexture(uint32_t id); |
|
|
|
#define SW_DEG2RAD (SW_PI/180.0f) |
|
|
|
#define SW_RAD2DEG (180.0f/SW_PI) |
|
|
|
|
|
|
|
#define SW_STATE_CHECK(flags) ((RLSW.stateFlags & (flags)) == (flags)) |
|
|
|
|
|
|
|
#define SW_STATE_TEXTURE_2D (1 << 0) |
|
|
|
#define SW_STATE_DEPTH_TEST (1 << 1) |
|
|
|
#define SW_STATE_CULL_FACE (1 << 2) |
|
|
|
#define SW_STATE_BLEND (1 << 3) |
|
|
|
|
|
|
|
#define SW_CLIP_INSIDE (0x00) // 0000 |
|
|
|
#define SW_CLIP_LEFT (0x01) // 0001 |
|
|
@ -354,9 +387,6 @@ typedef struct { |
|
|
|
uint32_t currentTexture; |
|
|
|
sw_matrix_t *currentMatrix; |
|
|
|
|
|
|
|
uint32_t blendFunction; |
|
|
|
uint32_t depthFunction; |
|
|
|
|
|
|
|
int vpPos[2]; // Represents the top-left corner of the viewport |
|
|
|
int vpDim[2]; // Represents the dimensions of the viewport (minus one) |
|
|
|
int vpMin[2]; // Represents the minimum renderable point of the viewport (top-left) |
|
|
@ -392,6 +422,9 @@ typedef struct { |
|
|
|
SWmatrix currentMatrixMode; // Current matrix mode (e.g., sw_MODELVIEW, sw_PROJECTION) |
|
|
|
bool modelMatrixUsed; // Flag indicating if the model matrix is used |
|
|
|
|
|
|
|
SWfactor srcFactor; |
|
|
|
SWfactor dstFactor; |
|
|
|
|
|
|
|
SWface cullFace; // Faces to cull |
|
|
|
SWerrcode errCode; // Last error code |
|
|
|
|
|
|
@ -825,6 +858,144 @@ static inline void sw_texture_sample(float* color, const sw_texture_t* tex, floa |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* === Color Blending Functions === */ |
|
|
|
|
|
|
|
static inline void sw_blend_colors(float dst[4], float src[4]) |
|
|
|
{ |
|
|
|
float src_factor[4] = { 0 }; |
|
|
|
float dst_factor[4] = { 0 }; |
|
|
|
|
|
|
|
switch (RLSW.srcFactor) { |
|
|
|
case SW_ZERO: |
|
|
|
src_factor[0] = src_factor[1] = src_factor[2] = src_factor[3] = 0.0f; |
|
|
|
break; |
|
|
|
case SW_ONE: |
|
|
|
src_factor[0] = src_factor[1] = src_factor[2] = src_factor[3] = 1.0f; |
|
|
|
break; |
|
|
|
case SW_SRC_COLOR: |
|
|
|
src_factor[0] = src[0]; |
|
|
|
src_factor[1] = src[1]; |
|
|
|
src_factor[2] = src[2]; |
|
|
|
src_factor[3] = src[3]; |
|
|
|
break; |
|
|
|
case SW_ONE_MINUS_SRC_COLOR: |
|
|
|
src_factor[0] = 1.0f - src[0]; |
|
|
|
src_factor[1] = 1.0f - src[1]; |
|
|
|
src_factor[2] = 1.0f - src[2]; |
|
|
|
src_factor[3] = 1.0f - src[3]; |
|
|
|
break; |
|
|
|
case SW_SRC_ALPHA: |
|
|
|
src_factor[0] = src[3]; |
|
|
|
src_factor[1] = src[3]; |
|
|
|
src_factor[2] = src[3]; |
|
|
|
src_factor[3] = src[3]; |
|
|
|
break; |
|
|
|
case SW_ONE_MINUS_SRC_ALPHA: |
|
|
|
src_factor[0] = 1.0f - src[3]; |
|
|
|
src_factor[1] = 1.0f - src[3]; |
|
|
|
src_factor[2] = 1.0f - src[3]; |
|
|
|
src_factor[3] = 1.0f - src[3]; |
|
|
|
break; |
|
|
|
case SW_DST_ALPHA: |
|
|
|
src_factor[0] = dst[3]; |
|
|
|
src_factor[1] = dst[3]; |
|
|
|
src_factor[2] = dst[3]; |
|
|
|
src_factor[3] = dst[3]; |
|
|
|
break; |
|
|
|
case SW_ONE_MINUS_DST_ALPHA: |
|
|
|
src_factor[0] = 1.0f - dst[3]; |
|
|
|
src_factor[1] = 1.0f - dst[3]; |
|
|
|
src_factor[2] = 1.0f - dst[3]; |
|
|
|
src_factor[3] = 1.0f - dst[3]; |
|
|
|
break; |
|
|
|
case SW_DST_COLOR: |
|
|
|
src_factor[0] = dst[0]; |
|
|
|
src_factor[1] = dst[1]; |
|
|
|
src_factor[2] = dst[2]; |
|
|
|
src_factor[3] = dst[3]; |
|
|
|
break; |
|
|
|
case SW_ONE_MINUS_DST_COLOR: |
|
|
|
src_factor[0] = 1.0f - dst[0]; |
|
|
|
src_factor[1] = 1.0f - dst[1]; |
|
|
|
src_factor[2] = 1.0f - dst[2]; |
|
|
|
src_factor[3] = 1.0f - dst[3]; |
|
|
|
break; |
|
|
|
case SW_SRC_ALPHA_SATURATE: |
|
|
|
src_factor[0] = 1.0f; |
|
|
|
src_factor[1] = 1.0f; |
|
|
|
src_factor[2] = 1.0f; |
|
|
|
src_factor[3] = fminf(src[3], 1.0f); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
switch (RLSW.dstFactor) { |
|
|
|
case SW_ZERO: |
|
|
|
dst_factor[0] = dst_factor[1] = dst_factor[2] = dst_factor[3] = 0.0f; |
|
|
|
break; |
|
|
|
case SW_ONE: |
|
|
|
dst_factor[0] = dst_factor[1] = dst_factor[2] = dst_factor[3] = 1.0f; |
|
|
|
break; |
|
|
|
case SW_SRC_COLOR: |
|
|
|
dst_factor[0] = src[0]; |
|
|
|
dst_factor[1] = src[1]; |
|
|
|
dst_factor[2] = src[2]; |
|
|
|
dst_factor[3] = src[3]; |
|
|
|
break; |
|
|
|
case SW_ONE_MINUS_SRC_COLOR: |
|
|
|
dst_factor[0] = 1.0f - src[0]; |
|
|
|
dst_factor[1] = 1.0f - src[1]; |
|
|
|
dst_factor[2] = 1.0f - src[2]; |
|
|
|
dst_factor[3] = 1.0f - src[3]; |
|
|
|
break; |
|
|
|
case SW_SRC_ALPHA: |
|
|
|
dst_factor[0] = src[3]; |
|
|
|
dst_factor[1] = src[3]; |
|
|
|
dst_factor[2] = src[3]; |
|
|
|
dst_factor[3] = src[3]; |
|
|
|
break; |
|
|
|
case SW_ONE_MINUS_SRC_ALPHA: |
|
|
|
dst_factor[0] = 1.0f - src[3]; |
|
|
|
dst_factor[1] = 1.0f - src[3]; |
|
|
|
dst_factor[2] = 1.0f - src[3]; |
|
|
|
dst_factor[3] = 1.0f - src[3]; |
|
|
|
break; |
|
|
|
case SW_DST_ALPHA: |
|
|
|
dst_factor[0] = dst[3]; |
|
|
|
dst_factor[1] = dst[3]; |
|
|
|
dst_factor[2] = dst[3]; |
|
|
|
dst_factor[3] = dst[3]; |
|
|
|
break; |
|
|
|
case SW_ONE_MINUS_DST_ALPHA: |
|
|
|
dst_factor[0] = 1.0f - dst[3]; |
|
|
|
dst_factor[1] = 1.0f - dst[3]; |
|
|
|
dst_factor[2] = 1.0f - dst[3]; |
|
|
|
dst_factor[3] = 1.0f - dst[3]; |
|
|
|
break; |
|
|
|
case SW_DST_COLOR: |
|
|
|
dst_factor[0] = dst[0]; |
|
|
|
dst_factor[1] = dst[1]; |
|
|
|
dst_factor[2] = dst[2]; |
|
|
|
dst_factor[3] = dst[3]; |
|
|
|
break; |
|
|
|
case SW_ONE_MINUS_DST_COLOR: |
|
|
|
dst_factor[0] = 1.0f - dst[0]; |
|
|
|
dst_factor[1] = 1.0f - dst[1]; |
|
|
|
dst_factor[2] = 1.0f - dst[2]; |
|
|
|
dst_factor[3] = 1.0f - dst[3]; |
|
|
|
break; |
|
|
|
case SW_SRC_ALPHA_SATURATE: |
|
|
|
// NOTE: This case is only available for the source. |
|
|
|
// Since the factors are validated before assignment, |
|
|
|
// we should never reach this point. |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) { |
|
|
|
dst[i] = src_factor[i] * src[i] + dst_factor[i] * dst[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* === Projection Helper Functions === */ |
|
|
|
|
|
|
|
static inline void sw_project_ndc_to_screen(float screen[2], const float ndc[4]) |
|
|
@ -979,9 +1150,9 @@ static inline void sw_triangle_project_and_clip(sw_vertex_t polygon[SW_MAX_CLIPP |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#define DEFINE_TRIANGLE_RASTER_SCANLINE(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST) \ |
|
|
|
#define DEFINE_TRIANGLE_RASTER_SCANLINE(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \ |
|
|
|
static inline void FUNC_NAME(const sw_texture_t* tex, const sw_vertex_t* start, \ |
|
|
|
const sw_vertex_t* end, float yDu, float yDv) \ |
|
|
|
const sw_vertex_t* end, float yDu, float yDv) \ |
|
|
|
{ \ |
|
|
|
/* Calculate the horizontal width and avoid division by zero */ \ |
|
|
|
float dx = end->screen[0] - start->screen[0]; \ |
|
|
@ -1022,12 +1193,12 @@ static inline void FUNC_NAME(const sw_texture_t* tex, const sw_vertex_t* start, |
|
|
|
} \ |
|
|
|
\ |
|
|
|
/* Pre-calculate the starting pointer for the color framebuffer row */ \ |
|
|
|
uint8_t* row_ptr = (uint8_t*)((uint32_t*)RLSW.framebuffer.color + y * RLSW.framebuffer.width); \ |
|
|
|
uint8_t* dst = row_ptr + xStart * 4; \ |
|
|
|
uint8_t* cptrRow = (uint8_t*)((uint32_t*)RLSW.framebuffer.color + y * RLSW.framebuffer.width); \ |
|
|
|
uint8_t* cptr = cptrRow + xStart * 4; \ |
|
|
|
\ |
|
|
|
/* Pre-calculate the pointer for the depth buffer row */ \ |
|
|
|
uint16_t* depth_row = RLSW.framebuffer.depth + y * RLSW.framebuffer.width + xStart; \ |
|
|
|
uint16_t* dptr = depth_row; \ |
|
|
|
uint16_t* dptrRow = RLSW.framebuffer.depth + y * RLSW.framebuffer.width + xStart; \ |
|
|
|
uint16_t* dptr = dptrRow; \ |
|
|
|
\ |
|
|
|
/* Scanline rasterization loop */ \ |
|
|
|
for (int x = xStart; x < xEnd; x++) { \ |
|
|
@ -1045,32 +1216,55 @@ static inline void FUNC_NAME(const sw_texture_t* tex, const sw_vertex_t* start, |
|
|
|
/* Update the depth buffer */ \ |
|
|
|
*dptr = (uint16_t)(z * UINT16_MAX); \ |
|
|
|
\ |
|
|
|
if (ENABLE_TEXTURE) \ |
|
|
|
if (ENABLE_COLOR_BLEND) \ |
|
|
|
{ \ |
|
|
|
/* Sample the texture */ \ |
|
|
|
float texColor[4]; \ |
|
|
|
sw_texture_sample(texColor, tex, u * w, v * w, xDu, yDu, xDv, yDv); \ |
|
|
|
float dstColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; \ |
|
|
|
float srcColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; \ |
|
|
|
\ |
|
|
|
if (ENABLE_TEXTURE) { \ |
|
|
|
sw_texture_sample(srcColor, tex, u * w, v * w, xDu, yDu, xDv, yDv); \ |
|
|
|
} \ |
|
|
|
\ |
|
|
|
/* Interpolate the color and modulate by the texture color */ \ |
|
|
|
for (int i = 0; i < 4; i++) { \ |
|
|
|
float finalColor = texColor[i]; \ |
|
|
|
finalColor *= (start->color[i] + t * dcol[i]) * w; \ |
|
|
|
dst[i] = (uint8_t)(sw_saturate(finalColor) * 255.0f); \ |
|
|
|
dstColor[i] = (float)cptr[i] / 255; \ |
|
|
|
srcColor[i] *= (start->color[i] + t * dcol[i]) * w; \ |
|
|
|
} \ |
|
|
|
\ |
|
|
|
sw_blend_colors(dstColor, srcColor); \ |
|
|
|
\ |
|
|
|
for (int i = 0; i < 4; i++) { \ |
|
|
|
cptr[i] = (uint8_t)(sw_saturate(dstColor[i]) * 255); \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
else \ |
|
|
|
{ \ |
|
|
|
/* Interpolate the color */ \ |
|
|
|
for (int i = 0; i < 4; i++) { \ |
|
|
|
float finalColor = (start->color[i] + t * dcol[i]) * w; \ |
|
|
|
dst[i] = (uint8_t)(sw_saturate(finalColor) * 255.0f); \ |
|
|
|
if (ENABLE_TEXTURE) \ |
|
|
|
{ \ |
|
|
|
/* Sample the texture */ \ |
|
|
|
float texColor[4]; \ |
|
|
|
sw_texture_sample(texColor, tex, u * w, v * w, xDu, yDu, xDv, yDv); \ |
|
|
|
\ |
|
|
|
/* Interpolate the color and modulate by the texture color */ \ |
|
|
|
for (int i = 0; i < 4; i++) { \ |
|
|
|
float finalColor = texColor[i]; \ |
|
|
|
finalColor *= (start->color[i] + t * dcol[i]) * w; \ |
|
|
|
cptr[i] = (uint8_t)(sw_saturate(finalColor) * 255.0f); \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
else \ |
|
|
|
{ \ |
|
|
|
/* Interpolate the color */ \ |
|
|
|
for (int i = 0; i < 4; i++) { \ |
|
|
|
float finalColor = (start->color[i] + t * dcol[i]) * w; \ |
|
|
|
cptr[i] = (uint8_t)(sw_saturate(finalColor) * 255.0f); \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
\ |
|
|
|
/* Increment the interpolation parameter, UVs, and pointers */ \ |
|
|
|
discard: \ |
|
|
|
t += dt; \ |
|
|
|
dst += 4; \ |
|
|
|
cptr += 4; \ |
|
|
|
dptr++; \ |
|
|
|
if (ENABLE_TEXTURE) { \ |
|
|
|
u += xDu; \ |
|
|
@ -1170,15 +1364,23 @@ static inline void FUNC_NAME(const sw_vertex_t* v0, const sw_vertex_t* v1, const |
|
|
|
} \ |
|
|
|
} |
|
|
|
|
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline, false, false) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_tex, true, false) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_depth, false, true) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_tex_depth, true, true) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline, 0, 0, 0) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX, 1, 0, 0) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_DEPTH, 0, 1, 0) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_BLEND, 0, 0, 1) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_DEPTH, 1, 1, 0) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_BLEND, 1, 0, 1) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_DEPTH_BLEND, 0, 1, 1) |
|
|
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_DEPTH_BLEND, 1, 1, 1) |
|
|
|
|
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster, sw_triangle_raster_scanline, false) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_tex, sw_triangle_raster_scanline_tex, true) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_depth, sw_triangle_raster_scanline_depth, false) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_tex_depth, sw_triangle_raster_scanline_tex_depth, true) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX, sw_triangle_raster_scanline_TEX, true) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_DEPTH, sw_triangle_raster_scanline_DEPTH, false) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_BLEND, sw_triangle_raster_scanline_BLEND, false) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH, sw_triangle_raster_scanline_TEX_DEPTH, true) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND, sw_triangle_raster_scanline_TEX_BLEND, true) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND, sw_triangle_raster_scanline_DEPTH_BLEND, false) |
|
|
|
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND, sw_triangle_raster_scanline_TEX_DEPTH_BLEND, true) |
|
|
|
|
|
|
|
static inline void sw_triangle_render(const sw_vertex_t* v0, const sw_vertex_t* v1, const sw_vertex_t* v2) |
|
|
|
{ |
|
|
@ -1195,37 +1397,39 @@ static inline void sw_triangle_render(const sw_vertex_t* v0, const sw_vertex_t* |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if ((RLSW.stateFlags & SW_STATE_TEXTURE_2D) && (RLSW.stateFlags & SW_STATE_DEPTH_TEST)) { |
|
|
|
for (int i = 0; i < vertexCounter - 2; i++) { |
|
|
|
sw_triangle_raster_tex_depth( |
|
|
|
&polygon[0], &polygon[i + 1], &polygon[i + 2], |
|
|
|
&RLSW.loadedTextures[RLSW.currentTexture] |
|
|
|
); |
|
|
|
} |
|
|
|
# define TRIANGLE_RASTER(RASTER_FUNC) \ |
|
|
|
{ \ |
|
|
|
for (int i = 0; i < vertexCounter - 2; i++) { \ |
|
|
|
RASTER_FUNC( \ |
|
|
|
&polygon[0], &polygon[i + 1], &polygon[i + 2], \ |
|
|
|
&RLSW.loadedTextures[RLSW.currentTexture] \ |
|
|
|
); \ |
|
|
|
} \ |
|
|
|
} |
|
|
|
else if (RLSW.stateFlags & SW_STATE_TEXTURE_2D) { |
|
|
|
for (int i = 0; i < vertexCounter - 2; i++) { |
|
|
|
sw_triangle_raster_tex( |
|
|
|
&polygon[0], &polygon[i + 1], &polygon[i + 2], |
|
|
|
&RLSW.loadedTextures[RLSW.currentTexture] |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) { |
|
|
|
TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND) |
|
|
|
} |
|
|
|
else if (RLSW.stateFlags & SW_STATE_DEPTH_TEST) { |
|
|
|
for (int i = 0; i < vertexCounter - 2; i++) { |
|
|
|
sw_triangle_raster_depth( |
|
|
|
&polygon[0], &polygon[i + 1], &polygon[i + 2], |
|
|
|
&RLSW.loadedTextures[RLSW.currentTexture] |
|
|
|
); |
|
|
|
} |
|
|
|
else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) { |
|
|
|
TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND) |
|
|
|
} |
|
|
|
else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) { |
|
|
|
TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND) |
|
|
|
} |
|
|
|
else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) { |
|
|
|
TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH) |
|
|
|
} |
|
|
|
else if (SW_STATE_CHECK(SW_STATE_BLEND)) { |
|
|
|
TRIANGLE_RASTER(sw_triangle_raster_BLEND) |
|
|
|
} |
|
|
|
else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) { |
|
|
|
TRIANGLE_RASTER(sw_triangle_raster_DEPTH) |
|
|
|
} |
|
|
|
else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D)) { |
|
|
|
TRIANGLE_RASTER(sw_triangle_raster_TEX) |
|
|
|
} |
|
|
|
else { |
|
|
|
for (int i = 0; i < vertexCounter - 2; i++) { |
|
|
|
sw_triangle_raster( |
|
|
|
&polygon[0], &polygon[i + 1], &polygon[i + 2], |
|
|
|
&RLSW.loadedTextures[RLSW.currentTexture] |
|
|
|
); |
|
|
|
} |
|
|
|
TRIANGLE_RASTER(sw_triangle_raster) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1383,7 +1587,7 @@ bool sw_line_project_and_clip(sw_vertex_t* v0, sw_vertex_t* v1) |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
#define DEFINE_LINE_RASTER(FUNC_NAME, ENABLE_DEPTH_TEST) \ |
|
|
|
#define DEFINE_LINE_RASTER(FUNC_NAME, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \ |
|
|
|
void FUNC_NAME(const sw_vertex_t* v0, const sw_vertex_t* v1) \ |
|
|
|
{ \ |
|
|
|
int x1 = (int)v0->screen[0]; \ |
|
|
@ -1417,11 +1621,11 @@ void FUNC_NAME(const sw_vertex_t* v0, const sw_vertex_t* v1) \ |
|
|
|
int decInc = (longLen == 0) ? 0 \ |
|
|
|
: (shortLen << 16) / longLen; \ |
|
|
|
\ |
|
|
|
const int fb_width = RLSW.framebuffer.width; \ |
|
|
|
const float z_diff = z2 - z1; \ |
|
|
|
const int fbWidth = RLSW.framebuffer.width; \ |
|
|
|
const float zDiff = z2 - z1; \ |
|
|
|
\ |
|
|
|
uint8_t* color_buffer = RLSW.framebuffer.color; \ |
|
|
|
uint16_t* depth_buffer = RLSW.framebuffer.depth; \ |
|
|
|
uint8_t* colorBuffer = RLSW.framebuffer.color; \ |
|
|
|
uint16_t* depthBuffer = RLSW.framebuffer.depth; \ |
|
|
|
\ |
|
|
|
int j = 0; \ |
|
|
|
if (yLonger) { \ |
|
|
@ -1430,10 +1634,10 @@ void FUNC_NAME(const sw_vertex_t* v0, const sw_vertex_t* v1) \ |
|
|
|
\ |
|
|
|
int x = x1 + (j >> 16); \ |
|
|
|
int y = y1 + i; \ |
|
|
|
float z = z1 + t * z_diff; \ |
|
|
|
int pixel_index = y * fb_width + x; \ |
|
|
|
float z = z1 + t * zDiff; \ |
|
|
|
int pixel_index = y * fbWidth + x; \ |
|
|
|
\ |
|
|
|
uint16_t* dptr = &depth_buffer[pixel_index]; \ |
|
|
|
uint16_t* dptr = &depthBuffer[pixel_index]; \ |
|
|
|
if (ENABLE_DEPTH_TEST) { \ |
|
|
|
float depth = (float)(*dptr) / UINT16_MAX; \ |
|
|
|
if (z > depth) continue; \ |
|
|
@ -1442,11 +1646,27 @@ void FUNC_NAME(const sw_vertex_t* v0, const sw_vertex_t* v1) \ |
|
|
|
*dptr = (uint16_t)(z * UINT16_MAX); \ |
|
|
|
\ |
|
|
|
int color_index = 4 * pixel_index; \ |
|
|
|
uint8_t* cptr = &color_buffer[color_index]; \ |
|
|
|
uint8_t* cptr = &colorBuffer[color_index]; \ |
|
|
|
\ |
|
|
|
for (int j = 0; j < 4; j++) { \ |
|
|
|
float finalColor = sw_lerp(v0->color[j], v1->color[j], t); \ |
|
|
|
cptr[j] = (uint8_t)(finalColor * 255); \ |
|
|
|
if (ENABLE_COLOR_BLEND) \ |
|
|
|
{ \ |
|
|
|
float dstColor[4]; \ |
|
|
|
float srcColor[4]; \ |
|
|
|
for (int j = 0; j < 4; j++) { \ |
|
|
|
dstColor[j] = (float)cptr[i] / 255; \ |
|
|
|
srcColor[j] = sw_lerp(v0->color[j], v1->color[j], t); \ |
|
|
|
} \ |
|
|
|
sw_blend_colors(dstColor, srcColor); \ |
|
|
|
for (int j = 0; j < 4; j++) { \ |
|
|
|
cptr[j] = (uint8_t)(dstColor[j] * 255); \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
else \ |
|
|
|
{ \ |
|
|
|
for (int j = 0; j < 4; j++) { \ |
|
|
|
float finalColor = sw_lerp(v0->color[j], v1->color[j], t); \ |
|
|
|
cptr[j] = (uint8_t)(finalColor * 255); \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
@ -1456,10 +1676,10 @@ void FUNC_NAME(const sw_vertex_t* v0, const sw_vertex_t* v1) \ |
|
|
|
\ |
|
|
|
int x = x1 + i; \ |
|
|
|
int y = y1 + (j >> 16); \ |
|
|
|
float z = z1 + t * z_diff; \ |
|
|
|
int pixel_index = y * fb_width + x; \ |
|
|
|
float z = z1 + t * zDiff; \ |
|
|
|
int pixel_index = y * fbWidth + x; \ |
|
|
|
\ |
|
|
|
uint16_t* dptr = &depth_buffer[pixel_index]; \ |
|
|
|
uint16_t* dptr = &depthBuffer[pixel_index]; \ |
|
|
|
if (ENABLE_DEPTH_TEST) { \ |
|
|
|
float depth = (float)(*dptr) / UINT16_MAX; \ |
|
|
|
if (z > depth) continue; \ |
|
|
@ -1468,18 +1688,36 @@ void FUNC_NAME(const sw_vertex_t* v0, const sw_vertex_t* v1) \ |
|
|
|
*dptr = (uint16_t)(z * UINT16_MAX); \ |
|
|
|
\ |
|
|
|
int color_index = 4 * pixel_index; \ |
|
|
|
uint8_t* cptr = &color_buffer[color_index]; \ |
|
|
|
uint8_t* cptr = &colorBuffer[color_index]; \ |
|
|
|
\ |
|
|
|
for (int j = 0; j < 4; j++) { \ |
|
|
|
float finalColor = sw_lerp(v0->color[j], v1->color[j], t); \ |
|
|
|
cptr[j] = (uint8_t)(finalColor * 255); \ |
|
|
|
if (ENABLE_COLOR_BLEND) \ |
|
|
|
{ \ |
|
|
|
float dstColor[4]; \ |
|
|
|
float srcColor[4]; \ |
|
|
|
for (int j = 0; j < 4; j++) { \ |
|
|
|
dstColor[j] = (float)cptr[i] / 255; \ |
|
|
|
srcColor[j] = sw_lerp(v0->color[j], v1->color[j], t); \ |
|
|
|
} \ |
|
|
|
sw_blend_colors(dstColor, srcColor); \ |
|
|
|
for (int j = 0; j < 4; j++) { \ |
|
|
|
cptr[j] = (uint8_t)(dstColor[j] * 255); \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
else \ |
|
|
|
{ \ |
|
|
|
for (int j = 0; j < 4; j++) { \ |
|
|
|
float finalColor = sw_lerp(v0->color[j], v1->color[j], t); \ |
|
|
|
cptr[j] = (uint8_t)(finalColor * 255); \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
} |
|
|
|
|
|
|
|
DEFINE_LINE_RASTER(sw_line_raster, false) |
|
|
|
DEFINE_LINE_RASTER(sw_line_raster_depth, true) |
|
|
|
DEFINE_LINE_RASTER(sw_line_raster, 0, 0) |
|
|
|
DEFINE_LINE_RASTER(sw_line_raster_DEPTH, 1, 0) |
|
|
|
DEFINE_LINE_RASTER(sw_line_raster_BLEND, 0, 1) |
|
|
|
DEFINE_LINE_RASTER(sw_line_raster_DEPTH_BLEND, 1, 1) |
|
|
|
|
|
|
|
static inline void sw_line_render(sw_vertex_t* v0, sw_vertex_t* v1) |
|
|
|
{ |
|
|
@ -1487,8 +1725,14 @@ static inline void sw_line_render(sw_vertex_t* v0, sw_vertex_t* v1) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (RLSW.stateFlags & SW_STATE_DEPTH_TEST) { |
|
|
|
sw_line_raster_depth(v0, v1); |
|
|
|
if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) { |
|
|
|
sw_line_raster_DEPTH_BLEND(v0, v1); |
|
|
|
} |
|
|
|
else if (SW_STATE_CHECK(SW_STATE_BLEND)) { |
|
|
|
sw_line_raster_BLEND(v0, v1); |
|
|
|
} |
|
|
|
else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) { |
|
|
|
sw_line_raster_DEPTH(v0, v1); |
|
|
|
} |
|
|
|
else { |
|
|
|
sw_line_raster(v0, v1); |
|
|
@ -1523,6 +1767,54 @@ static inline bool sw_is_face_valid(int face) |
|
|
|
return (face == SW_FRONT || face == SW_BACK); |
|
|
|
} |
|
|
|
|
|
|
|
static inline bool sw_is_blend_src_factor_valid(int blend) |
|
|
|
{ |
|
|
|
bool result = false; |
|
|
|
|
|
|
|
switch (blend) { |
|
|
|
case SW_ZERO: |
|
|
|
case SW_ONE: |
|
|
|
case SW_SRC_COLOR: |
|
|
|
case SW_ONE_MINUS_SRC_COLOR: |
|
|
|
case SW_SRC_ALPHA: |
|
|
|
case SW_ONE_MINUS_SRC_ALPHA: |
|
|
|
case SW_DST_ALPHA: |
|
|
|
case SW_ONE_MINUS_DST_ALPHA: |
|
|
|
case SW_DST_COLOR: |
|
|
|
case SW_ONE_MINUS_DST_COLOR: |
|
|
|
case SW_SRC_ALPHA_SATURATE: |
|
|
|
result = true; |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
static inline bool sw_is_blend_dst_factor_valid(int blend) |
|
|
|
{ |
|
|
|
bool result = false; |
|
|
|
|
|
|
|
switch (blend) { |
|
|
|
case SW_ZERO: |
|
|
|
case SW_ONE: |
|
|
|
case SW_SRC_COLOR: |
|
|
|
case SW_ONE_MINUS_SRC_COLOR: |
|
|
|
case SW_SRC_ALPHA: |
|
|
|
case SW_ONE_MINUS_SRC_ALPHA: |
|
|
|
case SW_DST_ALPHA: |
|
|
|
case SW_ONE_MINUS_DST_ALPHA: |
|
|
|
case SW_DST_COLOR: |
|
|
|
case SW_ONE_MINUS_DST_COLOR: |
|
|
|
result = true; |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/* === Public Implementation === */ |
|
|
|
|
|
|
@ -1565,6 +1857,9 @@ void swInit(int w, int h) |
|
|
|
RLSW.vertexBuffer[0].normal[1] = 0.0f; |
|
|
|
RLSW.vertexBuffer[0].normal[2] = 1.0f; |
|
|
|
|
|
|
|
RLSW.srcFactor = SW_SRC_ALPHA; |
|
|
|
RLSW.dstFactor = SW_ONE_MINUS_SRC_ALPHA; |
|
|
|
|
|
|
|
RLSW.cullFace = SW_BACK; |
|
|
|
|
|
|
|
static const float defTex[3*2*2] = |
|
|
@ -1610,6 +1905,9 @@ void swEnable(SWstate state) |
|
|
|
case SW_CULL_FACE: |
|
|
|
RLSW.stateFlags |= SW_STATE_CULL_FACE; |
|
|
|
break; |
|
|
|
case SW_BLEND: |
|
|
|
RLSW.stateFlags |= SW_STATE_BLEND; |
|
|
|
break; |
|
|
|
default: |
|
|
|
RLSW.errCode = SW_INVALID_ENUM; |
|
|
|
break; |
|
|
@ -1628,6 +1926,9 @@ void swDisable(SWstate state) |
|
|
|
case SW_CULL_FACE: |
|
|
|
RLSW.stateFlags &= ~SW_STATE_CULL_FACE; |
|
|
|
break; |
|
|
|
case SW_BLEND: |
|
|
|
RLSW.stateFlags &= ~SW_STATE_BLEND; |
|
|
|
break; |
|
|
|
default: |
|
|
|
RLSW.errCode = SW_INVALID_ENUM; |
|
|
|
break; |
|
|
@ -1910,6 +2211,17 @@ void swClear(void) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void swBlendFunc(SWfactor sfactor, SWfactor dfactor) |
|
|
|
{ |
|
|
|
if (!sw_is_blend_src_factor_valid(sfactor) |
|
|
|
|| !sw_is_blend_dst_factor_valid(dfactor)) { |
|
|
|
RLSW.errCode = SW_INVALID_ENUM; |
|
|
|
return; |
|
|
|
} |
|
|
|
RLSW.srcFactor = sfactor; |
|
|
|
RLSW.dstFactor = dfactor; |
|
|
|
} |
|
|
|
|
|
|
|
void swCullFace(SWface face) |
|
|
|
{ |
|
|
|
if (!sw_is_face_valid(face)) { |
|
|
|