summaryrefslogtreecommitdiff
path: root/src/core/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/device.c')
-rw-r--r--src/core/device.c339
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;
+}