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.c136
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) {