summaryrefslogtreecommitdiff
path: root/src/core/rasterizer.c
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-12-23 23:59:02 +0800
committerchai <chaifix@163.com>2019-12-23 23:59:02 +0800
commitd49f3d3f73709a9a7c0bce53aa13ed28a2bd27cb (patch)
tree3fc2cca442106a56fc151c5faffbb24217ca83f5 /src/core/rasterizer.c
parentec111247c614663d8231245a17c314b9b8b4a28c (diff)
*misc
Diffstat (limited to 'src/core/rasterizer.c')
-rw-r--r--src/core/rasterizer.c145
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);
+ }
}