diff options
Diffstat (limited to 'src/core/device.c')
-rw-r--r-- | src/core/device.c | 136 |
1 files changed, 94 insertions, 42 deletions
diff --git a/src/core/device.c b/src/core/device.c index ad640c6..f6b1a4e 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -1,5 +1,7 @@ #include "device.h" #include "rasterizer.h" +#include "clip.h" +#include "shader.h" #include "../util/assert.h" ssr_Config config; @@ -34,7 +36,7 @@ struct { uint* zbuffer; /* 顶点数据 */ - Vert** verts; uint nverts; + Vert* verts; uint nverts; uint* indices; uint nprims; /* shader program */ @@ -246,7 +248,7 @@ void ssrU_viewport(Vec2* p, Vec2* out) { //out->y = (int)((1 - p->y) * (halfh - 0.5f)); } -void ssr_bindvertices(Vert** verts, int nverts, uint* indices, int nprims) { +void ssr_bindvertices(Vert* verts, int nverts, uint* indices, int nprims) { ssr_assert(verts && indices); state.verts = verts; state.nverts = nverts; @@ -263,69 +265,119 @@ void ssr_unuseprogram() { state.program = NULL; } -static Vec4* homos = NULL; -static uint tri[3]; -static Vec3 ab, ac; -static Mat4 mvp, mv; +VertexShaderIn ssr_vert_in; +FragmentShaderIn ssr_frag_in; + +static struct { + Vec4* coords; + uint length; +} clipping_buffer; + +static ClippedBuffer clipped_buffer; /*clipping result*/ + void ssr_draw(ssr_PrimitiveType primitive) { ssr_assert(state.verts && state.indices); + static Mat4 mvp, mv; + ssr_getmvp(&mvp); ssr_getmv(&mv); - state.uniforms.model = &GETMATRIX(MATRIX_MODEL); - state.uniforms.view = &GETMATRIX(MATRIX_VIEW); + 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; + state.uniforms.mvp = &mvp; + state.uniforms.mv = &mv; + + uint varying_flag = state.program->varying_flag; + bool use_extra_varyings = varying_flag & VARYING_EXTRA; - VertexShaderIn vertIn = { NULL }; - if (!homos) - homos = ssrM_newvector(Vec4, state.nverts); + /*prepare registers if necessary*/ + if (use_extra_varyings) { + ssrS_setregisters(varying_flag, state.nverts); + } + + /*resize clipping coords buffer*/ + if (clipping_buffer.length < state.nverts) { + ssrM_resizevector( + Vec4, + clipping_buffer.coords, + clipping_buffer.length, + state.nverts, + FALSE + ); + } + + /*vertex operation*/ for (int i = 0; i < state.nverts; ++i) { - Vert* vert = state.verts[i]; - vertIn.vertex = vert; - state.program->vertexshader(&state.uniforms, &vertIn, &homos[i]); + Vert* vert = &state.verts[i]; + ssr_vert_in.vertex = vert; + /*set register pointers*/ + if (use_extra_varyings) { + ssrS_setupregisterpoints(varying_flag, vert->index); + } + state.program->vertexshader(&state.uniforms, &ssr_vert_in, &clipping_buffer.coords[i]); } + /*set register pointer to frag-in*/ + if (use_extra_varyings) { + ssrS_setregtofragin(varying_flag, &ssr_frag_in); + } + + /*primitive assembly*/ if (primitive == PRIMITIVE_TRIANGLE) { + uint i0, i1, i2; + Vec4 *h0, *h1, *h2; + Vert *v0, *v1, *v2; 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]; + i0 = state.indices[i * 3]; + i1 = state.indices[i * 3 + 1]; + i2 = state.indices[i * 3 + 2]; + + h0 = &clipping_buffer.coords[i0], + h1 = &clipping_buffer.coords[i1], + h2 = &clipping_buffer.coords[i2]; - /* back face culling */ + v0 = &state.verts[i0]; + v1 = &state.verts[i1]; + v2 = &state.verts[i2]; + + /*back face culling*/ if (ssr_isenable(ENABLEMASK_BACKFACECULL)) { - float w0 = 1 / homos[tri[0]].w, w1 = 1 / homos[tri[1]].w, w2 = 1 / homos[tri[2]].w; - Vec2* h0 = &homos[tri[0]], *h1 = &homos[tri[1]], *h2 = &homos[tri[2]]; - ab.x = h1->x * w1 - h0->x * w0; /*在屏幕空间做背面剔除*/ + float w0 = 1 / h0->w, w1 = 1 / h1->w, w2 = 1 / h2->w; + Vec3 ab, ac; + ab.x = h1->x * w1 - h0->x * w0; ab.y = h1->y * w1 - h0->y * w0; ac.x = h2->x * w2 - h0->x * w0; ac.y = h2->y * w2 - h0->y * w0; - if (ab.x * ac.y - ab.y * ac.x <= 0) { - continue; + if (ab.x * ac.y - ab.y * ac.x <= 0) + continue; /*cull*/ + } + + /*clipping*/ + bool clipped = clip_triangle(h0, h1, h2, v0, v1, v2, varying_flag, &clipped_buffer); + + /*rasterization*/ + if (!clipped) { + ssrR_triangle(h0, h1, h2, v0, v1, v2, TRUE, NULL, NULL, NULL, state.program, &state.uniforms); + } else { + if (clipped_buffer.count >= 3) { + ClippedVert* vt0 = &clipped_buffer.vertices[0], *vt1, *vt2; + for (int i = 1; i <= clipped_buffer.count - 2; ++i) { /*0->i->i+1*/ + vt1 = &clipped_buffer.vertices[i]; + vt2 = &clipped_buffer.vertices[i + 1]; + h0 = &vt0->clip_coord; h1 = &vt1->clip_coord; h2 = &vt2->clip_coord; + v0 = &vt0->vertex; v1 = &vt1->vertex; v2 = &vt2->vertex; + ssrR_triangle(h0, h1, h2, v0, v1, v2, FALSE, vt0, vt1, vt2, state.program, &state.uniforms); + } } } - /* render triangle */ - 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) { + } else if (primitive == PRIMITIVE_POINT) { + } else if (primitive == PRIMITIVE_LINE) { + } - //ssrM_free(homos); } void ssr_setuniformmat4(uint idx, Mat4* src) { |