impl color blending
This commit is contained in:
parent
5f92a0fcd0
commit
804240966a
472
src/external/rlsw.h
vendored
472
src/external/rlsw.h
vendored
|
|
@ -69,6 +69,7 @@
|
||||||
#define GL_TEXTURE_2D 0x0DE1
|
#define GL_TEXTURE_2D 0x0DE1
|
||||||
#define GL_DEPTH_TEST 0x0B71
|
#define GL_DEPTH_TEST 0x0B71
|
||||||
#define GL_CULL_FACE 0x0B44
|
#define GL_CULL_FACE 0x0B44
|
||||||
|
#define GL_BLEND 0x0BE2
|
||||||
|
|
||||||
#define GL_MODELVIEW 0x1700
|
#define GL_MODELVIEW 0x1700
|
||||||
#define GL_PROJECTION 0x1701
|
#define GL_PROJECTION 0x1701
|
||||||
|
|
@ -97,6 +98,18 @@
|
||||||
#define GL_FRONT 0x0404
|
#define GL_FRONT 0x0404
|
||||||
#define GL_BACK 0x0405
|
#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_NEAREST 0x2600
|
||||||
#define GL_LINEAR 0x2601
|
#define GL_LINEAR 0x2601
|
||||||
|
|
||||||
|
|
@ -124,7 +137,8 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SW_TEXTURE_2D = GL_TEXTURE_2D,
|
SW_TEXTURE_2D = GL_TEXTURE_2D,
|
||||||
SW_DEPTH_TEST = GL_DEPTH_TEST,
|
SW_DEPTH_TEST = GL_DEPTH_TEST,
|
||||||
SW_CULL_FACE = GL_CULL_FACE
|
SW_CULL_FACE = GL_CULL_FACE,
|
||||||
|
SW_BLEND = GL_BLEND
|
||||||
} SWstate;
|
} SWstate;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -152,6 +166,20 @@ typedef enum {
|
||||||
SW_BACK = GL_BACK,
|
SW_BACK = GL_BACK,
|
||||||
} SWface;
|
} 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 {
|
typedef enum {
|
||||||
SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||||
SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
|
SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
|
||||||
|
|
@ -206,6 +234,7 @@ typedef enum {
|
||||||
SW_INVALID_OPERATION = GL_INVALID_OPERATION,
|
SW_INVALID_OPERATION = GL_INVALID_OPERATION,
|
||||||
} SWerrcode;
|
} SWerrcode;
|
||||||
|
|
||||||
|
|
||||||
/* === Public API === */
|
/* === Public API === */
|
||||||
|
|
||||||
void swInit(int w, int h);
|
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 swClearColor(float r, float g, float b, float a);
|
||||||
void swClear(void);
|
void swClear(void);
|
||||||
|
|
||||||
|
void swBlendFunc(SWfactor sfactor, SWfactor dfactor);
|
||||||
void swCullFace(SWface face);
|
void swCullFace(SWface face);
|
||||||
|
|
||||||
void swBegin(SWdraw mode);
|
void swBegin(SWdraw mode);
|
||||||
|
|
@ -294,9 +324,12 @@ void swBindTexture(uint32_t id);
|
||||||
#define SW_DEG2RAD (SW_PI/180.0f)
|
#define SW_DEG2RAD (SW_PI/180.0f)
|
||||||
#define SW_RAD2DEG (180.0f/SW_PI)
|
#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_TEXTURE_2D (1 << 0)
|
||||||
#define SW_STATE_DEPTH_TEST (1 << 1)
|
#define SW_STATE_DEPTH_TEST (1 << 1)
|
||||||
#define SW_STATE_CULL_FACE (1 << 2)
|
#define SW_STATE_CULL_FACE (1 << 2)
|
||||||
|
#define SW_STATE_BLEND (1 << 3)
|
||||||
|
|
||||||
#define SW_CLIP_INSIDE (0x00) // 0000
|
#define SW_CLIP_INSIDE (0x00) // 0000
|
||||||
#define SW_CLIP_LEFT (0x01) // 0001
|
#define SW_CLIP_LEFT (0x01) // 0001
|
||||||
|
|
@ -354,9 +387,6 @@ typedef struct {
|
||||||
uint32_t currentTexture;
|
uint32_t currentTexture;
|
||||||
sw_matrix_t *currentMatrix;
|
sw_matrix_t *currentMatrix;
|
||||||
|
|
||||||
uint32_t blendFunction;
|
|
||||||
uint32_t depthFunction;
|
|
||||||
|
|
||||||
int vpPos[2]; // Represents the top-left corner of the viewport
|
int vpPos[2]; // Represents the top-left corner of the viewport
|
||||||
int vpDim[2]; // Represents the dimensions of the viewport (minus one)
|
int vpDim[2]; // Represents the dimensions of the viewport (minus one)
|
||||||
int vpMin[2]; // Represents the minimum renderable point of the viewport (top-left)
|
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)
|
SWmatrix currentMatrixMode; // Current matrix mode (e.g., sw_MODELVIEW, sw_PROJECTION)
|
||||||
bool modelMatrixUsed; // Flag indicating if the model matrix is used
|
bool modelMatrixUsed; // Flag indicating if the model matrix is used
|
||||||
|
|
||||||
|
SWfactor srcFactor;
|
||||||
|
SWfactor dstFactor;
|
||||||
|
|
||||||
SWface cullFace; // Faces to cull
|
SWface cullFace; // Faces to cull
|
||||||
SWerrcode errCode; // Last error code
|
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 === */
|
/* === Projection Helper Functions === */
|
||||||
|
|
||||||
static inline void sw_project_ndc_to_screen(float screen[2], const float ndc[4])
|
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, \
|
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 */ \
|
/* Calculate the horizontal width and avoid division by zero */ \
|
||||||
float dx = end->screen[0] - start->screen[0]; \
|
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 */ \
|
/* 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* cptrRow = (uint8_t*)((uint32_t*)RLSW.framebuffer.color + y * RLSW.framebuffer.width); \
|
||||||
uint8_t* dst = row_ptr + xStart * 4; \
|
uint8_t* cptr = cptrRow + xStart * 4; \
|
||||||
\
|
\
|
||||||
/* Pre-calculate the pointer for the depth buffer row */ \
|
/* Pre-calculate the pointer for the depth buffer row */ \
|
||||||
uint16_t* depth_row = RLSW.framebuffer.depth + y * RLSW.framebuffer.width + xStart; \
|
uint16_t* dptrRow = RLSW.framebuffer.depth + y * RLSW.framebuffer.width + xStart; \
|
||||||
uint16_t* dptr = depth_row; \
|
uint16_t* dptr = dptrRow; \
|
||||||
\
|
\
|
||||||
/* Scanline rasterization loop */ \
|
/* Scanline rasterization loop */ \
|
||||||
for (int x = xStart; x < xEnd; x++) { \
|
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 */ \
|
/* Update the depth buffer */ \
|
||||||
*dptr = (uint16_t)(z * UINT16_MAX); \
|
*dptr = (uint16_t)(z * UINT16_MAX); \
|
||||||
\
|
\
|
||||||
if (ENABLE_TEXTURE) \
|
if (ENABLE_COLOR_BLEND) \
|
||||||
{ \
|
{ \
|
||||||
/* Sample the texture */ \
|
float dstColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; \
|
||||||
float texColor[4]; \
|
float srcColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; \
|
||||||
sw_texture_sample(texColor, tex, u * w, v * w, xDu, yDu, xDv, yDv); \
|
\
|
||||||
|
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++) { \
|
for (int i = 0; i < 4; i++) { \
|
||||||
float finalColor = texColor[i]; \
|
dstColor[i] = (float)cptr[i] / 255; \
|
||||||
finalColor *= (start->color[i] + t * dcol[i]) * w; \
|
srcColor[i] *= (start->color[i] + t * dcol[i]) * w; \
|
||||||
dst[i] = (uint8_t)(sw_saturate(finalColor) * 255.0f); \
|
} \
|
||||||
|
\
|
||||||
|
sw_blend_colors(dstColor, srcColor); \
|
||||||
|
\
|
||||||
|
for (int i = 0; i < 4; i++) { \
|
||||||
|
cptr[i] = (uint8_t)(sw_saturate(dstColor[i]) * 255); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
/* Interpolate the color */ \
|
if (ENABLE_TEXTURE) \
|
||||||
for (int i = 0; i < 4; i++) { \
|
{ \
|
||||||
float finalColor = (start->color[i] + t * dcol[i]) * w; \
|
/* Sample the texture */ \
|
||||||
dst[i] = (uint8_t)(sw_saturate(finalColor) * 255.0f); \
|
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 */ \
|
/* Increment the interpolation parameter, UVs, and pointers */ \
|
||||||
discard: \
|
discard: \
|
||||||
t += dt; \
|
t += dt; \
|
||||||
dst += 4; \
|
cptr += 4; \
|
||||||
dptr++; \
|
dptr++; \
|
||||||
if (ENABLE_TEXTURE) { \
|
if (ENABLE_TEXTURE) { \
|
||||||
u += xDu; \
|
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, 0, 0, 0)
|
||||||
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_tex, true, false)
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX, 1, 0, 0)
|
||||||
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_depth, false, true)
|
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_DEPTH, 0, 1, 0)
|
||||||
DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_tex_depth, true, true)
|
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, sw_triangle_raster_scanline, false)
|
||||||
DEFINE_TRIANGLE_RASTER(sw_triangle_raster_tex, sw_triangle_raster_scanline_tex, 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_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_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)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((RLSW.stateFlags & SW_STATE_TEXTURE_2D) && (RLSW.stateFlags & SW_STATE_DEPTH_TEST)) {
|
# define TRIANGLE_RASTER(RASTER_FUNC) \
|
||||||
for (int i = 0; i < vertexCounter - 2; i++) {
|
{ \
|
||||||
sw_triangle_raster_tex_depth(
|
for (int i = 0; i < vertexCounter - 2; i++) { \
|
||||||
&polygon[0], &polygon[i + 1], &polygon[i + 2],
|
RASTER_FUNC( \
|
||||||
&RLSW.loadedTextures[RLSW.currentTexture]
|
&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++) {
|
if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) {
|
||||||
sw_triangle_raster_tex(
|
TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND)
|
||||||
&polygon[0], &polygon[i + 1], &polygon[i + 2],
|
|
||||||
&RLSW.loadedTextures[RLSW.currentTexture]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (RLSW.stateFlags & SW_STATE_DEPTH_TEST) {
|
else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) {
|
||||||
for (int i = 0; i < vertexCounter - 2; i++) {
|
TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND)
|
||||||
sw_triangle_raster_depth(
|
}
|
||||||
&polygon[0], &polygon[i + 1], &polygon[i + 2],
|
else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) {
|
||||||
&RLSW.loadedTextures[RLSW.currentTexture]
|
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 {
|
else {
|
||||||
for (int i = 0; i < vertexCounter - 2; i++) {
|
TRIANGLE_RASTER(sw_triangle_raster)
|
||||||
sw_triangle_raster(
|
|
||||||
&polygon[0], &polygon[i + 1], &polygon[i + 2],
|
|
||||||
&RLSW.loadedTextures[RLSW.currentTexture]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1383,7 +1587,7 @@ bool sw_line_project_and_clip(sw_vertex_t* v0, sw_vertex_t* v1)
|
||||||
return true;
|
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) \
|
void FUNC_NAME(const sw_vertex_t* v0, const sw_vertex_t* v1) \
|
||||||
{ \
|
{ \
|
||||||
int x1 = (int)v0->screen[0]; \
|
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 \
|
int decInc = (longLen == 0) ? 0 \
|
||||||
: (shortLen << 16) / longLen; \
|
: (shortLen << 16) / longLen; \
|
||||||
\
|
\
|
||||||
const int fb_width = RLSW.framebuffer.width; \
|
const int fbWidth = RLSW.framebuffer.width; \
|
||||||
const float z_diff = z2 - z1; \
|
const float zDiff = z2 - z1; \
|
||||||
\
|
\
|
||||||
uint8_t* color_buffer = RLSW.framebuffer.color; \
|
uint8_t* colorBuffer = RLSW.framebuffer.color; \
|
||||||
uint16_t* depth_buffer = RLSW.framebuffer.depth; \
|
uint16_t* depthBuffer = RLSW.framebuffer.depth; \
|
||||||
\
|
\
|
||||||
int j = 0; \
|
int j = 0; \
|
||||||
if (yLonger) { \
|
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 x = x1 + (j >> 16); \
|
||||||
int y = y1 + i; \
|
int y = y1 + i; \
|
||||||
float z = z1 + t * z_diff; \
|
float z = z1 + t * zDiff; \
|
||||||
int pixel_index = y * fb_width + x; \
|
int pixel_index = y * fbWidth + x; \
|
||||||
\
|
\
|
||||||
uint16_t* dptr = &depth_buffer[pixel_index]; \
|
uint16_t* dptr = &depthBuffer[pixel_index]; \
|
||||||
if (ENABLE_DEPTH_TEST) { \
|
if (ENABLE_DEPTH_TEST) { \
|
||||||
float depth = (float)(*dptr) / UINT16_MAX; \
|
float depth = (float)(*dptr) / UINT16_MAX; \
|
||||||
if (z > depth) continue; \
|
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); \
|
*dptr = (uint16_t)(z * UINT16_MAX); \
|
||||||
\
|
\
|
||||||
int color_index = 4 * pixel_index; \
|
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++) { \
|
if (ENABLE_COLOR_BLEND) \
|
||||||
float finalColor = sw_lerp(v0->color[j], v1->color[j], t); \
|
{ \
|
||||||
cptr[j] = (uint8_t)(finalColor * 255); \
|
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 x = x1 + i; \
|
||||||
int y = y1 + (j >> 16); \
|
int y = y1 + (j >> 16); \
|
||||||
float z = z1 + t * z_diff; \
|
float z = z1 + t * zDiff; \
|
||||||
int pixel_index = y * fb_width + x; \
|
int pixel_index = y * fbWidth + x; \
|
||||||
\
|
\
|
||||||
uint16_t* dptr = &depth_buffer[pixel_index]; \
|
uint16_t* dptr = &depthBuffer[pixel_index]; \
|
||||||
if (ENABLE_DEPTH_TEST) { \
|
if (ENABLE_DEPTH_TEST) { \
|
||||||
float depth = (float)(*dptr) / UINT16_MAX; \
|
float depth = (float)(*dptr) / UINT16_MAX; \
|
||||||
if (z > depth) continue; \
|
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); \
|
*dptr = (uint16_t)(z * UINT16_MAX); \
|
||||||
\
|
\
|
||||||
int color_index = 4 * pixel_index; \
|
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++) { \
|
if (ENABLE_COLOR_BLEND) \
|
||||||
float finalColor = sw_lerp(v0->color[j], v1->color[j], t); \
|
{ \
|
||||||
cptr[j] = (uint8_t)(finalColor * 255); \
|
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, 0, 0)
|
||||||
DEFINE_LINE_RASTER(sw_line_raster_depth, true)
|
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)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RLSW.stateFlags & SW_STATE_DEPTH_TEST) {
|
if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) {
|
||||||
sw_line_raster_depth(v0, v1);
|
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 {
|
else {
|
||||||
sw_line_raster(v0, v1);
|
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);
|
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 === */
|
/* === Public Implementation === */
|
||||||
|
|
||||||
|
|
@ -1565,6 +1857,9 @@ void swInit(int w, int h)
|
||||||
RLSW.vertexBuffer[0].normal[1] = 0.0f;
|
RLSW.vertexBuffer[0].normal[1] = 0.0f;
|
||||||
RLSW.vertexBuffer[0].normal[2] = 1.0f;
|
RLSW.vertexBuffer[0].normal[2] = 1.0f;
|
||||||
|
|
||||||
|
RLSW.srcFactor = SW_SRC_ALPHA;
|
||||||
|
RLSW.dstFactor = SW_ONE_MINUS_SRC_ALPHA;
|
||||||
|
|
||||||
RLSW.cullFace = SW_BACK;
|
RLSW.cullFace = SW_BACK;
|
||||||
|
|
||||||
static const float defTex[3*2*2] =
|
static const float defTex[3*2*2] =
|
||||||
|
|
@ -1610,6 +1905,9 @@ void swEnable(SWstate state)
|
||||||
case SW_CULL_FACE:
|
case SW_CULL_FACE:
|
||||||
RLSW.stateFlags |= SW_STATE_CULL_FACE;
|
RLSW.stateFlags |= SW_STATE_CULL_FACE;
|
||||||
break;
|
break;
|
||||||
|
case SW_BLEND:
|
||||||
|
RLSW.stateFlags |= SW_STATE_BLEND;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
RLSW.errCode = SW_INVALID_ENUM;
|
RLSW.errCode = SW_INVALID_ENUM;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1628,6 +1926,9 @@ void swDisable(SWstate state)
|
||||||
case SW_CULL_FACE:
|
case SW_CULL_FACE:
|
||||||
RLSW.stateFlags &= ~SW_STATE_CULL_FACE;
|
RLSW.stateFlags &= ~SW_STATE_CULL_FACE;
|
||||||
break;
|
break;
|
||||||
|
case SW_BLEND:
|
||||||
|
RLSW.stateFlags &= ~SW_STATE_BLEND;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
RLSW.errCode = SW_INVALID_ENUM;
|
RLSW.errCode = SW_INVALID_ENUM;
|
||||||
break;
|
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)
|
void swCullFace(SWface face)
|
||||||
{
|
{
|
||||||
if (!sw_is_face_valid(face)) {
|
if (!sw_is_face_valid(face)) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user