diff options
Diffstat (limited to 'src/core/rasterizer.c')
-rw-r--r-- | src/core/rasterizer.c | 226 |
1 files changed, 159 insertions, 67 deletions
diff --git a/src/core/rasterizer.c b/src/core/rasterizer.c index 0e5b785..5503e69 100644 --- a/src/core/rasterizer.c +++ b/src/core/rasterizer.c @@ -82,18 +82,21 @@ static void puttriangle(Vec2* A, Vec2* B, Vec2* C, Color c) { #define discardif(condition) if(condition) continue -static Vec3 SA, SB, SC; // screen coords -static Vec3 bcp; // 重心坐标 -void ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Program* program, UniformCollection* uniforms) { +extern FragmentShaderIn ssr_frag_in; + +void ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, bool from_reg, ClippedVert* CVA, ClippedVert* CVB, ClippedVert* CVC, Program* program, UniformCollection* uniforms) { ssr_assert(CA && CB && CC && program); + static Vec3 SA, SB, SC; + static Vec3 bcp; + vec4_dividew(CA, &SA); ssrU_viewport(&SA, &SA); vec4_dividew(CB, &SB); ssrU_viewport(&SB, &SB); vec4_dividew(CC, &SC); ssrU_viewport(&SC, &SC); - - //puttriangle(&SA, &SB, &SC, 0xffff0000); - //return; - +/* + puttriangle(&SA, &SB, &SC, 0xffff0000); + return; +*/ Vec3 *sa = &SA, *sb = &SB, *sc = &SC, *tmp; Vec4* v4tmp; Vert* vtemp; #define swap(t, a, b) {t = a; a = b; b = t;} /*sort in y axis*/ if (sb->y < sa->y) { swap(tmp, sa, sb); swap(v4tmp, CA, CB); swap(vtemp, A, B); } @@ -102,83 +105,174 @@ void ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Prog #undef swap Vec2 AB = {sb->x - sa->x, sb->y - sa->y}, AC = { sc->x - sa->x, sc->y - sa->y }; - int order = (AB.x * AC.y - AC.x * AB.y) > 0 ? 1 : -1; /*1代表B在AC上方*/ + int order = (AB.x * AC.y - AC.x * AB.y) > 0 ? 1 : -1; float invkAC = (sc->x - sa->x) / (sc->y - sa->y + EPSILON); float invkAB = (sb->x - sa->x) / (sb->y - sa->y + EPSILON); float invkBC = (sc->x - sb->x) / (sc->y - sb->y + EPSILON); - - FragmentShaderIn in = {A, B, C, 0}; + Color color; - float from, to; /*scan line*/ + float from, to; Vec2 p; - float depth; Vec3 cdepth = {sa->z, sb->z, sc->z}; + float depth; float CAw = 1.f / CA->w, CBw = 1.f / CB->w, CCw = 1.f / CC->w; - for (p.y = sa->y; p.y < sb->y; ++p.y) { - from = (int)(invkAC * (p.y - sa->y) + sa->x); - to = (int)(invkAB * (p.y - sa->y) + sa->x); - for (p.x = from; order * (p.x - to) <= 0; p.x += order) { - - if (!ssrR_barycentric(sa, sb, sc, &p, &bcp)) { - continue; /*discard fragment*/ - } + + uint varying_flag = program->varying_flag; + +#define DO_INTERPOLATION \ + if (varying_flag & VARYING_BASIC) { \ + if (varying_flag & VARYING_POSITION) ssrS_bcpvec3(&bcp, &A->position, &B->position, &C->position, &ssr_frag_in.position); \ + if (varying_flag & VARYING_NORMAL) ssrS_bcpvec3(&bcp, &A->normal, &B->normal, &C->normal, &ssr_frag_in.normal); \ + if (varying_flag & VARYING_TANGENT) ssrS_bcpvec3(&bcp, &A->tangent, &B->tangent, &C->tangent, &ssr_frag_in.tangent); \ + if (varying_flag & VARYING_TEXCOORD) ssrS_bcpvec2(&bcp, &A->texcoord, &B->texcoord, &C->texcoord, &ssr_frag_in.texcoord); \ + if (varying_flag & VARYING_JOINT) ssrS_bcpvec4(&bcp, &A->joint, &B->joint, &C->joint, &ssr_frag_in.joint); \ + if (varying_flag & VARYING_WEIGHT) ssrS_bcpvec4(&bcp, &A->weight, &B->weight, &C->weight, &ssr_frag_in.weight); \ + if (varying_flag & VARYING_COLOR) ssrS_bcpcolor(&bcp, A->color, B->color, C->color, &ssr_frag_in.color); \ + } \ + if (from_reg) { /*extra varying*/ \ + uint i_a = A->index, i_b = B->index, i_c = C->index; \ + if (varying_flag && VARYING_NUM) { \ + if (varying_flag & VARYING_NUM_00) reg_num_00 = ssrS_bcpnum(&bcp, reg_num[0].num[i_a], reg_num[0].num[i_b], reg_num[0].num[i_c], &ssr_frag_in.num[0]); \ + if (varying_flag & VARYING_NUM_01) reg_num_01 = ssrS_bcpnum(&bcp, reg_num[1].num[i_a], reg_num[1].num[i_b], reg_num[1].num[i_c], &ssr_frag_in.num[1]); \ + if (varying_flag & VARYING_NUM_02) reg_num_02 = ssrS_bcpnum(&bcp, reg_num[2].num[i_a], reg_num[2].num[i_b], reg_num[2].num[i_c], &ssr_frag_in.num[2]); \ + if (varying_flag & VARYING_NUM_03) reg_num_03 = ssrS_bcpnum(&bcp, reg_num[3].num[i_a], reg_num[3].num[i_b], reg_num[3].num[i_c], &ssr_frag_in.num[3]); \ + } \ + if (varying_flag && VARYING_V2) { \ + if (varying_flag & VARYING_V2_00) reg_v2_00 = ssrS_bcpvec2(&bcp, ®_v2[0].v2[i_a], ®_v2[0].v2[i_b], ®_v2[0].v2[i_c], &ssr_frag_in.v2[0]); \ + if (varying_flag & VARYING_V2_01) reg_v2_01 = ssrS_bcpvec2(&bcp, ®_v2[1].v2[i_a], ®_v2[1].v2[i_b], ®_v2[1].v2[i_c], &ssr_frag_in.v2[1]); \ + if (varying_flag & VARYING_V2_02) reg_v2_02 = ssrS_bcpvec2(&bcp, ®_v2[2].v2[i_a], ®_v2[2].v2[i_b], ®_v2[2].v2[i_c], &ssr_frag_in.v2[2]); \ + if (varying_flag & VARYING_V2_03) reg_v2_03 = ssrS_bcpvec2(&bcp, ®_v2[3].v2[i_a], ®_v2[3].v2[i_b], ®_v2[3].v2[i_c], &ssr_frag_in.v2[3]); \ + if (varying_flag & VARYING_V2_04) reg_v2_04 = ssrS_bcpvec2(&bcp, ®_v2[4].v2[i_a], ®_v2[4].v2[i_b], ®_v2[4].v2[i_c], &ssr_frag_in.v2[4]); \ + if (varying_flag & VARYING_V2_05) reg_v2_05 = ssrS_bcpvec2(&bcp, ®_v2[5].v2[i_a], ®_v2[5].v2[i_b], ®_v2[5].v2[i_c], &ssr_frag_in.v2[5]); \ + } \ + if (varying_flag && VARYING_V3) { \ + if (varying_flag & VARYING_V3_00) reg_v3_00 = ssrS_bcpvec3(&bcp, ®_v3[0].v3[i_a], ®_v3[0].v3[i_b], ®_v3[0].v3[i_c], &ssr_frag_in.v3[0]); \ + if (varying_flag & VARYING_V3_01) reg_v3_01 = ssrS_bcpvec3(&bcp, ®_v3[1].v3[i_a], ®_v3[1].v3[i_b], ®_v3[1].v3[i_c], &ssr_frag_in.v3[1]); \ + if (varying_flag & VARYING_V3_02) reg_v3_02 = ssrS_bcpvec3(&bcp, ®_v3[2].v3[i_a], ®_v3[2].v3[i_b], ®_v3[2].v3[i_c], &ssr_frag_in.v3[2]); \ + if (varying_flag & VARYING_V3_03) reg_v3_03 = ssrS_bcpvec3(&bcp, ®_v3[3].v3[i_a], ®_v3[3].v3[i_b], ®_v3[3].v3[i_c], &ssr_frag_in.v3[3]); \ + if (varying_flag & VARYING_V3_04) reg_v3_04 = ssrS_bcpvec3(&bcp, ®_v3[4].v3[i_a], ®_v3[4].v3[i_b], ®_v3[4].v3[i_c], &ssr_frag_in.v3[4]); \ + if (varying_flag & VARYING_V3_05) reg_v3_05 = ssrS_bcpvec3(&bcp, ®_v3[5].v3[i_a], ®_v3[5].v3[i_b], ®_v3[5].v3[i_c], &ssr_frag_in.v3[5]); \ + if (varying_flag & VARYING_V3_06) reg_v3_06 = ssrS_bcpvec3(&bcp, ®_v3[6].v3[i_a], ®_v3[6].v3[i_b], ®_v3[6].v3[i_c], &ssr_frag_in.v3[6]); \ + if (varying_flag & VARYING_V3_07) reg_v3_07 = ssrS_bcpvec3(&bcp, ®_v3[7].v3[i_a], ®_v3[7].v3[i_b], ®_v3[7].v3[i_c], &ssr_frag_in.v3[7]); \ + } \ + if (varying_flag && VARYING_V4) { \ + if (varying_flag & VARYING_V4_00) reg_v4_00 = ssrS_bcpvec4(&bcp, ®_v4[0].v4[i_a], ®_v4[0].v4[i_b], ®_v4[0].v4[i_c], &ssr_frag_in.v4[0]); \ + if (varying_flag & VARYING_V4_01) reg_v4_01 = ssrS_bcpvec4(&bcp, ®_v4[1].v4[i_a], ®_v4[1].v4[i_b], ®_v4[1].v4[i_c], &ssr_frag_in.v4[1]); \ + if (varying_flag & VARYING_V4_02) reg_v4_02 = ssrS_bcpvec4(&bcp, ®_v4[2].v4[i_a], ®_v4[2].v4[i_b], ®_v4[2].v4[i_c], &ssr_frag_in.v4[2]); \ + if (varying_flag & VARYING_V4_03) reg_v4_03 = ssrS_bcpvec4(&bcp, ®_v4[3].v4[i_a], ®_v4[3].v4[i_b], ®_v4[3].v4[i_c], &ssr_frag_in.v4[3]); \ + if (varying_flag & VARYING_V4_04) reg_v4_04 = ssrS_bcpvec4(&bcp, ®_v4[4].v4[i_a], ®_v4[4].v4[i_b], ®_v4[4].v4[i_c], &ssr_frag_in.v4[4]); \ + if (varying_flag & VARYING_V4_05) reg_v4_05 = ssrS_bcpvec4(&bcp, ®_v4[5].v4[i_a], ®_v4[5].v4[i_b], ®_v4[5].v4[i_c], &ssr_frag_in.v4[5]); \ + } \ + } else { \ + if (varying_flag && VARYING_NUM) { \ + if (varying_flag & VARYING_NUM_00) reg_num_00 = ssrS_bcpnum(&bcp, CVA->num[0], CVB->num[0], CVC->num[0], &ssr_frag_in.num[0]); \ + if (varying_flag & VARYING_NUM_01) reg_num_01 = ssrS_bcpnum(&bcp, CVA->num[1], CVB->num[1], CVC->num[1], &ssr_frag_in.num[1]); \ + if (varying_flag & VARYING_NUM_02) reg_num_02 = ssrS_bcpnum(&bcp, CVA->num[2], CVB->num[2], CVC->num[2], &ssr_frag_in.num[2]); \ + if (varying_flag & VARYING_NUM_03) reg_num_03 = ssrS_bcpnum(&bcp, CVA->num[3], CVB->num[3], CVC->num[3], &ssr_frag_in.num[3]); \ + } \ + if (varying_flag && VARYING_V2) { \ + if (varying_flag & VARYING_V2_00) reg_v2_00 = ssrS_bcpvec2(&bcp, &CVA->v2[0], &CVB->v2[0], &CVC->v2[0], &ssr_frag_in.v2[0]); \ + if (varying_flag & VARYING_V2_01) reg_v2_01 = ssrS_bcpvec2(&bcp, &CVA->v2[1], &CVB->v2[1], &CVC->v2[1], &ssr_frag_in.v2[1]); \ + if (varying_flag & VARYING_V2_02) reg_v2_02 = ssrS_bcpvec2(&bcp, &CVA->v2[2], &CVB->v2[2], &CVC->v2[2], &ssr_frag_in.v2[2]); \ + if (varying_flag & VARYING_V2_03) reg_v2_03 = ssrS_bcpvec2(&bcp, &CVA->v2[3], &CVB->v2[3], &CVC->v2[3], &ssr_frag_in.v2[3]); \ + if (varying_flag & VARYING_V2_04) reg_v2_04 = ssrS_bcpvec2(&bcp, &CVA->v2[4], &CVB->v2[4], &CVC->v2[4], &ssr_frag_in.v2[4]); \ + if (varying_flag & VARYING_V2_05) reg_v2_05 = ssrS_bcpvec2(&bcp, &CVA->v2[5], &CVB->v2[5], &CVC->v2[5], &ssr_frag_in.v2[5]); \ + } \ + if (varying_flag && VARYING_V3) { \ + if (varying_flag & VARYING_V3_00) reg_v3_00 = ssrS_bcpvec3(&bcp, &CVA->v3[0], &CVB->v3[0], &CVC->v3[0], &ssr_frag_in.v3[0]); \ + if (varying_flag & VARYING_V3_01) reg_v3_01 = ssrS_bcpvec3(&bcp, &CVA->v3[1], &CVB->v3[1], &CVC->v3[1], &ssr_frag_in.v3[1]); \ + if (varying_flag & VARYING_V3_02) reg_v3_02 = ssrS_bcpvec3(&bcp, &CVA->v3[2], &CVB->v3[2], &CVC->v3[2], &ssr_frag_in.v3[2]); \ + if (varying_flag & VARYING_V3_03) reg_v3_03 = ssrS_bcpvec3(&bcp, &CVA->v3[3], &CVB->v3[3], &CVC->v3[3], &ssr_frag_in.v3[3]); \ + if (varying_flag & VARYING_V3_04) reg_v3_04 = ssrS_bcpvec3(&bcp, &CVA->v3[4], &CVB->v3[4], &CVC->v3[4], &ssr_frag_in.v3[4]); \ + if (varying_flag & VARYING_V3_05) reg_v3_05 = ssrS_bcpvec3(&bcp, &CVA->v3[5], &CVB->v3[5], &CVC->v3[5], &ssr_frag_in.v3[5]); \ + if (varying_flag & VARYING_V3_06) reg_v3_06 = ssrS_bcpvec3(&bcp, &CVA->v3[6], &CVB->v3[6], &CVC->v3[6], &ssr_frag_in.v3[6]); \ + if (varying_flag & VARYING_V3_07) reg_v3_07 = ssrS_bcpvec3(&bcp, &CVA->v3[7], &CVB->v3[7], &CVC->v3[7], &ssr_frag_in.v3[7]); \ + } \ + if (varying_flag && VARYING_V4) { \ + if (varying_flag & VARYING_V4_00) reg_v4_00 = ssrS_bcpvec4(&bcp, &CVA->v4[0], &CVB->v4[0], &CVC->v4[0], &ssr_frag_in.v4[0]); \ + if (varying_flag & VARYING_V4_01) reg_v4_01 = ssrS_bcpvec4(&bcp, &CVA->v4[1], &CVB->v4[1], &CVC->v4[1], &ssr_frag_in.v4[1]); \ + if (varying_flag & VARYING_V4_02) reg_v4_02 = ssrS_bcpvec4(&bcp, &CVA->v4[2], &CVB->v4[2], &CVC->v4[2], &ssr_frag_in.v4[2]); \ + if (varying_flag & VARYING_V4_03) reg_v4_03 = ssrS_bcpvec4(&bcp, &CVA->v4[3], &CVB->v4[3], &CVC->v4[3], &ssr_frag_in.v4[3]); \ + if (varying_flag & VARYING_V4_04) reg_v4_04 = ssrS_bcpvec4(&bcp, &CVA->v4[4], &CVB->v4[4], &CVC->v4[4], &ssr_frag_in.v4[4]); \ + if (varying_flag & VARYING_V4_05) reg_v4_05 = ssrS_bcpvec4(&bcp, &CVA->v4[5], &CVB->v4[5], &CVC->v4[5], &ssr_frag_in.v4[5]); \ + } \ + } - discardif(bcp.x < 0 || bcp.y < 0 || bcp.z < 0); + Vec3 s[2], u; + s[0].x = sc->x - sa->x; s[0].y = sb->x - sa->x; + s[1].x = sc->y - sa->y; s[1].y = sb->y - sa->y; + +#define RENDER_TRIANGLE \ + for (p.y = FROM->y; p.y < TO->y; ++p.y) { \ + SET_FROM_AND_TO \ + s[1].z = sa->y - p.y; \ + for (p.x = from; order * (p.x - to) <= 0; p.x += order) { \ + s[0].z = sa->x - p.x; \ + vec3_cross(&s[0], &s[1], &u); \ + discardif(compare(u.z, 0)); \ + u.z = 1.f / u.z; \ + bcp.x = 1.f - (u.x + u.y) * u.z; \ + bcp.y = u.y * u.z; \ + bcp.z = u.x * u.z; \ + discardif(bcp.x < 0 || bcp.y < 0 || bcp.z < 0); \ + /*perspective correction*/ \ + bcp.x *= CAw; bcp.y *= CBw; bcp.z *= CCw; \ + vec3_scale(&bcp, 1.f / (bcp.x + bcp.y + bcp.z), &bcp); \ + /*depth test*/ \ + depth = (bcp.x*sa->z+bcp.y*sb->z+bcp.z*sc->z) * 0.5f + 0.5f; \ + discardif(!ssr_testdepthf(p.x, p.y, depth)); \ + /*set varying variables*/ \ + DO_INTERPOLATION \ + if(program->fragmentshader(uniforms, &ssr_frag_in, &color)) \ + ssr_putpoint(p.x, p.y, color); \ + } \ + } - bcp.x *= CAw; bcp.y *= CBw; bcp.z *= CCw; - vec3_scale(&bcp, 1.f / (bcp.x + bcp.y + bcp.z), &bcp); - /*depth test*/ - depth = vec3_dot(&bcp, &cdepth) * 0.5f + 0.5f; - if (!ssr_testdepthf(p.x, p.y, depth)) { - continue; /*discard fragment*/ - } - /*enter fragment shader*/ - in.bc = &bcp; - program->fragmentshader(uniforms, &in, &color); - ssr_putpoint(p.x, p.y, color); - } +#define FROM sa +#define TO sb +#define FROMK invkAC +#define TOK invkAB +#define SET_FROM_AND_TO \ + from = (int)(invkAC * (p.y - sa->y) + sa->x); \ + to = (int)(invkAB * (p.y - sa->y) + sa->x); \ + + RENDER_TRIANGLE + +#define FROM sb +#define TO sc +#define FROMK invkAC +#define TOK invkBC +#define SET_FROM_AND_TO \ + if (p.y == sb->y && sb->y == sc->y) { \ + from = sc->x; \ + to = sb->x; \ + } \ + else { \ + from = (int)(invkAC * (p.y - sa->y) + sa->x); \ + to = (int)(invkBC * (p.y - sb->y) + sb->x); \ } - for (p.y = sb->y; p.y <= sc->y; ++p.y) { - if (p.y == sb->y && sb->y == sc->y) { - from = sc->x; - to = sb->x; - } - else { - from = (int)(invkAC * (p.y - sa->y) + sa->x); - to = (int)(invkBC * (p.y - sb->y) + sb->x); - } - for (p.x = from; order * (p.x - to) <= 0; p.x += order) { - /*计算线性的(齐次裁剪空间)的重心坐标,分三步*/ - if (!ssrR_barycentric(sa, sb, sc, &p, &bcp)) { - continue; /*discard fragment*/ - } - discardif(bcp.x < 0 || bcp.y < 0 || bcp.z < 0); + RENDER_TRIANGLE - bcp.x *= CAw; bcp.y *= CBw; bcp.z *= CCw; - vec3_scale(&bcp, 1.f / (bcp.x + bcp.y + bcp.z), &bcp); - /*depth test*/ - depth = vec3_dot(&bcp, &cdepth) * 0.5f + 0.5f; - if (!ssr_testdepthf(p.x, p.y, depth)) { - continue; /*discard fragment*/ - } - /*enter fragment shader*/ - in.bc = &bcp; - program->fragmentshader(uniforms, &in, &color); - ssr_putpoint(p.x, p.y, color); - } - } +#undef FROM +#undef TO +#undef FROMK +#undef TOK +#undef SET_FROM_AND_TO +#undef RENDER_TRIANGLE } -static Vec2 bboxmin, bboxmax; -void _ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Program* program, UniformCollection* uniforms) { +/*deprecated*/ +/* +static Vec2 bboxmin, bboxmax; +void ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Program* program, UniformCollection* uniforms) { ssr_assert(CA && CB && CC && program && A && B && C && uniforms); vec4_dividew(CA, &SA); ssrU_viewport(&SA, &SA); vec4_dividew(CB, &SB); ssrU_viewport(&SB, &SB); vec4_dividew(CC, &SC); ssrU_viewport(&SC, &SC); - bboxmin.x = (int)min(SA.x, min(SB.x, SC.x)); /*这里一定要int,确保没有缝隙*/ + bboxmin.x = (int)min(SA.x, min(SB.x, SC.x)); bboxmax.x = (int)max(SA.x, max(SB.x, SC.x)); bboxmin.y = (int)min(SA.y, min(SB.y, SC.y)); bboxmax.y = (int)max(SA.y, max(SB.y, SC.y)); @@ -195,7 +289,6 @@ void _ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Pro for (p.y = bboxmin.y; p.y <= bboxmax.y; ++p.y) { s[1].z = SA.y - p.y; for (p.x = bboxmin.x; p.x <= bboxmax.x; ++p.x) { - /*计算线性的(齐次裁剪空间)的重心坐标*/ s[0].z = SA.x - p.x; vec3_cross(&s[0], &s[1], &u); @@ -211,13 +304,11 @@ void _ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Pro bcp.x *= CAw; bcp.y *= CBw; bcp.z *= CCw; vec3_scale(&bcp, 1.f / (bcp.x + bcp.y + bcp.z), &bcp); - /*depth test*/ if (ssr_isenable(ENABLEMASK_DEPTHTEST)) { depth = vec3_dot(&bcp, &cdepth) * 0.5f + 0.5f; discardif(!ssr_testdepthf(p.x, p.y, depth)); } - /*enter fragment shader*/ in.bc = &bcp; dontdiscad = program->fragmentshader(uniforms, &in, &color); if (dontdiscad) @@ -225,6 +316,7 @@ void _ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Pro } } } +*/ void ssrR_line(Vec4* CA, Vec4* CB, Vert* A, Vert* B, Program* program, UniformCollection* uniforms) { ssr_assert(CA && CB && program && A && B && uniforms); |