summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/color.c20
-rw-r--r--src/core/color.h7
-rw-r--r--src/core/device.c339
-rw-r--r--src/core/device.h98
-rw-r--r--src/core/limits.h6
-rw-r--r--src/core/mem.c0
-rw-r--r--src/core/mem.h20
-rw-r--r--src/core/rasterizer.c180
-rw-r--r--src/core/rasterizer.h17
-rw-r--r--src/core/shader.c34
-rw-r--r--src/core/shader.h89
-rw-r--r--src/core/tris.c0
-rw-r--r--src/core/tris.h17
-rw-r--r--src/core/vert.c42
-rw-r--r--src/core/vert.h48
15 files changed, 917 insertions, 0 deletions
diff --git a/src/core/color.c b/src/core/color.c
new file mode 100644
index 0000000..45ca555
--- /dev/null
+++ b/src/core/color.c
@@ -0,0 +1,20 @@
+#include "vert.h"
+#include "device.h"
+
+Color color32_tocolor(Color32* c) {
+ return ssr_color(0xff * c->r, 0xff * c->g, 0xff * c->b, 0xff * c->a);
+}
+
+void color_tocolor32(Color c, Color32* out) {
+ out->r = COLOR_R(c) / (float)0xff;
+ out->g = COLOR_G(c) / (float)0xff;
+ out->b = COLOR_B(c) / (float)0xff;
+ out->a = COLOR_A(c) / (float)0xff;
+}
+
+void color32_saturate(Color32* c) {
+ c->r = clamp(c->r, 0, 1);
+ c->g = clamp(c->g, 0, 1);
+ c->b = clamp(c->b, 0, 1);
+ c->a = clamp(c->a, 0, 1);
+}
diff --git a/src/core/color.h b/src/core/color.h
new file mode 100644
index 0000000..1c9f45c
--- /dev/null
+++ b/src/core/color.h
@@ -0,0 +1,7 @@
+#ifndef _SOFTSHADEROOM_COLOR_H_
+#define _SOFTSHADEROOM_COLOR_H_
+
+#define COLOR_WHITE 0xffffffff
+#define COLOR_BLACK 0xff000000
+
+#endif
diff --git a/src/core/device.c b/src/core/device.c
new file mode 100644
index 0000000..f5ed4eb
--- /dev/null
+++ b/src/core/device.c
@@ -0,0 +1,339 @@
+#include "device.h"
+#include "rasterizer.h"
+#include "../util/assert.h"
+
+ssr_Config config;
+
+typedef enum ssr_VertexAttrMask {
+ VERTEXATTR_POS = 1,
+ VERTEXATTR_COLOR = 1 << 1,
+ VERTEXATTR_UV = 1 << 2,
+ VERTEXATTR_NORMAL = 1 << 3,
+} ssr_VertexAttrMask;
+
+typedef struct VertexAttr {
+ int start;
+ int offset;
+} VertexAttr;
+
+/*
+** 状态结构
+*/
+struct {
+ /* MVP矩阵栈 */
+ Mat4 matrices[3][MATRIXDEPTH];
+ uint matrixtop[3];
+ ssr_MatrixMode matrixmode;
+
+ /* 屏幕缓冲区 */
+ Color* target;
+ Color* framebuffer;
+ uint buffersize; /*framebuffer size in bytess*/
+
+ /* zbuffer 深度会被映射到0~1的非线性区间*/
+ uint* zbuffer;
+
+ /* 顶点数据 */
+ Vert** verts; uint nverts;
+ uint* indices; uint nprims;
+
+ /* shader program */
+ Program* program;
+ UniformCollection uniforms;
+
+ uint enable;
+
+} state;
+
+/*
+** MVP矩阵栈
+*/
+#define MATRIXTOP state.matrixtop[state.matrixmode]
+#define MATRIX state.matrices[state.matrixmode][MATRIXTOP]
+#define MATRIXSTACK state.matrices[state.matrixmode]
+
+#define GETMATRIX(MODE) state.matrices[MODE][state.matrixtop[MODE]]
+
+#define BUFFER (state.framebuffer)
+
+#define contains(x, y, l, r, t, b) (x >= l && x <= r && y <= b && y >= t)
+
+void ssr_init(ssr_Config* conf) {
+ config = *conf;
+ ssrM_zero(state.matrixtop, sizeof(state.matrixtop));
+ state.target = conf->target;
+ if (config.dbuffer) {
+ state.framebuffer = ssrM_newvector(Color, config.width * config.height);
+ }
+ else {
+ state.framebuffer = conf->target;
+ }
+ state.buffersize = sizeof(Color) * config.width * config.height;
+ state.zbuffer = ssrM_newvector(uint, config.width * config.height);
+ memset(state.zbuffer, 0xff, sizeof(uint)*config.width*config.height);
+}
+
+int ssr_getframebufferw() {
+ return config.width;
+}
+
+int ssr_getframebufferh() {
+ return config.height;
+}
+
+void ssr_matrixmode(ssr_MatrixMode mode) {
+ state.matrixmode = mode;
+}
+
+void ssr_loadidentity() {
+ mat4_setidentity(&MATRIX);
+}
+
+/* push进去之后会将最新的拷贝一份放在栈顶 */
+void ssr_pushmatrix() {
+ ssr_assert(MATRIXTOP < MATRIXDEPTH - 1);
+ ++MATRIXTOP;
+ MATRIX = MATRIXSTACK[MATRIXTOP - 1];
+}
+
+void ssr_popmatrix() {
+ MATRIXTOP = clamp(--MATRIXTOP, 0, MATRIXDEPTH - 1);
+}
+
+/*用来做world->view的变换矩阵*/
+/*http://warmcat.org/chai/blog/?p=559*/
+void ssr_lookat(Vec3* pos, Vec3* target, Vec3* up) {
+ ssr_assert(pos && target && up);
+ Vec3 z;
+ vec3_minus(pos, target, &z); vec3_normalize(&z, &z); /*去除缩放影响*/
+ Vec3 x;
+ vec3_cross(up, &z, &x); vec3_normalize(&x, &x);
+ Vec3 y;
+ vec3_cross(&z, &x, &y); vec3_normalize(&y, &y);
+ Mat4 m = { /*注意这里是列主序*/
+ x.x, y.x, z.x, 0,
+ x.y, y.y, z.y, 0,
+ x.z, y.z, z.z, 0,
+ -vec3_dot(&x, pos), -vec3_dot(&y, pos), -vec3_dot(&z, pos), 1
+ };
+ mat4_multiply(&MATRIX, &m, &MATRIX);
+}
+
+/* scalematrix * matrix */
+void ssr_scale(float sx, float sy, float sz) {
+ Vec3 scale = { sx, sy, sz };
+ mat4_scale(&MATRIX, &scale, &MATRIX);
+}
+
+void ssr_rotate(float angle, float x, float y, float z) {
+ Vec3 axis = { x, y, z };
+ vec3_normalize(&axis, &axis);
+ mat4_rotate(&MATRIX, angle, &axis, &MATRIX);
+}
+
+void ssr_translate(float x, float y, float z) {
+ Vec3 trans = { x, y, z };
+ mat4_translate(&MATRIX, &trans, &MATRIX);
+}
+
+void ssr_loadmatrix(Mat4* m) {
+ ssr_assert(m);
+ MATRIX = *m;
+}
+
+void ssr_multmatrix(Mat4* m) {
+ ssr_assert(m);
+ mat4_multiply(&MATRIX, m, &MATRIX);
+}
+
+void ssr_getmvp(Mat4* out) {
+ ssr_assert(out);
+ mat4_multiply(&GETMATRIX(MATRIX_VIEW), &GETMATRIX(MATRIX_MODEL), out);
+ mat4_multiply(&GETMATRIX(MATRIX_PROJECTION), out, out);
+}
+
+void ssr_getmv(Mat4* out) {
+ ssr_assert(out);
+ mat4_multiply(&GETMATRIX(MATRIX_VIEW), &GETMATRIX(MATRIX_MODEL), out);
+}
+
+void ssr_enable(uint mask) {
+ state.enable |= mask;
+}
+
+void ssr_disable(uint mask) {
+ state.enable &= (~mask);
+}
+
+bool ssr_isenable(uint mask) {
+ return state.enable & mask;
+}
+
+void ssr_viewport(float l, float r, float b, float t) {
+}
+
+void ssr_frustum(float l, float r, float b, float t, float n, float f) {
+ Mat4 m;
+ mat4_setfrustum(l, r, b, t, n, f, &m);
+ mat4_multiply(&MATRIX, &m, &MATRIX);
+}
+
+void ssr_perspective(float fov, float aspect, float n, float f) {
+ Mat4 m;
+ mat4_setperspective(fov, aspect, n, f, &m);
+ mat4_multiply(&MATRIX, &m, &MATRIX);
+}
+
+void ssr_present() {
+ if (config.dbuffer) {
+ memcpy(state.target, state.framebuffer, state.buffersize);
+ }
+}
+
+void ssr_clearcolor(Color color) {
+ if (color == 0x00) {
+ memset(state.framebuffer, 0, state.buffersize);
+ }
+ else {
+ for (int i = 0; i < config.width*config.height; ++i)
+ state.framebuffer[i] = color;
+ }
+}
+
+void ssr_cleardepth() {
+ memset(state.zbuffer, 0xff, sizeof(uint)*config.width*config.height);
+}
+
+void ssr_putpoint(uint screenx, uint screeny, Color color) {
+ if (!contains(screenx, screeny, 0, config.width - 1, 0, config.height - 1))
+ return;
+ BUFFER[screeny * config.width + screenx] = color;
+}
+
+Color ssr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
+ unsigned int c = (a << 24) | (r << 16) | (g << 8) | b;
+ return c;
+}
+
+bool ssr_testdepth(uint x, uint y, uint depth) {
+ if (!contains(x, y, 0, config.width - 1, 0, config.height - 1))
+ return 0;
+ uint off = x + y * config.width;
+ if (state.zbuffer[off] < depth)
+ return 0;
+ state.zbuffer[off] = depth;
+ return 1;
+}
+
+bool ssr_testdepthf(uint x, uint y, float depth) {
+ uint d = UINT_MAX * (double)depth;
+ return ssr_testdepth(x, y, d);
+}
+
+void ssrU_viewport(Vec2* p, Vec2* out) {
+ ssr_assert(p && out);
+ int halfw = config.width >> 1, halfh = config.height >> 1;
+ out->x = p->x * halfw + halfw + 0.5f;
+ out->y = halfh - p->y * halfh + 0.5f;
+}
+
+void ssr_bindvertices(Vert** verts, int nverts, uint* indices, int nprims) {
+ ssr_assert(verts && indices);
+ state.verts = verts;
+ state.nverts = nverts;
+ state.indices = indices;
+ state.nprims = nprims;
+}
+
+void ssr_useprogram(Program* program) {
+ ssr_assert(program);
+ state.program = program;
+}
+
+void ssr_unuseprogram() {
+ state.program = NULL;
+}
+
+static Vec4* homos = 0;
+static uint tri[3]; /*三角形三个顶点的索引*/
+static Vec3 ab, ac;
+static Mat4 mvp, mv;
+void ssr_draw(ssr_PrimitiveType primitive) {
+ ssr_assert(state.verts && state.indices);
+
+ ssr_getmvp(&mvp);
+ ssr_getmv(&mv);
+ state.uniforms.model = &GETMATRIX(MATRIX_MODEL);
+ state.uniforms.view = &GETMATRIX(MATRIX_VIEW);
+ state.uniforms.projection = &GETMATRIX(MATRIX_PROJECTION);
+ state.uniforms.mvp = &mvp;
+ state.uniforms.mv = &mv;
+
+ VertexShaderIn vertIn = { NULL };
+ if (!homos)
+ homos = ssrM_newvector(Vec4, state.nverts);
+ for (int i = 0; i < state.nverts; ++i) {
+ Vert* vert = state.verts[i];
+ vertIn.vertex = vert;
+ state.program->vertexshader(&state.uniforms, &vertIn, &homos[i]);
+ }
+
+ if (primitive == PRIMITIVE_TRIANGLE) {
+ for (int i = 0; i < state.nprims; ++i) {
+ tri[0] = state.indices[i * 3];
+ tri[1] = state.indices[i * 3 + 1];
+ tri[2] = state.indices[i * 3 + 2];
+
+ /* back face culling */
+ if (ssr_isenable(ENABLEMASK_BACKFACECULL)) {
+ vec3_minus(&homos[tri[1]], &homos[tri[0]], &ab);
+ vec3_minus(&homos[tri[2]], &homos[tri[0]], &ac);
+ if (ab.x * ac.y - ab.y * ac.x <= 0) {
+ continue;
+ }
+ }
+
+ ssrR_triangle(
+ &homos[tri[0]],
+ &homos[tri[1]],
+ &homos[tri[2]],
+ state.verts[tri[0]],
+ state.verts[tri[1]],
+ state.verts[tri[2]],
+ state.program,
+ &state.uniforms
+ );
+ }
+ }
+ else if (primitive == PRIMITIVE_POINT) {
+
+ }
+ else if (primitive == PRIMITIVE_LINE) {
+
+ }
+ //ssrM_free(homos);
+}
+
+void ssr_setuniformmat4(uint idx, Mat4* src) {
+ ssr_assert(src);
+ if (idx < 0 || idx > 7) return;
+ state.uniforms.var_mat4[idx] = *src;
+}
+
+void ssr_setuniformvec4(uint idx, Vec4* src) {
+ ssr_assert(src);
+ if (idx < 0 || idx > 7) return;
+ state.uniforms.var_vec4[idx] = *src;
+}
+
+void ssr_setuniformvec3(uint idx, Vec3* src) {
+ ssr_assert(src);
+ if (idx < 0 || idx > 7) return;
+ state.uniforms.var_vec3[idx] = *src;
+}
+
+void ssr_setuniformvec2(uint idx, Vec2* src) {
+ ssr_assert(src);
+ if (idx < 0 || idx > 7) return;
+ state.uniforms.var_vec2[idx] = *src;
+}
diff --git a/src/core/device.h b/src/core/device.h
new file mode 100644
index 0000000..aa6e73f
--- /dev/null
+++ b/src/core/device.h
@@ -0,0 +1,98 @@
+#ifndef _SOFTSHADEROOM_DEVICE_H_
+#define _SOFTSHADEROOM_DEVICE_H_
+
+#include "../math/math.h"
+#include "../util/type.h"
+#include "mem.h"
+#include "limits.h"
+#include "shader.h"
+#include "rasterizer.h"
+#include "vert.h"
+
+typedef enum ssr_MatrixMode {
+ MATRIX_MODEL = 0,
+ MATRIX_VIEW = 1,
+ MATRIX_PROJECTION = 2,
+} ssr_MatrixMode;
+
+typedef struct ssr_Config {
+ int width, height;
+ bool dbuffer;/* double buffer? */
+ Color* target; /* screen target buffer */
+} ssr_Config;
+
+typedef enum ssr_PrimitiveType {
+ PRIMITIVE_POINT,
+ PRIMITIVE_LINE,
+ PRIMITIVE_TRIANGLE,
+} ssr_PrimitiveType;
+
+typedef enum ssr_EnableMask {
+ ENABLEMASK_BACKFACECULL = 1 ,
+ ENABLEMASK_DEPTHTEST = 1 << 1,
+} ssr_EnableMask;
+
+void ssr_init(ssr_Config* config);
+
+int ssr_getframebufferw();
+int ssr_getframebufferh();
+
+void ssr_matrixmode(ssr_MatrixMode mode);
+void ssr_loadidentity();
+void ssr_pushmatrix();
+void ssr_popmatrix();
+void ssr_lookat(Vec3* pos, Vec3* target, Vec3* up);
+
+/*后乘,意味着这些操作会被率先应用到物体上,应该按照反向顺序调用这些函数*/
+void ssr_translate(float x, float y, float z);
+void ssr_rotate(float angle, float x, float y, float z);
+void ssr_scale(float sx, float sy, float sz);
+
+void ssr_multmatrix(Mat4* m);/*右乘矩阵*/
+void ssr_loadmatrix(Mat4* m);
+void ssr_frustum(float l, float r, float b, float t, float n, float f);
+void ssr_perspective(float fov, float aspect, float n, float f);
+
+void ssr_viewport(float l, float r, float b, float t);
+
+void ssr_getmv(Mat4* out);
+void ssr_getmvp(Mat4* out);
+
+void ssr_enable(uint mask);
+void ssr_disable(uint mask);
+bool ssr_isenable(uint mask);
+
+/* 绑定顶点数据 */
+void ssr_bindvertices(Vert** verts, int nverts, uint* indices, int nprims);
+void ssr_unbindvertices();
+
+void ssr_useprogram(Program* program);
+void ssr_unuseprogram();
+
+void ssr_setuniformmat4(uint idx, Mat4* src);
+void ssr_setuniformvec4(uint idx, Vec4* src);
+void ssr_setuniformvec3(uint idx, Vec3* src);
+void ssr_setuniformvec2(uint idx, Vec2* src);
+
+void ssr_draw(ssr_PrimitiveType primitive);
+void ssr_clearcolor(Color color);
+void ssr_cleardepth();
+
+/*直接绘制到缓冲区*/
+void ssr_putpoint(uint screenx, uint screeny, Color color); /*直接修改某个位置的颜色*/
+
+void ssr_present();
+
+Color ssr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+
+//bool ssr_cutline(int* x0, int* y0, int* x1, int* y1);
+
+bool ssr_testdepth(uint x, uint y, uint depth); /*尝试写入深度,如果可绘制返回true,否则discard*/
+bool ssr_testdepthf(uint x, uint y, float depth01);
+
+/*
+** Utils
+*/
+void ssrU_viewport(Vec2* p, Vec2* out);
+
+#endif \ No newline at end of file
diff --git a/src/core/limits.h b/src/core/limits.h
new file mode 100644
index 0000000..4ef0b75
--- /dev/null
+++ b/src/core/limits.h
@@ -0,0 +1,6 @@
+#ifndef _SOFTSHADEROOM_LIMITS_H_
+#define _SOFTSHADEROOM_LIMITS_H_
+
+#define MATRIXDEPTH 32
+
+#endif \ No newline at end of file
diff --git a/src/core/mem.c b/src/core/mem.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/core/mem.c
diff --git a/src/core/mem.h b/src/core/mem.h
new file mode 100644
index 0000000..1a763f9
--- /dev/null
+++ b/src/core/mem.h
@@ -0,0 +1,20 @@
+#ifndef _SOFTSHADEROOM_MEM_H_
+#define _SOFTSHADEROOM_MEM_H_
+
+#include <memory.h>
+
+/*
+** 内存分配相关
+*/
+
+void ssrM_freemem();
+void ssrM_realloc();
+
+#define ssrM_zero(obj, size) memset(obj, 0, size)
+#define ssrM_new(T) (T*)malloc(sizeof(T))
+#define ssrM_newvector(T, c) ((T*)calloc(c, sizeof(T)))
+#define ssrM_free(obj) free(obj)
+
+#define cast(v, T) (*(T*)(&v))
+
+#endif \ No newline at end of file
diff --git a/src/core/rasterizer.c b/src/core/rasterizer.c
new file mode 100644
index 0000000..0c8c6eb
--- /dev/null
+++ b/src/core/rasterizer.c
@@ -0,0 +1,180 @@
+#include "rasterizer.h"
+#include "device.h"
+#include "shader.h"
+#include "../math/math.h"
+#include "../util/assert.h"
+
+void ssrR_putline(int x0, int y0, int x1, int y1, Color color) {
+ int steep = 0;
+ if (abs(x0 - x1) < abs(y0 - y1)) {
+ swapi(x0, y0);
+ swapi(x1, y1);
+ steep = 1;
+ }
+ if (x0 > x1) {
+ swapi(x0, x1);
+ swapi(y0, y1);
+ }
+ int dx = x1 - x0;
+ int dy = y1 - y0;
+ int derror2 = abs(dy) << 1;
+ int error2 = 0;
+ int y = y0;
+ for (int x = x0; x <= x1; ++x) {
+ if (steep) {
+ ssr_putpoint(y, x, color);
+ }
+ else {
+ ssr_putpoint(x, y, color);
+ }
+ error2 += derror2;
+ if (error2 > dx) {
+ y += (y1 > y0 ? 1 : -1);
+ error2 -= (dx << 1);
+ }
+ }
+}
+
+/*使用辅助梯形计算三角形面积,《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;
+bool ssrR_barycentric(Vec2* A, Vec2* B, Vec2* C, Vec2* p, Vec3* out) {
+ ssr_assert(A && B && C && p && out);
+ 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);
+ if (compare(u.z, 0)) {
+ return 0;
+ } else {
+ float uz = 1.f / u.z;
+ out->x = 1 - (u.x + u.y) * uz;
+ out->y = u.y * uz;
+ out->z = u.x * uz;
+ return 1;
+ }
+}
+
+bool ssrR_ispointintriangle(Vec2* A, Vec2* B, Vec2* C, Vec2* p) {
+ ssr_assert(A && B && C && p);
+ Vec3 c; ssrR_barycentric(A, B, C, p, &c);
+ return c.x >= 0 && c.y >= 0 && c.z >= 0;
+}
+
+void ssrR_center(Vec2* A, Vec2* B, Vec2* C, Vec2* out) {
+ ssr_assert(A && B && C && out);
+ float k = 1 / 3.f;
+ out->x = k * (A->x + B->x + C->x);
+ out->y = k * (A->y + B->y + C->y);
+}
+
+/*
+** clipc 按列排放的三角形三个顶点的齐次裁剪坐标
+** program shader程序
+*/
+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) {
+ 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最大*/
+ 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; }
+
+ 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);
+
+ int order = 1; if (((sb->y - sa->y) / (sb->x - sa->x) - invkAC) * invkAC > 0) { order = -1; }
+
+ FragmentShaderIn in = {A, B, C, 0};
+ Color color;
+ Vec2 l, r, 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.x = l.x; order * (r.x - p.x) >= 0; p.x += order) {
+ /*计算线性的(齐次裁剪空间)的重心坐标,分三步*/
+ if (!ssrR_barycentric(sa, sb, sc, &p, &bcp)) {
+ continue; /*discard fragment*/
+ }
+ 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);
+ }
+ }
+}
+
+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);
+ 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));
+ 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;
+ for (p.y = bboxmin.y; p.y <= bboxmax.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*/
+ }
+ bcp.x *= CAw; bcp.y *= CBw; bcp.z *= CCw;
+ vec3_scale(&bcp, 1.f / (bcp.x + bcp.y + bcp.z), &bcp);
+
+ /*深度测试*/
+ 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*/
+ }
+ }
+
+ /*enter fragment shader*/
+ in.bc = &bcp;
+ bool discad = program->fragmentshader(uniforms, &in, &color);
+ if (!discad)
+ 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
diff --git a/src/core/rasterizer.h b/src/core/rasterizer.h
new file mode 100644
index 0000000..e35b24a
--- /dev/null
+++ b/src/core/rasterizer.h
@@ -0,0 +1,17 @@
+#ifndef _SOFTSHADEROOM_GEOMETRY_H_
+#define _SOFTSHADEROOM_GEOMETRY_H_
+
+#include "../math/math.h"
+#include "shader.h"
+
+void ssrR_putline(int x0, int y0, int x1, int y1, Color color);
+
+float ssrR_area(Vec2* v1, Vec2* v2, Vec2* v3); /*计算三角形面积,注意v1v2v3按逆时针顺序定义*/
+
+bool ssrR_barycentric(Vec2* A, Vec2* B, Vec2* C, Vec2* p, Vec3* out); /*计算重心坐标*/
+void ssrR_center(Vec2* A, Vec2* B, Vec2* C, Vec2* out); /*获得重心*/
+bool ssrR_ispointintriangle(Vec2* A, Vec2* B, Vec2* C, Vec2* p);
+
+void ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Program* program, UniformCollection* uniforms); /*绘制三角形图元*/
+
+#endif \ No newline at end of file
diff --git a/src/core/shader.c b/src/core/shader.c
new file mode 100644
index 0000000..fe25408
--- /dev/null
+++ b/src/core/shader.c
@@ -0,0 +1,34 @@
+#include "shader.h"
+#include "vert.h"
+#include "device.h"
+
+void ssrS_bcpcolor(Vec3* bc, Color A, Color B, Color C, Color* out) {
+ ssr_assert(bc && out);
+ *out = ssr_color(
+ bc->A * COLOR_R(A) + bc->B * COLOR_R(B) + bc->C * COLOR_R(C),
+ bc->A * COLOR_G(A) + bc->B * COLOR_G(B) + bc->C * COLOR_G(C),
+ bc->A * COLOR_B(A) + bc->B * COLOR_B(B) + bc->C * COLOR_B(C),
+ bc->A * COLOR_A(A) + bc->B * COLOR_A(B) + bc->C * COLOR_A(C)
+ );
+}
+
+void ssrS_bcpvec2(Vec3* bc, Vec2* A, Vec2* B, Vec2* C, Vec2* out) {
+ ssr_assert(bc && A && B && C && out);
+ out->x = bc->A * A->x + bc->B * B->x + bc->C * C->x;
+ out->y = bc->A * A->y + bc->B * B->y + bc->C * C->y;
+}
+
+void ssrS_bcpvec3(Vec3* bc, Vec3* A, Vec3* B, Vec3* C, Vec3* out) {
+ ssr_assert(bc && A && B && C && out);
+ out->x = bc->A * A->x + bc->B * B->x + bc->C * C->x;
+ out->y = bc->A * A->y + bc->B * B->y + bc->C * C->y;
+ out->z = bc->A * A->z + bc->B * B->z + bc->C * C->z;
+}
+
+void ssrS_bcpvec4(Vec3* bc, Vec4* A, Vec4* B, Vec4* C, Vec4* out) {
+ ssr_assert(bc && A && B && C && out);
+ out->x = bc->A * A->x + bc->B * B->x + bc->C * C->x;
+ out->y = bc->A * A->y + bc->B * B->y + bc->C * C->y;
+ out->z = bc->A * A->z + bc->B * B->z + bc->C * C->z;
+ out->w = bc->A * A->w + bc->B * B->w + bc->C * C->w;
+}
diff --git a/src/core/shader.h b/src/core/shader.h
new file mode 100644
index 0000000..8da8ae3
--- /dev/null
+++ b/src/core/shader.h
@@ -0,0 +1,89 @@
+#ifndef _SOFTSHADEROOM_SHADER_H_
+#define _SOFTSHADEROOM_SHADER_H_
+
+#include "../math/math.h"
+#include "vert.h"
+
+typedef struct UniformCollection {
+ /*built in varaibles*/
+ Mat4* model;
+ Mat4* view;
+ Mat4* projection;
+ Mat4* mvp;
+ Mat4* mv;
+ /*userside variables*/
+ Mat4 var_mat4[8];
+ Vec4 var_vec4[8];
+ Vec3 var_vec3[8];
+ Vec2 var_vec2[8];
+} UniformCollection;
+
+#define ssrum4(i) (uniforms->var_mat4[i])
+#define ssruv2(i) (uniforms->var_vec2[i])
+#define ssruv3(i) (uniforms->var_vec3[i])
+#define ssruv4(i) (uniforms->var_vec4[i])
+
+typedef struct VertexShaderIn {
+ Vert* vertex;
+} VertexShaderIn;
+
+typedef void(*VertexShader)(UniformCollection* uniforms, VertexShaderIn* in, Vec4* homocoord);
+
+typedef struct FragmentShaderIn {
+ Vert *A, *B, *C;
+ Vec3* bc;
+} FragmentShaderIn;
+
+typedef bool(*FragmentShader)(UniformCollection* uniforms, FragmentShaderIn* in, Color* color);
+
+typedef struct Program {
+ VertexShader vertexshader;
+ FragmentShader fragmentshader;
+} Program;
+
+void ssrS_bcpcolor(Vec3* bc, Color A, Color B, Color C, Color* out);
+void ssrS_bcpvec2(Vec3* bc, Vec2* A, Vec2* B, Vec2* C, Vec2* out);
+void ssrS_bcpvec3(Vec3* bc, Vec3* A, Vec3* B, Vec3* C, Vec3* out);
+void ssrS_bcpvec4(Vec3* bc, Vec4* A, Vec4* B, Vec4* C, Vec4* out);
+
+/*
+** 顶点数据外,还提供额外的寄存器
+*/
+enum RegisterType {
+ REGTYPE_VEC2 = 1,
+ REGTYPE_VEC4 = 2,
+ REGTYPE_VEC3 = 3,
+};
+
+typedef struct Register {
+ uint length;
+ uint type;
+ union {
+ Vec4* v4;
+ Vec2* v2;
+ Vec3* v3;
+ };
+} Register;
+
+void ssrS_setregvec4_01i(uint idx, Vec4* value);
+void ssrS_setregvec4_02i(uint idx, Vec4* value);
+void ssrS_setregvec2_01i(uint idx, Vec2* value);
+void ssrS_setregvec2_02i(uint idx, Vec2* value);
+void ssrS_setregvec3_01i(uint idx, Vec3* value);
+void ssrS_setregvec3_02i(uint idx, Vec3* value);
+
+Vec4* ssrS_getregvec4_01i(uint idx);
+Vec4* ssrS_getregvec4_02i(uint idx);
+Vec2* ssrS_getregvec2_01i(uint idx);
+Vec2* ssrS_getregvec2_02i(uint idx);
+Vec3* ssrS_getregvec3_01i(uint idx);
+Vec3* ssrS_getregvec3_02i(uint idx);
+
+Vec4* ssrS_getregvec4_01(Vert* vert);
+Vec4* ssrS_getregvec4_02(Vert* vert);
+Vec2* ssrS_getregvec2_01(Vert* vert);
+Vec2* ssrS_getregvec2_02(Vert* vert);
+Vec3* ssrS_getregvec3_01(Vert* vert);
+Vec3* ssrS_getregvec3_02(Vert* vert);
+
+#endif \ No newline at end of file
diff --git a/src/core/tris.c b/src/core/tris.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/core/tris.c
diff --git a/src/core/tris.h b/src/core/tris.h
new file mode 100644
index 0000000..1f4208f
--- /dev/null
+++ b/src/core/tris.h
@@ -0,0 +1,17 @@
+#ifndef _SOFTSHADEROOM_TRIS_H_
+#define _SOFTSHADEROOM_TRIS_H_
+
+#include "../util/type.h"
+
+/* 用索引表示的三角形,在一系列顶点中索引 */
+typedef union Triangle
+{
+ uint v[3];
+ struct {
+ uint v1, v2, v3;
+ };
+} Triangle;
+
+
+
+#endif \ No newline at end of file
diff --git a/src/core/vert.c b/src/core/vert.c
new file mode 100644
index 0000000..0e62087
--- /dev/null
+++ b/src/core/vert.c
@@ -0,0 +1,42 @@
+#include "vert.h"
+
+Vert* vert_new(uint comp) {
+ Vert* vert = ssrM_new(Vert);
+ vert->comp = comp;
+ vert->position = ssrM_new(Vec3);
+ vert->normal = ssrM_new(Vec3);
+ vert->tangent = ssrM_new(Vec3);
+ vert->uv = ssrM_new(Vec2);
+ return vert;
+}
+
+void vert_init(Vert* v, uint comp) {
+ ssr_assert(v);
+ v->comp = comp;
+ v->index = 0;
+ if ((comp & VERTMASK_POSITION) && !v->position)
+ v->position = ssrM_new(Vec3);
+ else if (!(comp & VERTMASK_POSITION) && v->position)
+ ssrM_free(v->position);
+ if ((comp & VERTMASK_NORMAL) && !v->normal)
+ v->normal = ssrM_new(Vec3);
+ else if (!(comp & VERTMASK_NORMAL) && v->normal)
+ ssrM_free(v->normal);
+ if ((comp & VERTMASK_TANGENT) && !v->tangent)
+ v->tangent = ssrM_new(Vec3);
+ else if (!(comp & VERTMASK_TANGENT) && v->tangent)
+ ssrM_free(v->tangent);
+ if ((comp & VERTMASK_UV) && !v->uv)
+ v->uv = ssrM_new(Vec2);
+ else if (!(comp & VERTMASK_UV) && v->uv)
+ ssrM_free(v->uv);
+}
+
+void vert_free(Vert* v) {
+ ssr_assert(v);
+ if (v->position) ssrM_free(v->position);
+ if (v->normal) ssrM_free(v->normal);
+ if (v->tangent) ssrM_free(v->tangent);
+ if (v->uv) ssrM_free(v->uv);
+ ssrM_free(v);
+} \ No newline at end of file
diff --git a/src/core/vert.h b/src/core/vert.h
new file mode 100644
index 0000000..a2fdb74
--- /dev/null
+++ b/src/core/vert.h
@@ -0,0 +1,48 @@
+#ifndef _SOFTSHADEROOM_VERT_H_
+#define _SOFTSHADEROOM_VERT_H_
+
+#include "mem.h"
+#include "color.h"
+#include "../math/math.h"
+#include "../util/type.h"
+#include "../util/assert.h"
+
+//typedef uint Color; // ARGB by default
+
+typedef uint Color; // ARGB by default
+
+#define COLOR_A(c) ((c >> 24) & 0xff)
+#define COLOR_R(c) ((c >> 16) & 0xff)
+#define COLOR_G(c) ((c >> 8) & 0xff)
+#define COLOR_B(c) (c & 0xff)
+
+typedef Vec4 Color32; // 4个float的颜色
+
+Color color32_tocolor(Color32* c);
+void color_tocolor32(Color c, Color32* out);
+void color32_saturate(Color32* c);
+
+enum VertMask {
+ VERTMASK_POSITION = 1 ,
+ VERTMASK_NORMAL = 1 << 1,
+ VERTMASK_COLOR = 1 << 2,
+ VERTMASK_TANGENT = 1 << 3,
+ VERTMASK_UV = 1 << 4,
+};
+
+/*标准的顶点结构,禁止修改*/
+typedef struct Vert {
+ uint index;
+ uint comp;
+ Vec3* position;
+ Vec3* normal;
+ Vec3* tangent;
+ Vec2* uv;
+ Color color;
+} Vert;
+
+Vert* vert_new(uint comp); /*新建vert*/
+void vert_init(Vert* v, uint comp); /*如果某些component没创建,创建它*/
+void vert_free(Vert* v); /*释放vert*/
+
+#endif \ No newline at end of file