diff options
author | chai <chaifix@163.com> | 2019-12-23 23:59:02 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-12-23 23:59:02 +0800 |
commit | d49f3d3f73709a9a7c0bce53aa13ed28a2bd27cb (patch) | |
tree | 3fc2cca442106a56fc151c5faffbb24217ca83f5 /src/core/rasterizer.c | |
parent | ec111247c614663d8231245a17c314b9b8b4a28c (diff) |
*misc
Diffstat (limited to 'src/core/rasterizer.c')
-rw-r--r-- | src/core/rasterizer.c | 145 |
1 files changed, 135 insertions, 10 deletions
diff --git a/src/core/rasterizer.c b/src/core/rasterizer.c index 5618fde..a7d3544 100644 --- a/src/core/rasterizer.c +++ b/src/core/rasterizer.c @@ -1,9 +1,11 @@ -#include "rasterizer.h" +#include "rasterizer.h" #include "device.h" #include "shader.h" #include "../math/math.h" #include "../util/assert.h" +/*directly put line onto screen*/ +/*Bresenham's line algorithm*/ void ssrR_putline(int x0, int y0, int x1, int y1, Color color) { int steep = 0; if (abs(x0 - x1) < abs(y0 - y1)) { @@ -35,17 +37,17 @@ void ssrR_putline(int x0, int y0, int x1, int y1, Color color) { } } -/*ʹøμ3DѧP245*/ +/*使用辅助梯形计算三角形面积,《3D数学基础》P245*/ float ssrR_area(Vec2* v1, Vec2* v2, Vec2* v3) { ssr_assert(v1 && v2 && v3); float area = 0.5f * ((v1->y - v2->y) * (v3->x - v2->x) + (v3->y - v2->y) * (v2->x - v1->x)); return area; } -/*from https://github.com/ssloy/tinyrenderer*/ -static Vec3 s[2], u; +/*from 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; s[0].x = C->x - A->x; s[0].y = B->x - A->x; s[0].z = A->x - p->x; s[1].x = C->y - A->y; s[1].y = B->y - A->y; s[1].z = A->y - p->y; vec3_cross(&s[0], &s[1], &u); @@ -121,7 +123,6 @@ void ssrR_triangle( float CAw = 1.f / CA->w, CBw = 1.f / CB->w, CCw = 1.f / CC->w; bool depth_test = ssr_isenable(ENABLE_DEPTHTEST); - bool multi_sample = ssr_isenable(ENABLE_MULTISAMPLE); bool blend = ssr_isenable(ENABLE_BLEND); bool write_depth = ssr_isenable(ENABLE_WRITEDEPTH); bool stencil_test = ssr_isenable(ENABLE_STENCILTEST); @@ -171,7 +172,7 @@ void ssrR_triangle( } \ discardif(!pass_depth_test || !pass_stencil_test); \ /*interpolate varying variables*/ \ - ssrS_solveregs(&bc, IA, IB, IC); \ + ssrS_solveregsbcp(&bc, IA, IB, IC); \ /*enter fragment shader*/ \ discard = !frag_shader(uniforms, &ssr_frag_in, out_color[0]); \ discardif(discard); \ @@ -226,12 +227,136 @@ void ssrR_triangle( #undef RENDER_TRIANGLE } -void ssrR_line(Vec4* CA, Vec4* CB, Vert* A, Vert* B, Program* program, UniformCollection* uniforms) { - ssr_assert(CA && CB && program && A && B && uniforms); +void ssrR_line( + Vec4* CA, Vec4* CB, + uint IA, uint IB, + Program* program, + UniformCollection* uniforms +) { + ssr_assert(CA && CB && program && uniforms); + + Vec3 SA, SB; + vec4_dividew(CA, &SA); ssrU_viewport(&SA, &SA); + vec4_dividew(CB, &SB); ssrU_viewport(&SB, &SB); + + FragmentShader frag_shader = program->fragmentshader; + + int x0 = SA.x, y0 = SA.y; + int x1 = SB.x, y1 = SB.y; + float wA = 1 / CA->w, wB = 1 / CB->w; + float zA = SA.z, zB = SB.z; + + bool steep = FALSE; + if (abs(x0 - x1) < abs(y0 - y1)) { + swapi(x0, y0); + swapi(x1, y1); + steep = 1; + } + if (x0 > x1) { + swapi(x0, x1); + swapi(y0, y1); + swapi(IA, IB); + swapf(wA, wB); + swapf(zA, zB); + } + + bool depth_test = ssr_isenable(ENABLE_DEPTHTEST); + bool blend = ssr_isenable(ENABLE_BLEND); + bool write_depth = ssr_isenable(ENABLE_WRITEDEPTH); + bool stencil_test = ssr_isenable(ENABLE_STENCILTEST); + bool write_stencil = ssr_iswritesencil(); + + bool pass_depth_test = TRUE; + bool pass_stencil_test = TRUE; + bool discard = FALSE; + +#define discardif(condition) if(condition) continue + float t, depth; + Vec2 c; + int x, y, px, py; + for (x = x0; x <= x1; ++x) { + t = (x - x0) / (float)(x1 - x0); + y = y0 + (y1 - y0)*t; + /*caculate center*/ + c.x = (1 - t) * wA; + c.y = t * wB; + discardif(compare(c.x+c.y, 0)); + c.x /= (c.x + c.y); + t = 1 - c.x; + if (steep) { + px = y; + py = x; + } + else { + px = x; + py = y; + } + if (depth_test) { + ssrS_lerpnum(t, &zA, &zB, &depth); + pass_depth_test = ssr_testdepth(px, py, depth); + } + if (stencil_test) { + pass_stencil_test = ssr_teststencil(px, py, pass_depth_test); + } + discardif(!pass_depth_test || !pass_stencil_test); + /*solve registers with lerp*/ + ssrS_solveregslerp(t, IA, IB); + discard = !frag_shader(uniforms, &ssr_frag_in, out_color[0]); + discardif(discard); + /*put point*/ + ssr_blendandputpoint(px, py, blend); + /*write depth and stencil*/ + if (write_depth) { + ssr_writedepth(px, py, depth); + } + if (write_stencil) { + ssr_writestencil(px, py, pass_depth_test, pass_stencil_test); + } + } +#undef discardif } -void ssrR_point(Vec4* CA, Vert* A, Program* program, UniformCollection* uniforms) { - ssr_assert(CA && program && A && uniforms); +void ssrR_point(Vec4* CA, uint IA, Program* program, UniformCollection* uniforms) { + ssr_assert(CA && program && uniforms); + + FragmentShader frag_shader = program->fragmentshader; + + Vec3 SA; + vec4_dividew(CA, &SA); ssrU_viewport(&SA, &SA); + bool depth_test = ssr_isenable(ENABLE_DEPTHTEST); + bool blend = ssr_isenable(ENABLE_BLEND); + bool write_depth = ssr_isenable(ENABLE_WRITEDEPTH); + bool stencil_test = ssr_isenable(ENABLE_STENCILTEST); + bool write_stencil = ssr_iswritesencil(); + + bool pass_depth_test = TRUE; + bool pass_stencil_test = TRUE; + bool discard = FALSE; + +#define discardif(condition) if(condition) return ; + + int px = SA.x, py = SA.y; + float depth = SA.z; + + if (depth_test) { + pass_depth_test = ssr_testdepth(px, py, depth); + } + if (stencil_test) { + pass_stencil_test = ssr_teststencil(px, py, pass_depth_test); + } + discardif(!pass_depth_test || !pass_stencil_test); + ssrS_solveregscopy(IA); + discard = !frag_shader(uniforms, &ssr_frag_in, out_color[0]); + discardif(discard); + /*put point*/ + ssr_blendandputpoint(px, py, blend); + /*write depth and stencil*/ + if (write_depth) { + ssr_writedepth(px, py, depth); + } + if (write_stencil) { + ssr_writestencil(px, py, pass_depth_test, pass_stencil_test); + } } |