summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-12-23 23:59:02 +0800
committerchai <chaifix@163.com>2019-12-23 23:59:02 +0800
commitd49f3d3f73709a9a7c0bce53aa13ed28a2bd27cb (patch)
tree3fc2cca442106a56fc151c5faffbb24217ca83f5 /src/core
parentec111247c614663d8231245a17c314b9b8b4a28c (diff)
*misc
Diffstat (limited to 'src/core')
-rw-r--r--src/core/clip.c72
-rw-r--r--src/core/clip.h4
-rw-r--r--src/core/device.c192
-rw-r--r--src/core/mem.c0
-rw-r--r--src/core/rasterizer.c145
-rw-r--r--src/core/rasterizer.h2
-rw-r--r--src/core/shader.c104
-rw-r--r--src/core/shader.h13
-rw-r--r--src/core/texture.c20
-rw-r--r--src/core/texture.h2
10 files changed, 422 insertions, 132 deletions
diff --git a/src/core/clip.c b/src/core/clip.c
index 37aa9d2..48c376d 100644
--- a/src/core/clip.c
+++ b/src/core/clip.c
@@ -188,9 +188,10 @@ static bool clip_against_plane(
, ClippedBuffer* dst_buffer
, byte* src_data[]
, byte* dst_data[]
+ , uint prim_vcount/*minimum number of primitive vertices*/
) {
bool varying = varying_flag & VARYING_ANY;
- int idx = 0; /**/
+ int idx = 0;
ClippedVert *prev, *curr;
uint previ, curri;
bool prev_inside, curr_inside;
@@ -241,12 +242,12 @@ static bool clip_against_plane(
}
}
dst_buffer->count = idx;
- return idx < 3;
+ return idx < prim_vcount;
}
-#define CLIP(plane, from, to, from_data, to_data) \
- if (clip_against_plane(plane, varying_flag, from, to, from_data, to_data)) { \
- buffer->count = 0;/*cull this triangle*/ \
+#define CLIP(plane, from, to, from_data, to_data, prim_vcount) \
+ if (clip_against_plane(plane, varying_flag, from, to, from_data, to_data, prim_vcount)) { \
+ buffer->count = 0;/*cull this primitive*/ \
return 1; \
}
@@ -286,13 +287,60 @@ bool clip_triangle(
}
#undef COPY_VERT
- CLIP(POSITIVE_W, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data);
- CLIP(POSITIVE_X, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data);
- CLIP(NEGATIVE_X, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data);
- CLIP(POSITIVE_Y, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data);
- CLIP(NEGATIVE_Y, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data);
- CLIP(POSITIVE_Z, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data);
- CLIP(NEGATIVE_Z, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data);
+ CLIP(POSITIVE_W, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data, 3);
+ CLIP(POSITIVE_X, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data, 3);
+ CLIP(NEGATIVE_X, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data, 3);
+ CLIP(POSITIVE_Y, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data, 3);
+ CLIP(NEGATIVE_Y, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data, 3);
+ CLIP(POSITIVE_Z, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data, 3);
+ CLIP(NEGATIVE_Z, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data, 3);
return 1;
}
+
+uint clip_line(
+ Vec4* c0, Vec4* c1,
+ uint i0, uint i1,
+ uint varying_flag,
+ ClippedBuffer* buffer
+) {
+ bool is_visible = is_vertex_visible(c0) && is_vertex_visible(c1);
+
+ if (is_visible)
+ return 0;
+
+ ssr_assert(buffer == &clip_buffer);
+
+ /*copy vert data to temp_clip_buffer*/
+ temp_clip_buffer.count = 2;
+#define COPY_VERT(i) \
+ temp_clip_buffer.vertices[i].clip_coord = *c##i; \
+ temp_clip_buffer.vertices[i].index = ##i; \
+
+ COPY_VERT(0);
+ COPY_VERT(1);
+
+ int i, index, size;
+ for (i = 0; i < REG_TOTAL; ++i) {
+ index = open_regsi[i];
+ if (index == -1) break;
+ size = registers[index].element_size;
+ ssrM_copy(&temp_clip_buffer_data[index][0], &registers[index].data[i0*size], size);
+ ssrM_copy(&temp_clip_buffer_data[index][size], &registers[index].data[i1*size], size);
+ }
+#undef COPY_VERT
+
+ CLIP(POSITIVE_W, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data, 2);
+ CLIP(POSITIVE_X, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data, 2);
+ CLIP(NEGATIVE_X, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data, 2);
+ CLIP(POSITIVE_Y, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data, 2);
+ CLIP(NEGATIVE_Y, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data, 2);
+ CLIP(POSITIVE_Z, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data, 2);
+ CLIP(NEGATIVE_Z, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data, 2);
+
+ return 1;
+}
+
+uint clip_point(Vec4* c0, uint i0, uint varying_flag, ClippedBuffer* buffer) {
+ return !is_vertex_visible(c0);
+}
diff --git a/src/core/clip.h b/src/core/clip.h
index 076d3ab..c7fa6cb 100644
--- a/src/core/clip.h
+++ b/src/core/clip.h
@@ -30,8 +30,8 @@ ClippedBuffer clip_buffer; /*clipping result*/
bool clip_triangle(Vec4* c0, Vec4* c1, Vec4* c2, uint i0, uint i1, uint i2, uint varying_flag, ClippedBuffer* clipped);
-uint clip_line();
+uint clip_line(Vec4* c0, Vec4* c1, uint i0, uint i1, uint varying_flag, ClippedBuffer* clipped);
-uint clip_point();
+uint clip_point(Vec4* c0, uint i0, uint varying_flag, ClippedBuffer* clipped);
#endif \ No newline at end of file
diff --git a/src/core/device.c b/src/core/device.c
index dc4d80e..23e4bb3 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -319,6 +319,7 @@ void ssr_clearstencil(byte val) {
memset(state.stencil_buffer, val, config.width * config.height);
}
+/*directly put point onto screen*/
void ssr_putpoint(uint screenx, uint screeny, Color color) {
if (!contains(screenx, screeny, 0, config.width - 1, 0, config.height - 1))
return;
@@ -369,9 +370,9 @@ void ssrU_viewport(Vec2* p, Vec2* out) {
b = state.viewport.z,
t = state.viewport.w,
w2 = (r - l) * 0.5f,
- h2 = (b - t) * 0.5f;
+ c2 = (b - t) * 0.5f;
out->x = (int)round((p->x + 1) * (w2 - 0.5f) + l);
- out->y = (int)round((1 - p->y) * (h2 - 0.5f) + t);
+ out->y = (int)round((1 - p->y) * (c2 - 0.5f) + t);
}
void ssr_blend(Color32* src, Color32* dst, Color32* out) {
@@ -483,6 +484,124 @@ static struct {
extern ClippedBuffer clip_buffer; /*clipping result*/
+static void render_prims_triangle(uint varying_flag) {
+ uint i0, i1, i2;
+ Vec4 *c0, *c1, *c2;
+ bool reset_active_reg = FALSE;
+ bool clipped = FALSE;
+ for (int i = 0; i < state.prim_count; ++i) {
+ i0 = state.indices[i * 3];
+ i1 = state.indices[i * 3 + 1];
+ i2 = state.indices[i * 3 + 2];
+
+ c0 = &clip_coords.coords[i0];
+ c1 = &clip_coords.coords[i1];
+ c2 = &clip_coords.coords[i2];
+
+ /*back face culling*/
+ if (ssr_isenable(ENABLE_BACKFACECULL)) {
+ float w0 = 1 / c0->w, w1 = 1 / c1->w, w2 = 1 / c2->w;
+ Vec3 ab, ac;
+ ab.x = c1->x * w1 - c0->x * w0;
+ ab.y = c1->y * w1 - c0->y * w0;
+ ac.x = c2->x * w2 - c0->x * w0;
+ ac.y = c2->y * w2 - c0->y * w0;
+ if (ab.x * ac.y - ab.y * ac.x <= 0) {
+ continue; /*cull*/
+ }
+ }
+
+ /*clipping*/
+ clipped = clip_triangle(c0, c1, c2, i0, i1, i2, varying_flag, &clip_buffer);
+
+ /*rasterization*/
+ if (!clipped) {
+ if (reset_active_reg) {
+ reset_active_reg = FALSE;
+ ssrS_setactiveregr();
+ }
+ ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program, &state.uniforms);
+ }
+ else {
+ if (!reset_active_reg) {
+ reset_active_reg = TRUE;
+ ssrS_setactiveregc();
+ }
+ if (clip_buffer.count >= 3) {
+ ClippedVert* vt0 = &clip_buffer.vertices[0], *vt1, *vt2;
+ for (int i = 1; i <= clip_buffer.count - 2; ++i) {
+ vt1 = &clip_buffer.vertices[i];
+ vt2 = &clip_buffer.vertices[i + 1];
+ c0 = &vt0->clip_coord; c1 = &vt1->clip_coord; c2 = &vt2->clip_coord;
+ i0 = vt0->index; i1 = vt1->index; i2 = vt2->index;
+ ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program, &state.uniforms);
+ }
+ }
+ }
+ }
+}
+
+static void render_prims_line(uint varying_flag) {
+ uint i0, i1;
+ Vec4 *c0, *c1;
+ bool reset_active_reg = FALSE;
+ bool clipped = FALSE;
+ for (int i = 0; i < state.prim_count; ++i) {
+ i0 = state.indices[i * 2];
+ i1 = state.indices[i * 2 + 1];
+
+ c0 = &clip_coords.coords[i0];
+ c1 = &clip_coords.coords[i1];
+
+ clipped = clip_line(c0, c1, i0, i1, varying_flag, &clip_buffer);
+
+ if(!clipped) {
+ if (reset_active_reg) {
+ reset_active_reg = FALSE;
+ ssrS_setactiveregr();
+ }
+ ssrR_line(c0, c1, i0, i1, state.program, &state.uniforms);
+ }
+ else {
+ if (!reset_active_reg) {
+ reset_active_reg = TRUE;
+ ssrS_setactiveregc();
+ }
+ if (clip_buffer.count >= 2) {
+ ClippedVert* vt0, *vt1;
+ for (int i = 0; i < clip_buffer.count - 1; ++i) {
+ vt0 = &clip_buffer.vertices[i];
+ vt1 = &clip_buffer.vertices[i + 1];
+ c0 = &vt0->clip_coord; c1 = &vt1->clip_coord;
+ i0 = vt0->index; i1 = vt1->index;
+ ssrR_line(c0, c1, i0, i1, state.program, &state.uniforms);
+ }
+ }
+ }
+ }
+}
+
+static void render_prims_point(uint varying_flag) {
+ uint i0;
+ Vec4 *c0;
+ bool reset_active_reg = FALSE;
+ bool clipped = FALSE;
+ for (int i = 0; i < state.prim_count; ++i) {
+ i0 = state.indices[i];
+
+ c0 = &clip_coords.coords[i0];
+
+ clipped = clip_point(c0, i0, varying_flag, &clip_buffer);
+
+ if (!clipped) {
+ ssrR_point(c0, i0, state.program, &state.uniforms);
+ }
+ else {
+ /*clipped*/
+ }
+ }
+}
+
void ssr_draw(ssr_PrimitiveType primitive) {
ssr_assert(state.verts && state.indices);
@@ -535,64 +654,17 @@ void ssr_draw(ssr_PrimitiveType primitive) {
ssrS_setregtofragin(varying_flag, &ssr_frag_in);
}
- /*primitive assembly*/
- if (primitive == PRIMITIVE_TRIANGLE) {
- uint i0, i1, i2;
- Vec4 *h0, *h1, *h2;
- bool reset_active_reg = FALSE;
- for (int i = 0; i < state.prim_count; ++i) {
- i0 = state.indices[i * 3];
- i1 = state.indices[i * 3 + 1];
- i2 = state.indices[i * 3 + 2];
-
- h0 = &clip_coords.coords[i0],
- h1 = &clip_coords.coords[i1],
- h2 = &clip_coords.coords[i2];
-
- /*back face culling*/
- if (ssr_isenable(ENABLE_BACKFACECULL)) {
- 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; /*cull*/
- }
- }
-
- /*clipping*/
- bool clipped = clip_triangle(h0, h1, h2, i0, i1, i2, varying_flag, &clip_buffer);
-
- /*rasterization*/
- if (!clipped) {
- if (reset_active_reg) {
- reset_active_reg = FALSE;
- ssrS_setactiveregr();
- }
- ssrR_triangle(h0, h1, h2, i0, i1, i2, state.program, &state.uniforms);
- } else {
- if (!reset_active_reg) {
- reset_active_reg = TRUE;
- ssrS_setactiveregc();
- }
- if (clip_buffer.count >= 3) {
- ClippedVert* vt0 = &clip_buffer.vertices[0], *vt1, *vt2;
- for (int i = 1; i <= clip_buffer.count - 2; ++i) {
- vt1 = &clip_buffer.vertices[i];
- vt2 = &clip_buffer.vertices[i + 1];
- h0 = &vt0->clip_coord; h1 = &vt1->clip_coord; h2 = &vt2->clip_coord;
- i0 = vt0->index; i1 = vt1->index; i2 = vt2->index;
- ssrR_triangle(h0, h1, h2, i0, i1, i2, state.program, &state.uniforms);
- }
- }
- }
- }
- } else if (primitive == PRIMITIVE_POINT) {
-
- } else if (primitive == PRIMITIVE_LINE) {
-
+ /*primitive assembly and rendering*/
+ switch (primitive) {
+ case PRIMITIVE_TRIANGLE:
+ render_prims_triangle(varying_flag);
+ break;
+ case PRIMITIVE_LINE:
+ render_prims_line(varying_flag);
+ break;
+ case PRIMITIVE_POINT:
+ render_prims_point(varying_flag);
+ break;
}
}
diff --git a/src/core/mem.c b/src/core/mem.c
deleted file mode 100644
index e69de29..0000000
--- a/src/core/mem.c
+++ /dev/null
diff --git a/src/core/rasterizer.c b/src/core/rasterizer.c
index 5618fde..a7d3544 100644
--- a/src/core/rasterizer.c
+++ b/src/core/rasterizer.c
@@ -1,9 +1,11 @@
-#include "rasterizer.h"
+#include "rasterizer.h"
#include "device.h"
#include "shader.h"
#include "../math/math.h"
#include "../util/assert.h"
+/*directly put line onto screen*/
+/*Bresenham's line algorithm*/
void ssrR_putline(int x0, int y0, int x1, int y1, Color color) {
int steep = 0;
if (abs(x0 - x1) < abs(y0 - y1)) {
@@ -35,17 +37,17 @@ void ssrR_putline(int x0, int y0, int x1, int y1, Color color) {
}
}
-/*ʹøμ3DѧP245*/
+/*使用辅助梯形计算三角形面积,《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;
+/*from https://github.com/ssloy/tinyrenderer */
bool ssrR_barycentric(Vec2* A, Vec2* B, Vec2* C, Vec2* p, Vec3* out) {
ssr_assert(A && B && C && p && out);
+ Vec3 s[2], u;
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);
@@ -121,7 +123,6 @@ void ssrR_triangle(
float CAw = 1.f / CA->w, CBw = 1.f / CB->w, CCw = 1.f / CC->w;
bool depth_test = ssr_isenable(ENABLE_DEPTHTEST);
- bool multi_sample = ssr_isenable(ENABLE_MULTISAMPLE);
bool blend = ssr_isenable(ENABLE_BLEND);
bool write_depth = ssr_isenable(ENABLE_WRITEDEPTH);
bool stencil_test = ssr_isenable(ENABLE_STENCILTEST);
@@ -171,7 +172,7 @@ void ssrR_triangle(
} \
discardif(!pass_depth_test || !pass_stencil_test); \
/*interpolate varying variables*/ \
- ssrS_solveregs(&bc, IA, IB, IC); \
+ ssrS_solveregsbcp(&bc, IA, IB, IC); \
/*enter fragment shader*/ \
discard = !frag_shader(uniforms, &ssr_frag_in, out_color[0]); \
discardif(discard); \
@@ -226,12 +227,136 @@ void ssrR_triangle(
#undef RENDER_TRIANGLE
}
-void ssrR_line(Vec4* CA, Vec4* CB, Vert* A, Vert* B, Program* program, UniformCollection* uniforms) {
- ssr_assert(CA && CB && program && A && B && uniforms);
+void ssrR_line(
+ Vec4* CA, Vec4* CB,
+ uint IA, uint IB,
+ Program* program,
+ UniformCollection* uniforms
+) {
+ ssr_assert(CA && CB && program && uniforms);
+
+ Vec3 SA, SB;
+ vec4_dividew(CA, &SA); ssrU_viewport(&SA, &SA);
+ vec4_dividew(CB, &SB); ssrU_viewport(&SB, &SB);
+
+ FragmentShader frag_shader = program->fragmentshader;
+
+ int x0 = SA.x, y0 = SA.y;
+ int x1 = SB.x, y1 = SB.y;
+ float wA = 1 / CA->w, wB = 1 / CB->w;
+ float zA = SA.z, zB = SB.z;
+
+ bool steep = FALSE;
+ if (abs(x0 - x1) < abs(y0 - y1)) {
+ swapi(x0, y0);
+ swapi(x1, y1);
+ steep = 1;
+ }
+ if (x0 > x1) {
+ swapi(x0, x1);
+ swapi(y0, y1);
+ swapi(IA, IB);
+ swapf(wA, wB);
+ swapf(zA, zB);
+ }
+
+ bool depth_test = ssr_isenable(ENABLE_DEPTHTEST);
+ bool blend = ssr_isenable(ENABLE_BLEND);
+ bool write_depth = ssr_isenable(ENABLE_WRITEDEPTH);
+ bool stencil_test = ssr_isenable(ENABLE_STENCILTEST);
+ bool write_stencil = ssr_iswritesencil();
+
+ bool pass_depth_test = TRUE;
+ bool pass_stencil_test = TRUE;
+ bool discard = FALSE;
+
+#define discardif(condition) if(condition) continue
+ float t, depth;
+ Vec2 c;
+ int x, y, px, py;
+ for (x = x0; x <= x1; ++x) {
+ t = (x - x0) / (float)(x1 - x0);
+ y = y0 + (y1 - y0)*t;
+ /*caculate center*/
+ c.x = (1 - t) * wA;
+ c.y = t * wB;
+ discardif(compare(c.x+c.y, 0));
+ c.x /= (c.x + c.y);
+ t = 1 - c.x;
+ if (steep) {
+ px = y;
+ py = x;
+ }
+ else {
+ px = x;
+ py = y;
+ }
+ if (depth_test) {
+ ssrS_lerpnum(t, &zA, &zB, &depth);
+ pass_depth_test = ssr_testdepth(px, py, depth);
+ }
+ if (stencil_test) {
+ pass_stencil_test = ssr_teststencil(px, py, pass_depth_test);
+ }
+ discardif(!pass_depth_test || !pass_stencil_test);
+ /*solve registers with lerp*/
+ ssrS_solveregslerp(t, IA, IB);
+ discard = !frag_shader(uniforms, &ssr_frag_in, out_color[0]);
+ discardif(discard);
+ /*put point*/
+ ssr_blendandputpoint(px, py, blend);
+ /*write depth and stencil*/
+ if (write_depth) {
+ ssr_writedepth(px, py, depth);
+ }
+ if (write_stencil) {
+ ssr_writestencil(px, py, pass_depth_test, pass_stencil_test);
+ }
+ }
+#undef discardif
}
-void ssrR_point(Vec4* CA, Vert* A, Program* program, UniformCollection* uniforms) {
- ssr_assert(CA && program && A && uniforms);
+void ssrR_point(Vec4* CA, uint IA, Program* program, UniformCollection* uniforms) {
+ ssr_assert(CA && program && uniforms);
+
+ FragmentShader frag_shader = program->fragmentshader;
+
+ Vec3 SA;
+ vec4_dividew(CA, &SA); ssrU_viewport(&SA, &SA);
+ bool depth_test = ssr_isenable(ENABLE_DEPTHTEST);
+ bool blend = ssr_isenable(ENABLE_BLEND);
+ bool write_depth = ssr_isenable(ENABLE_WRITEDEPTH);
+ bool stencil_test = ssr_isenable(ENABLE_STENCILTEST);
+ bool write_stencil = ssr_iswritesencil();
+
+ bool pass_depth_test = TRUE;
+ bool pass_stencil_test = TRUE;
+ bool discard = FALSE;
+
+#define discardif(condition) if(condition) return ;
+
+ int px = SA.x, py = SA.y;
+ float depth = SA.z;
+
+ if (depth_test) {
+ pass_depth_test = ssr_testdepth(px, py, depth);
+ }
+ if (stencil_test) {
+ pass_stencil_test = ssr_teststencil(px, py, pass_depth_test);
+ }
+ discardif(!pass_depth_test || !pass_stencil_test);
+ ssrS_solveregscopy(IA);
+ discard = !frag_shader(uniforms, &ssr_frag_in, out_color[0]);
+ discardif(discard);
+ /*put point*/
+ ssr_blendandputpoint(px, py, blend);
+ /*write depth and stencil*/
+ if (write_depth) {
+ ssr_writedepth(px, py, depth);
+ }
+ if (write_stencil) {
+ ssr_writestencil(px, py, pass_depth_test, pass_stencil_test);
+ }
}
diff --git a/src/core/rasterizer.h b/src/core/rasterizer.h
index 5f29677..a566329 100644
--- a/src/core/rasterizer.h
+++ b/src/core/rasterizer.h
@@ -14,5 +14,7 @@ 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, uint IA, uint IB, uint IC, Program* program, UniformCollection* uniforms);
+void ssrR_line(Vec4* CA, Vec4* CB, uint IA, uint IB, Program* program, UniformCollection* uniforms);
+void ssrR_point(Vec4* CA, uint IA, Program* program, UniformCollection* uniforms);
#endif \ No newline at end of file
diff --git a/src/core/shader.c b/src/core/shader.c
index b28a5e2..899a160 100644
--- a/src/core/shader.c
+++ b/src/core/shader.c
@@ -46,41 +46,41 @@ Register registers[REG_TOTAL] = {
ActiveReg active_regs[REG_TOTAL] = {
/*4 float registers*/
- { sizeof(float), NULL, &reg_num_00, ssrS_bcpnum, &ssr_frag_in.num[0] },
- { sizeof(float), NULL, &reg_num_01, ssrS_bcpnum, &ssr_frag_in.num[1] },
- { sizeof(float), NULL, &reg_num_02, ssrS_bcpnum, &ssr_frag_in.num[2] },
- { sizeof(float), NULL, &reg_num_03, ssrS_bcpnum, &ssr_frag_in.num[3] },
- /*8 vec2 registers*/
- { sizeof(Vec2), NULL, &reg_v2_00, ssrS_bcpvec2, &ssr_frag_in.v2[0] },
- { sizeof(Vec2), NULL, &reg_v2_01, ssrS_bcpvec2, &ssr_frag_in.v2[1] },
- { sizeof(Vec2), NULL, &reg_v2_02, ssrS_bcpvec2, &ssr_frag_in.v2[2] },
- { sizeof(Vec2), NULL, &reg_v2_03, ssrS_bcpvec2, &ssr_frag_in.v2[3] },
- { sizeof(Vec2), NULL, &reg_v2_04, ssrS_bcpvec2, &ssr_frag_in.v2[4] },
- { sizeof(Vec2), NULL, &reg_v2_05, ssrS_bcpvec2, &ssr_frag_in.v2[5] },
- { sizeof(Vec2), NULL, &reg_v2_06, ssrS_bcpvec2, &ssr_frag_in.v2[6] },
- { sizeof(Vec2), NULL, &reg_v2_07, ssrS_bcpvec2, &ssr_frag_in.v2[7] },
+ { sizeof(float), NULL, &reg_num_00, ssrS_bcpnum, ssrS_lerpnum, &ssr_frag_in.num[0] },
+ { sizeof(float), NULL, &reg_num_01, ssrS_bcpnum, ssrS_lerpnum, &ssr_frag_in.num[1] },
+ { sizeof(float), NULL, &reg_num_02, ssrS_bcpnum, ssrS_lerpnum, &ssr_frag_in.num[2] },
+ { sizeof(float), NULL, &reg_num_03, ssrS_bcpnum, ssrS_lerpnum, &ssr_frag_in.num[3] },
+ /*8 vec2 registers*/
+ { sizeof(Vec2), NULL, &reg_v2_00, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[0] },
+ { sizeof(Vec2), NULL, &reg_v2_01, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[1] },
+ { sizeof(Vec2), NULL, &reg_v2_02, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[2] },
+ { sizeof(Vec2), NULL, &reg_v2_03, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[3] },
+ { sizeof(Vec2), NULL, &reg_v2_04, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[4] },
+ { sizeof(Vec2), NULL, &reg_v2_05, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[5] },
+ { sizeof(Vec2), NULL, &reg_v2_06, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[6] },
+ { sizeof(Vec2), NULL, &reg_v2_07, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[7] },
/*12 vec3 registers*/
- { sizeof(Vec3), NULL, &reg_v3_00, ssrS_bcpvec3, &ssr_frag_in.v3[0] },
- { sizeof(Vec3), NULL, &reg_v3_01, ssrS_bcpvec3, &ssr_frag_in.v3[1] },
- { sizeof(Vec3), NULL, &reg_v3_02, ssrS_bcpvec3, &ssr_frag_in.v3[2] },
- { sizeof(Vec3), NULL, &reg_v3_03, ssrS_bcpvec3, &ssr_frag_in.v3[3] },
- { sizeof(Vec3), NULL, &reg_v3_04, ssrS_bcpvec3, &ssr_frag_in.v3[4] },
- { sizeof(Vec3), NULL, &reg_v3_05, ssrS_bcpvec3, &ssr_frag_in.v3[5] },
- { sizeof(Vec3), NULL, &reg_v3_06, ssrS_bcpvec3, &ssr_frag_in.v3[6] },
- { sizeof(Vec3), NULL, &reg_v3_07, ssrS_bcpvec3, &ssr_frag_in.v3[7] },
- { sizeof(Vec3), NULL, &reg_v3_08, ssrS_bcpvec3, &ssr_frag_in.v3[8] },
- { sizeof(Vec3), NULL, &reg_v3_09, ssrS_bcpvec3, &ssr_frag_in.v3[9] },
- { sizeof(Vec3), NULL, &reg_v3_10, ssrS_bcpvec3, &ssr_frag_in.v3[10] },
- { sizeof(Vec3), NULL, &reg_v3_11, ssrS_bcpvec3, &ssr_frag_in.v3[11] },
+ { sizeof(Vec3), NULL, &reg_v3_00, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[0] },
+ { sizeof(Vec3), NULL, &reg_v3_01, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[1] },
+ { sizeof(Vec3), NULL, &reg_v3_02, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[2] },
+ { sizeof(Vec3), NULL, &reg_v3_03, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[3] },
+ { sizeof(Vec3), NULL, &reg_v3_04, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[4] },
+ { sizeof(Vec3), NULL, &reg_v3_05, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[5] },
+ { sizeof(Vec3), NULL, &reg_v3_06, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[6] },
+ { sizeof(Vec3), NULL, &reg_v3_07, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[7] },
+ { sizeof(Vec3), NULL, &reg_v3_08, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[8] },
+ { sizeof(Vec3), NULL, &reg_v3_09, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[9] },
+ { sizeof(Vec3), NULL, &reg_v3_10, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[10] },
+ { sizeof(Vec3), NULL, &reg_v3_11, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[11] },
/*8 vec4 registers*/
- { sizeof(Vec4), NULL, &reg_v4_00, ssrS_bcpvec4, &ssr_frag_in.v4[0] },
- { sizeof(Vec4), NULL, &reg_v4_01, ssrS_bcpvec4, &ssr_frag_in.v4[1] },
- { sizeof(Vec4), NULL, &reg_v4_02, ssrS_bcpvec4, &ssr_frag_in.v4[2] },
- { sizeof(Vec4), NULL, &reg_v4_03, ssrS_bcpvec4, &ssr_frag_in.v4[3] },
- { sizeof(Vec4), NULL, &reg_v4_04, ssrS_bcpvec4, &ssr_frag_in.v4[4] },
- { sizeof(Vec4), NULL, &reg_v4_05, ssrS_bcpvec4, &ssr_frag_in.v4[5] },
- { sizeof(Vec4), NULL, &reg_v4_06, ssrS_bcpvec4, &ssr_frag_in.v4[6] },
- { sizeof(Vec4), NULL, &reg_v4_07, ssrS_bcpvec4, &ssr_frag_in.v4[7] },
+ { sizeof(Vec4), NULL, &reg_v4_00, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[0] },
+ { sizeof(Vec4), NULL, &reg_v4_01, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[1] },
+ { sizeof(Vec4), NULL, &reg_v4_02, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[2] },
+ { sizeof(Vec4), NULL, &reg_v4_03, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[3] },
+ { sizeof(Vec4), NULL, &reg_v4_04, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[4] },
+ { sizeof(Vec4), NULL, &reg_v4_05, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[5] },
+ { sizeof(Vec4), NULL, &reg_v4_06, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[6] },
+ { sizeof(Vec4), NULL, &reg_v4_07, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[7] },
};
/*draw callļĴ*/
@@ -127,8 +127,8 @@ void ssrS_setactiveregc() { /*set active reg data from clipping buffer*/
}
}
-/*Ĵеֵ*/
-void ssrS_solveregs(Vec3* bc, uint ia, uint ib, uint ic) {
+/*IJֵĴеֵ*/
+void ssrS_solveregsbcp(Vec3* bc, uint ia, uint ib, uint ic) {
int index = 0;
uint stride = 0;
ActiveReg* reg;
@@ -147,6 +147,40 @@ void ssrS_solveregs(Vec3* bc, uint ia, uint ib, uint ic) {
}
}
+/*ԲֵĴеֵ*/
+void ssrS_solveregslerp(float t, uint ia, uint ib) {
+ int index = 0;
+ uint stride = 0;
+ ActiveReg* reg;
+ for (int i = 0; i < REG_TOTAL; ++i) {
+ index = open_regsi[i];
+ if (index == -1) break;
+ reg = &active_regs[index];
+ stride = reg->element_size;
+ *reg->accessor = reg->linear_interpolator(
+ t
+ , &reg->data[ia*stride]
+ , &reg->data[ib*stride]
+ , reg->output
+ );
+ }
+}
+
+/*ƵͼԪʱֱӿҪԲֵ*/
+void ssrS_solveregscopy(uint pindex) {
+ int index = 0;
+ uint stride = 0;
+ ActiveReg* reg;
+ for (int i = 0; i < REG_TOTAL; ++i) {
+ index = open_regsi[i];
+ if (index == -1) break;
+ reg = &active_regs[index];
+ stride = reg->element_size;
+ ssrM_copy(reg->output, &reg->data[pindex*stride], stride);
+ *reg->accessor = reg->output;
+ }
+}
+
/*ĴݣҪĻ*/
void ssrS_setregisters(int capacity) {
Register* reg;
diff --git a/src/core/shader.h b/src/core/shader.h
index 9ae757b..3737e8c 100644
--- a/src/core/shader.h
+++ b/src/core/shader.h
@@ -119,10 +119,6 @@ void ssrS_lerpvec2(float t, Vec2* A, Vec2* B, Vec2* out);
void ssrS_lerpvec3(float t, Vec3* A, Vec3* B, Vec3* out);
void ssrS_lerpvec4(float t, Vec4* A, Vec4* B, Vec4* out);
-/*
-** ⣬ṩļĴ洢vertex shaderĶ
-** 24
-*/
typedef enum {
REGTYPE_NUM = 1,
REGTYPE_VEC2,
@@ -152,15 +148,15 @@ typedef struct {
byte* data; /*mutable, either of registers or temp-registers*/
byte** accessor;
BcpInterpolator bcp_interpolator;
+ LinearInterpolator linear_interpolator;
byte* output; /*fragment-in*/
} ActiveReg;
Register registers[REG_TOTAL];
ActiveReg active_regs[REG_TOTAL];
-int open_regsi[REG_TOTAL]; /*draw callõļĴregistersactive_regs*/
+int open_regsi[REG_TOTAL]; /*active registers during a draw call*/
-/*ĴָaccessorָĴеijֵshaderٷʣʹôܻҰָ*/
float *reg_num_00, *reg_num_01, *reg_num_02, *reg_num_03;
Vec2 *reg_v2_00, *reg_v2_01, *reg_v2_02, *reg_v2_03, *reg_v2_04, *reg_v2_05, *reg_v2_06, *reg_v2_07;
Vec3 *reg_v3_00, *reg_v3_01, *reg_v3_02, *reg_v3_03, *reg_v3_04, *reg_v3_05, *reg_v3_06, *reg_v3_07, *reg_v3_08, *reg_v3_09, *reg_v3_10, *reg_v3_11;
@@ -169,10 +165,11 @@ Vec4 *reg_v4_00, *reg_v4_01, *reg_v4_02, *reg_v4_03, *reg_v4_04, *reg_v4_05, *re
void ssrS_openregs(uint varying_flag);
void ssrS_setactiveregr();
void ssrS_setactiveregc();
-void ssrS_solveregs(Vec3* bc, uint a, uint b, uint c);
+void ssrS_solveregsbcp(Vec3* bc, uint a, uint b, uint c);
+void ssrS_solveregslerp(float t, uint ia, uint ib);
+void ssrS_solveregscopy(uint i);
void ssrS_setregisters(int capacity);
-/*üĴָ룬ָĴfragment׶ΣָָfragmentInṹ*/
void ssrS_setupregisterpointers(int idx);
/*set register accessor, point to fragin struct*/
diff --git a/src/core/texture.c b/src/core/texture.c
index 33a00c5..bb33bae 100644
--- a/src/core/texture.c
+++ b/src/core/texture.c
@@ -41,17 +41,23 @@ Texture* texture_loadfromfile(const char* path) {
return NULL;
}
fclose(file);
+
int width, height;
Color* pixels = (Color*)stbi_load_from_memory((unsigned char*)buffer, size, &width, &height, NULL, STBI_rgb_alpha);
ssrM_free(buffer);
- if (!pixels) return NULL;
+ if (!pixels)
+ return NULL;
+
+ /*build texture*/
Texture* texture = ssrM_new(Texture);
texture->width = width; texture->height = height;
texture->pixels = ssrM_newvector(Color32, width*height);
texture->filter_mode = FILTERMODE_POINT;
texture->wrap_mode = WRAPMODE_CLAMP;
texture_abgr2c32(pixels, texture->pixels, width*height);
+
ssrM_free(pixels);
+
return texture;
}
@@ -65,6 +71,10 @@ Texture* texture_create(uint width, uint height) {
return tex;
}
+void texture_save(const char* file) {
+
+}
+
static Color32 sampling(Texture* tex, WrapMode wrap_mode, int x, int y) {
if (wrap_mode == WRAPMODE_CLAMP) { /*clamp*/
x = clamp(x, 0, tex->width - 1);
@@ -81,16 +91,16 @@ Color32 texture_sampling(Texture* tex, float x01, float y01) {
FilterMode filter_mode = tex->filter_mode;
WrapMode wrap_mode = tex->wrap_mode;
float x = x01 * tex->width, y = (1 - y01) * tex->height; /*map to texture coordinate*/
- int x_min = floor(x), y_min = floor(y);
- int x_max = ceil(x), y_max = ceil(y);
if (filter_mode == FILTERMODE_POINT) {
- int px = (x_max - x > x - x_min) ? x_min : x_max;
- int py = (y_max - y > y - y_min) ? y_min : y_max;
+ int px = round(x);
+ int py = round(y);
return sampling(tex, wrap_mode, px, py);
}
else if (filter_mode == FILTERMODE_BILINEAR) {
static Color32 tl, tr, bl, br, t, b, out;
+ int x_min = floor(x), y_min = floor(y);
+ int x_max = ceil(x), y_max = ceil(y);
tl = sampling(tex, wrap_mode, x_min, y_min);
tr = sampling(tex, wrap_mode, x_max, y_min);
diff --git a/src/core/texture.h b/src/core/texture.h
index 06016ad..4e2c992 100644
--- a/src/core/texture.h
+++ b/src/core/texture.h
@@ -29,6 +29,8 @@ typedef struct {
Texture* texture_loadfromfile(const char* path);
Texture* texture_create(uint width, uint height);
+void texture_save(const char* file);
+
void texture_setfiltermode(Texture* tex, FilterMode filter);
void texture_setwrapmode(Texture* tex, WrapMode wrap);