diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/device.c | 99 | ||||
-rw-r--r-- | src/core/device.h | 5 | ||||
-rw-r--r-- | src/core/rasterizer.c | 24 | ||||
-rw-r--r-- | src/core/rasterizer.h | 2 |
4 files changed, 80 insertions, 50 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); } } } diff --git a/src/core/device.h b/src/core/device.h index 79ffd4b..6d0b61d 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -118,9 +118,12 @@ void ssr_disable(uint mask); bool ssr_isenable(uint mask); /* 绑定顶点数据 */ -void ssr_bindvertices(Vertex* verts, int vert_count, uint* indices, int prim_count); +void ssr_bindvertices(Vertex* verts, int vert_count); void ssr_unbindvertices(); +void ssr_bindindices(uint* indices, int prim_count); +void ssr_unbindindices(); + void ssr_useprogram(Program* program); void ssr_unuseprogram(); diff --git a/src/core/rasterizer.c b/src/core/rasterizer.c index 55d4ad3..9276cbd 100644 --- a/src/core/rasterizer.c +++ b/src/core/rasterizer.c @@ -44,7 +44,7 @@ float ssrR_area(Vec2* v1, Vec2* v2, Vec2* v3) { return area; } -/*from https://github.com/ssloy/tinyrenderer */ +/*https://github.com/ssloy/tinyrenderer */ bool ssrR_barycentric(Vec2* A, Vec2* B, Vec2* C, Vec2* p, Vec3* out) { ssr_assert(A && B && C && p && out); Vec3 s[2], u; @@ -87,24 +87,10 @@ extern UniformCollection* g_uniforms ; void ssrR_triangle( Vec4* CA, Vec4* CB, Vec4* CC, uint IA, uint IB, uint IC, - Program* program, - bool early_culled + Program* program ) { ssr_assert(CA && CB && CC && program); - /*late back face culling*/ - if (!early_culled && ssr_isenable(ENABLE_BACKFACECULL)) { - float w0 = 1 / CA->w, w1 = 1 / CB->w, w2 = 1 / CC->w; - Vec2 ab, ac; - ab.x = CB->x * w1 - CA->x * w0; - ab.y = CB->y * w1 - CA->y * w0; - ac.x = CC->x * w2 - CA->x * w0; - ac.y = CC->y * w2 - CA->y * w0; - if (ab.x * ac.y - ab.y * ac.x <= 0) { - return; - } - } - UniformCollection* uniforms = g_uniforms; Vec4 SA, SB, SC; @@ -164,7 +150,7 @@ void ssrR_triangle( for (p.x = from; order * (p.x - to) <= 0; p.x += order) { \ /*calculate barycentric coordinate*/ \ s[0].z = sa->x - p.x; \ - internal_vec3_cross(&s[0], &s[1], &u); \ + internal_vec3_cross(&s[0], &s[1], &u); \ discardif(compare(u.z, 0)); \ u.z = 1.f / u.z; \ bc.x = 1.f - (u.x + u.y) * u.z; \ @@ -173,7 +159,7 @@ void ssrR_triangle( discardif(bc.x < 0 || bc.y < 0 || bc.z < 0); \ /*perspective correction*/ \ bc.x *= CAw; bc.y *= CBw; bc.z *= CCw; \ - internal_vec3_scale(&bc, 1.f / (bc.x + bc.y + bc.z), &bc); \ + internal_vec3_scale(&bc, 1.f / (bc.x + bc.y + bc.z), &bc); \ /*early depth testing*/ \ if(depth_test){ \ depth = bc.x*sa->z + bc.y*sb->z + bc.z*sc->z; \ @@ -189,7 +175,7 @@ void ssrR_triangle( /*interpolate varying variables*/ \ ssrS_solveregsbcp(&bc, IA, IB, IC); \ /*enter fragment shader*/ \ - discard = !frag_shader(out_color[0]); \ + discard = !frag_shader(out_color[0]); \ discardif(discard); \ /*put point*/ \ ssr_blendandputpoint(p.x, p.y, blend); \ diff --git a/src/core/rasterizer.h b/src/core/rasterizer.h index fce8376..c7ccc3c 100644 --- a/src/core/rasterizer.h +++ b/src/core/rasterizer.h @@ -13,7 +13,7 @@ bool ssrR_barycentric(Vec2* A, Vec2* B, Vec2* C, Vec2* p, Vec3* out); /*计算重心 void ssrR_center(Vec2* A, Vec2* B, Vec2* C, Vec2* out); /*获得重心*/ bool ssrR_ispointintriangle(Vec2* A, Vec2* B, Vec2* C, Vec2* p); -void ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, uint IA, uint IB, uint IC, Program* program, bool early_called); +void ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, uint IA, uint IB, uint IC, Program* program); void ssrR_line(Vec4* CA, Vec4* CB, uint IA, uint IB, Program* program); void ssrR_point(Vec4* CA, uint IA, Program* program); |