diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/color.c | 20 | ||||
-rw-r--r-- | src/core/color.h | 7 | ||||
-rw-r--r-- | src/core/device.c | 339 | ||||
-rw-r--r-- | src/core/device.h | 98 | ||||
-rw-r--r-- | src/core/limits.h | 6 | ||||
-rw-r--r-- | src/core/mem.c | 0 | ||||
-rw-r--r-- | src/core/mem.h | 20 | ||||
-rw-r--r-- | src/core/rasterizer.c | 180 | ||||
-rw-r--r-- | src/core/rasterizer.h | 17 | ||||
-rw-r--r-- | src/core/shader.c | 34 | ||||
-rw-r--r-- | src/core/shader.h | 89 | ||||
-rw-r--r-- | src/core/tris.c | 0 | ||||
-rw-r--r-- | src/core/tris.h | 17 | ||||
-rw-r--r-- | src/core/vert.c | 42 | ||||
-rw-r--r-- | src/core/vert.h | 48 |
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 |