diff options
author | chai <chaifix@163.com> | 2019-12-23 23:59:02 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-12-23 23:59:02 +0800 |
commit | d49f3d3f73709a9a7c0bce53aa13ed28a2bd27cb (patch) | |
tree | 3fc2cca442106a56fc151c5faffbb24217ca83f5 /src/core | |
parent | ec111247c614663d8231245a17c314b9b8b4a28c (diff) |
*misc
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/clip.c | 72 | ||||
-rw-r--r-- | src/core/clip.h | 4 | ||||
-rw-r--r-- | src/core/device.c | 192 | ||||
-rw-r--r-- | src/core/mem.c | 0 | ||||
-rw-r--r-- | src/core/rasterizer.c | 145 | ||||
-rw-r--r-- | src/core/rasterizer.h | 2 | ||||
-rw-r--r-- | src/core/shader.c | 104 | ||||
-rw-r--r-- | src/core/shader.h | 13 | ||||
-rw-r--r-- | src/core/texture.c | 20 | ||||
-rw-r--r-- | src/core/texture.h | 2 |
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], ®isters[index].data[i0*size], size); + ssrM_copy(&temp_clip_buffer_data[index][size], ®isters[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, ®_num_00, ssrS_bcpnum, &ssr_frag_in.num[0] }, - { sizeof(float), NULL, ®_num_01, ssrS_bcpnum, &ssr_frag_in.num[1] }, - { sizeof(float), NULL, ®_num_02, ssrS_bcpnum, &ssr_frag_in.num[2] }, - { sizeof(float), NULL, ®_num_03, ssrS_bcpnum, &ssr_frag_in.num[3] }, - /*8 vec2 registers*/ - { sizeof(Vec2), NULL, ®_v2_00, ssrS_bcpvec2, &ssr_frag_in.v2[0] }, - { sizeof(Vec2), NULL, ®_v2_01, ssrS_bcpvec2, &ssr_frag_in.v2[1] }, - { sizeof(Vec2), NULL, ®_v2_02, ssrS_bcpvec2, &ssr_frag_in.v2[2] }, - { sizeof(Vec2), NULL, ®_v2_03, ssrS_bcpvec2, &ssr_frag_in.v2[3] }, - { sizeof(Vec2), NULL, ®_v2_04, ssrS_bcpvec2, &ssr_frag_in.v2[4] }, - { sizeof(Vec2), NULL, ®_v2_05, ssrS_bcpvec2, &ssr_frag_in.v2[5] }, - { sizeof(Vec2), NULL, ®_v2_06, ssrS_bcpvec2, &ssr_frag_in.v2[6] }, - { sizeof(Vec2), NULL, ®_v2_07, ssrS_bcpvec2, &ssr_frag_in.v2[7] }, + { sizeof(float), NULL, ®_num_00, ssrS_bcpnum, ssrS_lerpnum, &ssr_frag_in.num[0] }, + { sizeof(float), NULL, ®_num_01, ssrS_bcpnum, ssrS_lerpnum, &ssr_frag_in.num[1] }, + { sizeof(float), NULL, ®_num_02, ssrS_bcpnum, ssrS_lerpnum, &ssr_frag_in.num[2] }, + { sizeof(float), NULL, ®_num_03, ssrS_bcpnum, ssrS_lerpnum, &ssr_frag_in.num[3] }, + /*8 vec2 registers*/ + { sizeof(Vec2), NULL, ®_v2_00, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[0] }, + { sizeof(Vec2), NULL, ®_v2_01, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[1] }, + { sizeof(Vec2), NULL, ®_v2_02, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[2] }, + { sizeof(Vec2), NULL, ®_v2_03, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[3] }, + { sizeof(Vec2), NULL, ®_v2_04, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[4] }, + { sizeof(Vec2), NULL, ®_v2_05, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[5] }, + { sizeof(Vec2), NULL, ®_v2_06, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[6] }, + { sizeof(Vec2), NULL, ®_v2_07, ssrS_bcpvec2, ssrS_lerpvec2, &ssr_frag_in.v2[7] }, /*12 vec3 registers*/ - { sizeof(Vec3), NULL, ®_v3_00, ssrS_bcpvec3, &ssr_frag_in.v3[0] }, - { sizeof(Vec3), NULL, ®_v3_01, ssrS_bcpvec3, &ssr_frag_in.v3[1] }, - { sizeof(Vec3), NULL, ®_v3_02, ssrS_bcpvec3, &ssr_frag_in.v3[2] }, - { sizeof(Vec3), NULL, ®_v3_03, ssrS_bcpvec3, &ssr_frag_in.v3[3] }, - { sizeof(Vec3), NULL, ®_v3_04, ssrS_bcpvec3, &ssr_frag_in.v3[4] }, - { sizeof(Vec3), NULL, ®_v3_05, ssrS_bcpvec3, &ssr_frag_in.v3[5] }, - { sizeof(Vec3), NULL, ®_v3_06, ssrS_bcpvec3, &ssr_frag_in.v3[6] }, - { sizeof(Vec3), NULL, ®_v3_07, ssrS_bcpvec3, &ssr_frag_in.v3[7] }, - { sizeof(Vec3), NULL, ®_v3_08, ssrS_bcpvec3, &ssr_frag_in.v3[8] }, - { sizeof(Vec3), NULL, ®_v3_09, ssrS_bcpvec3, &ssr_frag_in.v3[9] }, - { sizeof(Vec3), NULL, ®_v3_10, ssrS_bcpvec3, &ssr_frag_in.v3[10] }, - { sizeof(Vec3), NULL, ®_v3_11, ssrS_bcpvec3, &ssr_frag_in.v3[11] }, + { sizeof(Vec3), NULL, ®_v3_00, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[0] }, + { sizeof(Vec3), NULL, ®_v3_01, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[1] }, + { sizeof(Vec3), NULL, ®_v3_02, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[2] }, + { sizeof(Vec3), NULL, ®_v3_03, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[3] }, + { sizeof(Vec3), NULL, ®_v3_04, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[4] }, + { sizeof(Vec3), NULL, ®_v3_05, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[5] }, + { sizeof(Vec3), NULL, ®_v3_06, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[6] }, + { sizeof(Vec3), NULL, ®_v3_07, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[7] }, + { sizeof(Vec3), NULL, ®_v3_08, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[8] }, + { sizeof(Vec3), NULL, ®_v3_09, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[9] }, + { sizeof(Vec3), NULL, ®_v3_10, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[10] }, + { sizeof(Vec3), NULL, ®_v3_11, ssrS_bcpvec3, ssrS_lerpvec3, &ssr_frag_in.v3[11] }, /*8 vec4 registers*/ - { sizeof(Vec4), NULL, ®_v4_00, ssrS_bcpvec4, &ssr_frag_in.v4[0] }, - { sizeof(Vec4), NULL, ®_v4_01, ssrS_bcpvec4, &ssr_frag_in.v4[1] }, - { sizeof(Vec4), NULL, ®_v4_02, ssrS_bcpvec4, &ssr_frag_in.v4[2] }, - { sizeof(Vec4), NULL, ®_v4_03, ssrS_bcpvec4, &ssr_frag_in.v4[3] }, - { sizeof(Vec4), NULL, ®_v4_04, ssrS_bcpvec4, &ssr_frag_in.v4[4] }, - { sizeof(Vec4), NULL, ®_v4_05, ssrS_bcpvec4, &ssr_frag_in.v4[5] }, - { sizeof(Vec4), NULL, ®_v4_06, ssrS_bcpvec4, &ssr_frag_in.v4[6] }, - { sizeof(Vec4), NULL, ®_v4_07, ssrS_bcpvec4, &ssr_frag_in.v4[7] }, + { sizeof(Vec4), NULL, ®_v4_00, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[0] }, + { sizeof(Vec4), NULL, ®_v4_01, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[1] }, + { sizeof(Vec4), NULL, ®_v4_02, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[2] }, + { sizeof(Vec4), NULL, ®_v4_03, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[3] }, + { sizeof(Vec4), NULL, ®_v4_04, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[4] }, + { sizeof(Vec4), NULL, ®_v4_05, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[5] }, + { sizeof(Vec4), NULL, ®_v4_06, ssrS_bcpvec4, ssrS_lerpvec4, &ssr_frag_in.v4[6] }, + { sizeof(Vec4), NULL, ®_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 + , ®->data[ia*stride] + , ®->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, ®->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); |