From d49f3d3f73709a9a7c0bce53aa13ed28a2bd27cb Mon Sep 17 00:00:00 2001
From: chai <chaifix@163.com>
Date: Mon, 23 Dec 2019 23:59:02 +0800
Subject: *misc

---
 src/core/rasterizer.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 135 insertions(+), 10 deletions(-)

(limited to 'src/core/rasterizer.c')

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);
+	}
 }
-- 
cgit v1.1-26-g67d0