diff options
Diffstat (limited to 'src/core/device.c')
-rw-r--r-- | src/core/device.c | 339 |
1 files changed, 339 insertions, 0 deletions
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; +} |