summaryrefslogtreecommitdiff
path: root/src/core/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/device.c')
-rw-r--r--src/core/device.c99
1 files changed, 70 insertions, 29 deletions
diff --git a/src/core/device.c b/src/core/device.c
index ce13c72..5ff39ef 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -459,14 +459,28 @@ void ssrU_blend(
out->a = src->a + dst->a;
}
-void ssr_bindvertices(Vertex* verts, int vert_count, uint* indices, int prim_count) {
- ssr_assert(verts && indices);
+void ssr_bindvertices(Vertex* verts, int vert_count) {
+ ssr_assert(verts);
state.verts = verts;
state.vert_count = vert_count;
+}
+
+void ssr_unbindvertices() {
+ state.verts = NULL;
+ state.vert_count = 0;
+}
+
+void ssr_bindindices(uint* indices, int prim_count) {
+ ssr_assert(indices);
state.indices = indices;
state.prim_count = prim_count;
}
+void ssr_unbindindices() {
+ state.indices = NULL;
+ state.prim_count = 0;
+}
+
void ssr_useprogram(Program* program) {
ssr_assert(program);
state.program = program;
@@ -485,11 +499,45 @@ static struct {
extern ClippedBuffer clip_buffer; /*clipping result*/
+static bool is_back_face(Vec4* c0, Vec4* c1, Vec4*c2) {
+ /*cull in ndc*/
+ float w0 = 1 / c0->w, w1 = 1 / c1->w, w2 = 1 / c2->w;
+ bool all_front = w0 > 0 && w1 > 0 && w2 > 0;
+ if (all_front)
+ {
+ Vec2 ab, ac;
+ ab.x = c1->x * w1 - c0->x * w0;
+ ab.y = c1->y * w1 - c0->y * w0;
+ ac.x = c2->x * w2 - c0->x * w0;
+ ac.y = c2->y * w2 - c0->y * w0;
+ if (ab.x * ac.y - ab.y * ac.x <= 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+ /*OpenGL algrithm*/
+ /*
+ float w0 = max(1 / c0->w, 0), w1 = 1 / c1->w, w2 = 1 / c2->w;
+ Vec2 a = { c0->x * w0, c0->y * w0 };
+ Vec2 b = { c1->x * w1, c1->y * w1 };
+ Vec2 c = { c2->x * w2, c2->y * w2 };
+ float signed_area = 0;
+ signed_area += a.x * b.y - a.y * b.x;
+ signed_area += b.x * c.y - b.y * c.x;
+ signed_area += c.x * a.y - c.y * a.x;
+ if (signed_area <= 0) {
+ return TRUE;
+ }
+ return FALSE;
+ */
+}
+
static void render_prims_triangle(uint varying_flag) {
uint i0, i1, i2;
Vec4 *c0, *c1, *c2;
bool reset_active_reg = FALSE;
bool clipped = FALSE;
+ bool is_enable_backface_cull = ssr_isenable(ENABLE_BACKFACECULL);
for (int i = 0; i < state.prim_count; ++i) {
i0 = state.indices[i * 3];
i1 = state.indices[i * 3 + 1];
@@ -501,34 +549,17 @@ static void render_prims_triangle(uint varying_flag) {
/*early back face culling*/
bool early_culled = FALSE;
- if (ssr_isenable(ENABLE_BACKFACECULL)) {
- /*cull in ndc*/
+ if (is_enable_backface_cull) {
float w0 = 1 / c0->w, w1 = 1 / c1->w, w2 = 1 / c2->w;
- bool all_front = w0 > 0 && w1 > 0 && w2 > 0;
- if (all_front)
- {
+ if (w0 <= 0 && w1 <= 0 && w2 <= 0) {
+ early_culled = TRUE;
+ continue;
+ }
+ else if (w0 > 0 && w1 > 0 && w2 > 0) {
early_culled = TRUE;
- Vec2 ab, ac;
- ab.x = c1->x * w1 - c0->x * w0;
- ab.y = c1->y * w1 - c0->y * w0;
- ac.x = c2->x * w2 - c0->x * w0;
- ac.y = c2->y * w2 - c0->y * w0;
- if (ab.x * ac.y - ab.y * ac.x <= 0) {
- continue; /*cull*/
- }
+ if (is_back_face(c0, c1, c2))
+ continue;
}
- //OpenGL algrithm:
- //float w0 = max(1 / c0->w, 0), w1 = 1 / c1->w, w2 = 1 / c2->w;
- //Vec2 a = { c0->x * w0, c0->y * w0 };
- //Vec2 b = { c1->x * w1, c1->y * w1 };
- //Vec2 c = { c2->x * w2, c2->y * w2 };
- //float signed_area = 0;
- //signed_area += a.x * b.y - a.y * b.x;
- //signed_area += b.x * c.y - b.y * c.x;
- //signed_area += c.x * a.y - c.y * a.x;
- //if (signed_area <= 0) {
- // continue; /*cull*/
- //}
}
/*clipping*/
@@ -540,7 +571,12 @@ static void render_prims_triangle(uint varying_flag) {
reset_active_reg = FALSE;
ssrS_setactiveregr();
}
- ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program, early_culled);
+ /*late back face culling*/
+ if (!early_culled && is_enable_backface_cull) {
+ if(is_back_face(c0, c1, c2))
+ continue;
+ }
+ ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program);
}
else {
if (!reset_active_reg) {
@@ -554,7 +590,12 @@ static void render_prims_triangle(uint varying_flag) {
vt2 = &clip_buffer.vertices[i + 1];
c0 = &vt0->clip_coord; c1 = &vt1->clip_coord; c2 = &vt2->clip_coord;
i0 = vt0->index; i1 = vt1->index; i2 = vt2->index;
- ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program, early_culled);
+ /*late back face culling*/
+ if (!early_culled && is_enable_backface_cull) {
+ if (is_back_face(c0, c1, c2))
+ continue;
+ }
+ ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program);
}
}
}