summaryrefslogtreecommitdiff
path: root/src/core/rasterizer.c
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-12-05 09:21:26 +0800
committerchai <chaifix@163.com>2019-12-05 09:21:26 +0800
commit8e684dc0c76708e3174f005aebcaabc144b85500 (patch)
treed7803e49ee1fdb5575128114d19499787f870c00 /src/core/rasterizer.c
parent2e82e2ddd0852b8063a3d6645366f53ee844e273 (diff)
*鑳岄潰鍓旈櫎
Diffstat (limited to 'src/core/rasterizer.c')
-rw-r--r--src/core/rasterizer.c159
1 files changed, 108 insertions, 51 deletions
diff --git a/src/core/rasterizer.c b/src/core/rasterizer.c
index 0c8c6eb..0e5b785 100644
--- a/src/core/rasterizer.c
+++ b/src/core/rasterizer.c
@@ -73,51 +73,88 @@ void ssrR_center(Vec2* A, Vec2* B, Vec2* C, Vec2* out) {
out->y = k * (A->y + B->y + C->y);
}
-/*
-** clipc 按列排放的三角形三个顶点的齐次裁剪坐标
-** program shader程序
-*/
+static void puttriangle(Vec2* A, Vec2* B, Vec2* C, Color c) {
+ ssr_assert(A && B && C);
+ ssrR_putline(A->x, A->y, B->x, B->y, c);
+ ssrR_putline(A->x, A->y, C->x, C->y, c);
+ ssrR_putline(C->x, C->y, B->x, B->y, 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) {
+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);
+
vec4_dividew(CA, &SA); ssrU_viewport(&SA, &SA);
vec4_dividew(CB, &SB); ssrU_viewport(&SB, &SB);
vec4_dividew(CC, &SC); ssrU_viewport(&SC, &SC);
- /*根据屏幕空间的y值排序, A的y最小,B居中,C最大*/
+
+ //puttriangle(&SA, &SB, &SC, 0xffff0000);
+ //return;
+
Vec3 *sa = &SA, *sb = &SB, *sc = &SC, *tmp; Vec4* v4tmp; Vert* vtemp;
- if (sb->y < sa->y) { sa = &SB; sb = &SA; v4tmp = CA; CA = CB; CB = v4tmp; vtemp = A; A = B; B = vtemp; }
- if (sc->y < sb->y) { tmp = sc; sc = sb; sb = tmp; v4tmp = CC; CC = CB; CB = v4tmp; vtemp = B; B = C; C = vtemp; }
- if (sc->y < sa->y) { tmp = sc; sc = sa; sa = tmp; v4tmp = CC; CC = CA; CA = v4tmp; vtemp = C; C = A; A = 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); }
+ if (sc->y < sb->y) { swap(tmp, sb, sc); swap(v4tmp, CB, CC); swap(vtemp, B, C); }
+ if (sb->y < sa->y) { swap(tmp, sa, sb); swap(v4tmp, CA, CB); swap(vtemp, A, B); }
+#undef swap
- 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);
+ 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 = 1; if (((sb->y - sa->y) / (sb->x - sa->x) - invkAC) * invkAC > 0) { order = -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;
- Vec2 l, r, p;
- float depth; Vec3 cdepth = {SA.z, SB.z, SC.z};
+ float from, to; /*scan line*/
+ Vec2 p;
+ float depth; Vec3 cdepth = {sa->z, sb->z, sc->z};
float CAw = 1.f / CA->w, CBw = 1.f / CB->w, CCw = 1.f / CC->w;
- for (p.y = sa->y; p.y <= sc->y; ++p.y) {
- l.y = p.y;
- r.y = p.y;
- if (compare(SC.y, SA.y)) r.x = sc->x;
- else r.x = sa->x + invkAC * (p.y - sa->y); /*AC*/
- if (p.y <= sb->y) {
- if (compare(SB.y, SA.y)) l.x = sb->x;
- else l.x = sa->x + invkAB * (p.y - sa->y);
- } else {
- if (compare(SC.y, SB.y)) l.x = sc->x;
- else l.x = sb->x + invkBC * (p.y - sb->y);
+ 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*/
+ }
+
+ discardif(bcp.x < 0 || bcp.y < 0 || bcp.z < 0);
+
+ 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);
+ }
+ }
+ 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;
}
- for (p.x = l.x; order * (r.x - p.x) >= 0; p.x += order) {
+ 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);
+
bcp.x *= CAw; bcp.y *= CBw; bcp.z *= CCw;
vec3_scale(&bcp, 1.f / (bcp.x + bcp.y + bcp.z), &bcp);
/*depth test*/
@@ -134,47 +171,67 @@ void _ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Pro
}
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);
+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 = min(SA.x, min(SB.x, SC.x));
- bboxmax.x = max(SA.x, max(SB.x, SC.x));
- bboxmin.y = min(SA.y, min(SB.y, SC.y));
- bboxmax.y = max(SA.y, max(SB.y, SC.y));
+
+ bboxmin.x = (int)min(SA.x, min(SB.x, SC.x)); /*这里一定要int,确保没有缝隙*/
+ 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));
+
float CAw = 1.f / CA->w, CBw = 1.f / CB->w, CCw = 1.f / CC->w;
float depth; Vec3 cdepth = { SA.z, SB.z, SC.z };
FragmentShaderIn in = { A, B, C, 0 };
- Vec2 p; Color color;
+ Vec2 p;
+ Color color;
+ 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;
+ bool dontdiscad;
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) {
- /*计算线性的(齐次裁剪空间)的重心坐标,分三步*/
- if (!ssrR_barycentric(&SA, &SB, &SC, &p, &bcp)) {
- continue; /*discard fragment*/
- }
- if (bcp.x < 0 || bcp.y < 0 || bcp.z < 0) {
- continue; /*discard fragment*/
- }
+ /*计算线性的(齐次裁剪空间)的重心坐标*/
+ 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);
+
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;
- if (!ssr_testdepthf(p.x, p.y, depth)) {
- continue; /*discard fragment*/
- }
+ discardif(!ssr_testdepthf(p.x, p.y, depth));
}
/*enter fragment shader*/
in.bc = &bcp;
- bool discad = program->fragmentshader(uniforms, &in, &color);
- if (!discad)
+ dontdiscad = program->fragmentshader(uniforms, &in, &color);
+ if (dontdiscad)
ssr_putpoint(p.x, p.y, color);
}
}
- //ssrR_putline(SA.x, SA.y, SB.x, SB.y, 0xffff0000);
- //ssrR_putline(SA.x, SA.y, SC.x, SC.y, 0xffff0000);
- //ssrR_putline(SC.x, SC.y, SB.x, SB.y, 0xffff0000);
-} \ No newline at end of file
+}
+
+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_point(Vec4* CA, Vert* A, Program* program, UniformCollection* uniforms) {
+ ssr_assert(CA && program && A && uniforms);
+
+}