diff options
author | chai <chaifix@163.com> | 2019-12-21 22:24:15 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-12-21 22:24:15 +0800 |
commit | ec111247c614663d8231245a17c314b9b8b4a28c (patch) | |
tree | a66058508161da488371c90316865ae850b8be15 /src/core | |
parent | c3f45735ecfab6e567be371758f21395e92dfef6 (diff) |
*misc
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/clip.c | 44 | ||||
-rw-r--r-- | src/core/clip.h | 9 | ||||
-rw-r--r-- | src/core/color.c | 2 | ||||
-rw-r--r-- | src/core/depth.c | 35 | ||||
-rw-r--r-- | src/core/depth.h | 17 | ||||
-rw-r--r-- | src/core/device.c | 396 | ||||
-rw-r--r-- | src/core/device.h | 62 | ||||
-rw-r--r-- | src/core/framebuffer.c | 5 | ||||
-rw-r--r-- | src/core/framebuffer.h | 22 | ||||
-rw-r--r-- | src/core/rasterizer.c | 130 | ||||
-rw-r--r-- | src/core/rasterizer.h | 2 | ||||
-rw-r--r-- | src/core/shader.c | 55 | ||||
-rw-r--r-- | src/core/shader.h | 8 | ||||
-rw-r--r-- | src/core/stencil.c | 69 | ||||
-rw-r--r-- | src/core/stencil.h | 28 | ||||
-rw-r--r-- | src/core/texture.c | 32 | ||||
-rw-r--r-- | src/core/texture.h | 17 | ||||
-rw-r--r-- | src/core/vert.h | 2 |
18 files changed, 682 insertions, 253 deletions
diff --git a/src/core/clip.c b/src/core/clip.c index 23e18ce..37aa9d2 100644 --- a/src/core/clip.c +++ b/src/core/clip.c @@ -37,13 +37,16 @@ static LinearInterpolator clip_interpolator[REG_TOTAL] = { ssrS_lerpvec4, }; -uint clip_element_size[REG_TOTAL] = { - 4,4,4,4, /*float*/ - 8, 8, 8, 8,8, 8, 8, 8, /*Vec2*/ - 12,12,12,12,12,12,12,12,12,12,12,12, /*Vec3*/ - 16,16,16,16,16,16,16,16 /*Vec4*/ +static uint clip_element_size[REG_TOTAL] = { + sizeof(float),sizeof(float),sizeof(float),sizeof(float), /*float*/ + sizeof(Vec2), sizeof(Vec2), sizeof(Vec2), sizeof(Vec2),sizeof(Vec2), sizeof(Vec2), sizeof(Vec2), sizeof(Vec2), /*Vec2*/ + sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3),sizeof(Vec3), /*Vec3*/ + sizeof(Vec4),sizeof(Vec4),sizeof(Vec4),sizeof(Vec4),sizeof(Vec4),sizeof(Vec4),sizeof(Vec4),sizeof(Vec4) /*Vec4*/ }; +ClippedBuffer clip_buffer; +static ClippedBuffer temp_clip_buffer; + /*用来访问临时寄存器*/ byte* clip_buffer_data[REG_TOTAL] = { @@ -82,7 +85,7 @@ byte* clip_buffer_data[REG_TOTAL] = }; /*用来访问临时寄存器*/ -byte* temp_clip_buffer_data[REG_TOTAL] = +static byte* temp_clip_buffer_data[REG_TOTAL] = { temp_clip_buffer.temp_reg_num[0], temp_clip_buffer.temp_reg_num[1], @@ -198,8 +201,8 @@ static bool clip_against_plane( prev = &src_buffer->vertices[(i - 1 + src_buffer->count) % src_buffer->count]; curr = &src_buffer->vertices[i]; - previ = prev->vertex.index; - curri = curr->vertex.index; + previ = prev->index; + curri = curr->index; prev_inside = is_inside_plane(&prev->clip_coord, plane); curr_inside = is_inside_plane(&curr->clip_coord, plane); @@ -208,7 +211,7 @@ static bool clip_against_plane( t = get_intersect_ratio(&prev->clip_coord, &curr->clip_coord, plane); dst = &dst_buffer->vertices[idx]; ssrS_lerpvec4(t, &prev->clip_coord, &curr->clip_coord, &dst->clip_coord); - dst->vertex.index = idx; + dst->index = idx; /*set varying variables*/ if (varying) { for (j = 0; j < REG_TOTAL; ++j) { @@ -224,7 +227,7 @@ static bool clip_against_plane( if (curr_inside) { dst = &dst_buffer->vertices[idx]; *dst = *curr; - dst->vertex.index = idx; + dst->index = idx; /*copy varying variables*/ if (varying) { for (j = 0; j < REG_TOTAL; ++j) { @@ -247,18 +250,15 @@ static bool clip_against_plane( return 1; \ } -ClippedBuffer clip_buffer; -ClippedBuffer temp_clip_buffer; - bool clip_triangle( Vec4* c0, Vec4* c1, Vec4* c2 - , Vert* v0, Vert* v1, Vert* v2 + , uint i0, uint i1, uint i2 , uint varying_flag , ClippedBuffer* buffer ) { bool is_visible = is_vertex_visible(c0) - && is_vertex_visible(c1) - && is_vertex_visible(c2); + && is_vertex_visible(c1) + && is_vertex_visible(c2); if (is_visible) return 0; /*no need to clip*/ @@ -269,24 +269,22 @@ bool clip_triangle( temp_clip_buffer.count = 3; #define COPY_VERT(i) \ temp_clip_buffer.vertices[i].clip_coord = *c##i; \ - temp_clip_buffer.vertices[i].vertex = *v##i; \ - temp_clip_buffer.vertices[i].vertex.index = ##i; \ + temp_clip_buffer.vertices[i].index = ##i; \ COPY_VERT(0); COPY_VERT(1); COPY_VERT(2); -#undef COPY_VERT - 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[v0->index*size], size); - ssrM_copy(&temp_clip_buffer_data[index][size], ®isters[index].data[v1->index*size], size); - ssrM_copy(&temp_clip_buffer_data[index][2*size], ®isters[index].data[v2->index*size], 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); + ssrM_copy(&temp_clip_buffer_data[index][2*size], ®isters[index].data[i2*size], size); } +#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); diff --git a/src/core/clip.h b/src/core/clip.h index c1bb7b6..076d3ab 100644 --- a/src/core/clip.h +++ b/src/core/clip.h @@ -10,15 +10,15 @@ typedef struct { /*clipping coord*/ Vec4 clip_coord; - /*vertex data*/ - Vert vertex; + /*new index*/ + uint index; } ClippedVert; #define CLIP_BUFFER_SIZE 6 typedef struct { + uint count; /*number of resulting vertices*/ ClippedVert vertices[CLIP_BUFFER_SIZE]; - uint count; /*temp register*/ float temp_reg_num[REG_NUM_COUNT][CLIP_BUFFER_SIZE]; Vec2 temp_reg_v2[REG_V2_COUNT][CLIP_BUFFER_SIZE]; @@ -27,9 +27,8 @@ typedef struct { } ClippedBuffer; ClippedBuffer clip_buffer; /*clipping result*/ -ClippedBuffer temp_clip_buffer; -bool clip_triangle(Vec4* c0, Vec4* c1, Vec4* c2, Vert* v0, Vert* v1, Vert* v2, uint varying_flag, ClippedBuffer* clipped); +bool clip_triangle(Vec4* c0, Vec4* c1, Vec4* c2, uint i0, uint i1, uint i2, uint varying_flag, ClippedBuffer* clipped); uint clip_line(); diff --git a/src/core/color.c b/src/core/color.c index 45ca555..4f1a877 100644 --- a/src/core/color.c +++ b/src/core/color.c @@ -1,6 +1,8 @@ #include "vert.h" #include "device.h" +Color32 COLOR32_WHITE = {1,1,1,1}; + Color color32_tocolor(Color32* c) { return ssr_color(0xff * c->r, 0xff * c->g, 0xff * c->b, 0xff * c->a); } diff --git a/src/core/depth.c b/src/core/depth.c new file mode 100644 index 0000000..e2c776b --- /dev/null +++ b/src/core/depth.c @@ -0,0 +1,35 @@ +#include "mem.h" +#include "depth.h" +#include "../util/assert.h" + +bool depth_always(float src, float dst) { + return 1; +} + +bool depth_never(float src, float dst) { + return 0; +} + +bool depth_less(float src, float dst) { + return src < dst; +} + +bool depth_equal(float src, float dst) { + return src == dst; +} + +bool depth_leuqal(float src, float dst) { + return src <= dst; +} + +bool depth_greater(float src, float dst) { + return src > dst; +} + +bool depth_notequal(float src, float dst) { + return src != dst; +} + +bool depth_gequer(float src, float dst) { + return src >= dst; +} diff --git a/src/core/depth.h b/src/core/depth.h new file mode 100644 index 0000000..3914055 --- /dev/null +++ b/src/core/depth.h @@ -0,0 +1,17 @@ +#ifndef _SOFTSHADEROOM_DEPTH_H_ +#define _SOFTSHADEROOM_DEPTH_H_ + +#include "../util/type.h" + +typedef bool(*DepthFunc)(float src, float dst); + +bool depth_always(float src, float dst); +bool depth_never(float src, float dst); +bool depth_less(float src, float dst); +bool depth_equal(float src, float dst); +bool depth_leuqal(float src, float dst); +bool depth_greater(float src, float dst); +bool depth_notequal(float src, float dst); +bool depth_gequer(float src, float dst); + +#endif
\ No newline at end of file diff --git a/src/core/device.c b/src/core/device.c index b5468cd..dc4d80e 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -3,93 +3,111 @@ #include "clip.h" #include "shader.h" #include "../util/assert.h" +#include "framebuffer.h" +#include "depth.h" +#include "stencil.h" ssr_Config config; -typedef enum ssr_VertexAttrMask { +typedef enum { VERTEXATTR_POS = 1, VERTEXATTR_COLOR = 1 << 1, VERTEXATTR_UV = 1 << 2, VERTEXATTR_NORMAL = 1 << 3, } ssr_VertexAttrMask; -typedef struct VertexAttr { +typedef struct { int start; int offset; } VertexAttr; -/* -** 状态结构 -*/ static struct { - /* MVP矩阵栈 */ Mat4 matrices[3][MATRIXDEPTH]; - uint matrixtop[3]; - ssr_MatrixMode matrixmode; + uint matrix_top[3]; + ssr_MatrixMode matrix_mode; + + Vec4 viewport; - /* 屏幕缓冲区 */ Color* target; - Color* framebuffer; - uint buffersize; /*framebuffer size in bytess*/ + Color* color_buffer; /*screen color buffer*/ + uint buffer_size; + + float* depth_buffer; + float* depth_screen_buffer; + DepthFunc depth_func; - /* zbuffer 深度会被映射到0~1的非线性区间*/ - float* zbuffer; + byte* stencil_buffer; + byte* stencil_screen_buffer; + byte stencil_read_mask; + uint stencil_ref; + byte stencil_write_mask; + StencilFunc stencil_func; + StencilOp stencil_failop, stencil_dpfailop, stencil_passop; - /* 顶点数据 */ - Vert* verts; uint nverts; - uint* indices; uint nprims; + Vert* verts; uint vert_count; + uint* indices; uint prim_count; - /* shader program */ Program* program; UniformCollection uniforms; - /* texture relavent */ - FilterMode filtermode; - WrapMode wrapmode; - - //FrameBuffer* framebuffer; + FrameBuffer* frame_buffer; uint enable; struct { ssr_BlendFactor src; ssr_BlendFactor dst; - } blendfactor; + } blend_factor; } state; -/* -** MVP矩阵栈 -*/ -#define MATRIXTOP state.matrixtop[state.matrixmode] -#define MATRIX state.matrices[state.matrixmode][MATRIXTOP] -#define MATRIXSTACK state.matrices[state.matrixmode] +#define MATRIXTOP state.matrix_top[state.matrix_mode] +#define MATRIX state.matrices[state.matrix_mode][MATRIXTOP] +#define MATRIXSTACK state.matrices[state.matrix_mode] -#define GETMATRIX(MODE) state.matrices[MODE][state.matrixtop[MODE]] +#define GETMATRIX(MODE) state.matrices[MODE][state.matrix_top[MODE]] -#define BUFFER (state.framebuffer) +#define BUFFER (state.color_buffer) +/*topleft*/ #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)); + ssrM_zero(state.matrix_top, sizeof(state.matrix_top)); + state.target = conf->target; + + int size = config.width * config.height; + if (config.dbuffer) { - state.framebuffer = ssrM_newvector(Color, config.width * config.height); + state.color_buffer = ssrM_newvector(Color, size); } else { - state.framebuffer = conf->target; + state.color_buffer = conf->target; } - state.buffersize = sizeof(Color) * config.width * config.height; - state.zbuffer = ssrM_newvector(float, config.width * config.height); - //memset(state.zbuffer, 0xff, sizeof(uint)*config.width*config.height); + state.buffer_size = sizeof(Color) * size; + + state.depth_screen_buffer = ssrM_newvector(float, size); + state.depth_buffer = state.depth_screen_buffer; + state.depth_func = depth_leuqal; + + state.blend_factor.src = BLEND_SRC_ALPHA; + state.blend_factor.dst = BLEND_ONE_MINUS_SRC_ALPHA; + + state.stencil_screen_buffer = ssrM_newvector(byte, size); + state.stencil_buffer = state.stencil_screen_buffer; + state.stencil_ref = 1; + state.stencil_read_mask = 1; + state.stencil_write_mask = 0; + state.stencil_func = stencil_equal; + state.stencil_failop = stencilop_keep; + state.stencil_dpfailop = stencilop_keep; + state.stencil_passop = stencilop_replace; - state.filtermode = FILTERMODE_POINT; - state.wrapmode = WRAPMODE_CLAMP; + state.frame_buffer = NULL; - state.blendfactor.src = BLEND_SRC_ALPHA; - state.blendfactor.dst = BLEND_ONE_MINUS_SRC_ALPHA; + ssr_viewport(0, config.width, config.height, 0); } float ssr_getaspect() { @@ -104,44 +122,38 @@ int ssr_getframebufferh() { return config.height; } -void ssr_setfiltermode(FilterMode filter_mode) { - state.filtermode = filter_mode; -} - -void ssr_setwrapmode(WrapMode wrap_mode) { - state.wrapmode = wrap_mode; -} - -FilterMode ssr_getfiltermode() { - return state.filtermode; -} - -WrapMode ssr_getwrapmode() { - return state.wrapmode; -} - void ssr_bindframebuffer(FrameBuffer* fbo) { - + ssr_assert(fbo); + state.frame_buffer = fbo; + state.depth_buffer = fbo->depth_buffer; + state.stencil_buffer = fbo->stencil_buffer; } void ssr_unbindframebuffer() { - + state.frame_buffer = NULL; + state.depth_buffer = state.depth_screen_buffer; + state.stencil_buffer = state.stencil_screen_buffer; } void ssr_setblendfunc(ssr_BlendFactor sfactor, ssr_BlendFactor dfactor) { - state.blendfactor.src = sfactor; - state.blendfactor.dst = dfactor; + state.blend_factor.src = sfactor; + state.blend_factor.dst = dfactor; +} + +void ssrU_blendscreencolor(uint x, uint y, Color32* src) { + Color c = state.color_buffer[x + y * config.width]; + Color32 dst; color_tocolor32(c, &dst); + ssr_blend(src, &dst, src); } void ssr_matrixmode(ssr_MatrixMode mode) { - state.matrixmode = mode; + state.matrix_mode = mode; } void ssr_loadidentity() { mat4_setidentity(&MATRIX); } -/* push进去之后会将最新的拷贝一份放在栈顶 */ void ssr_pushmatrix() { ssr_assert(MATRIXTOP < MATRIXDEPTH - 1); ++MATRIXTOP; @@ -152,7 +164,6 @@ 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); @@ -171,7 +182,6 @@ void ssr_lookat(Vec3* pos, Vec3* target, Vec3* up) { 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); @@ -227,6 +237,10 @@ bool ssr_isenable(uint mask) { } void ssr_viewport(float l, float r, float b, float t) { + state.viewport.x = l; + state.viewport.y = r; + state.viewport.z = b; + state.viewport.w = t; } void ssr_ortho(float l, float r, float b, float t, float n, float f) { @@ -236,13 +250,14 @@ void ssr_ortho(float l, float r, float b, float t, float n, float f) { } void ssr_frustum(float l, float r, float b, float t, float n, float f) { + ssr_assert(n > 0 && f > 0 && f > n); Mat4 m; mat4_setfrustum(l, r, b, t, n, f, &m); mat4_multiply(&MATRIX, &m, &MATRIX); } -/*注意这里nf都要是正数,代表距离*/ void ssr_perspective(float fov, float aspect, float n, float f) { + ssr_assert(n > 0 && f > 0 && f > n); Mat4 m; mat4_setperspective(fov, aspect, n, f, &m); mat4_multiply(&MATRIX, &m, &MATRIX); @@ -250,30 +265,60 @@ void ssr_perspective(float fov, float aspect, float n, float f) { void ssr_present() { if (config.dbuffer) { - memcpy(state.target, state.framebuffer, state.buffersize); + memcpy(state.target, state.color_buffer, state.buffer_size); } } -void ssr_clearcolor(Color color) { +static void _clearscreen(Color color) { if (color == 0x00) { - memset(state.framebuffer, 0, state.buffersize); + memset(state.color_buffer, 0, state.buffer_size); } else { uint size = config.width * sizeof(Color); - for(int x = 0; x < config.width; ++x) - state.framebuffer[x] = color; + for (int x = 0; x < config.width; ++x) + state.color_buffer[x] = color; for (int y = 1; y < config.height; ++y) - ssrM_copy(&state.framebuffer[config.width * y], state.framebuffer, size); + ssrM_copy(&state.color_buffer[config.width * y], state.color_buffer, size); + } +} + +static void _clearcolorbuffer(Color32 color) { + Texture* rt; + Color32* pixels; + for (int i = 0; i < RENDER_TARGET_COUNT; ++i) { + rt = state.frame_buffer->render_textures[i]; + if (rt == NULL) continue; + pixels = rt->pixels; + uint size = rt->width * sizeof(Color32); + for (int x = 0; x < rt->width; ++x) + pixels[x] = color; + for (int y = 1; y < rt->height; ++y) + ssrM_copy(&pixels[rt->width * y], pixels, size); + } +} + +void ssr_clearcolor(Color color) { + if (state.frame_buffer == NULL) { + _clearscreen(color); + } + else { + Color32 c; color_tocolor32(color, &c); + _clearcolorbuffer(c); } } void ssr_cleardepth() { - //memset(state.zbuffer, 0xff, sizeof(uint)*config.width*config.height); + ssr_assert(state.depth_buffer); for (int i = 0; i < config.width * config.height; ++i) { - state.zbuffer[i] = 1; + state.depth_buffer[i] = 1; } } +void ssr_clearstencil(byte val) { + ssr_assert(state.stencil_buffer); + memset(state.stencil_buffer, val, 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; @@ -291,26 +336,46 @@ Color ssr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char } bool ssr_testdepth(uint x, uint y, float depth){ + ssr_assert(state.depth_buffer); uint off = x + y * config.width; - return state.zbuffer[off] >= depth; + return state.depth_func(depth, state.depth_buffer[off]); } void ssr_writedepth(uint x, uint y, float depth) { + ssr_assert(state.depth_buffer); uint off = x + y * config.width; - state.zbuffer[off] = depth; + state.depth_buffer[off] = depth; +} + +void ssr_setdepthfunc(ssr_DepthFunc func) { + switch (func) + { + case DEPTHFUNC_ALWAYS: state.depth_func = depth_always; break; + case DEPTHFUNC_NEVER: state.depth_func = depth_never; break; + case DEPTHFUNC_LESS: state.depth_func = depth_less; break; + case DEPTHFUNC_EQUAL: state.depth_func = depth_equal; break; + case DEPTHFUNC_LEQUAL: state.depth_func = depth_leuqal; break; + case DEPTHFUNC_GREATER: state.depth_func = depth_greater; break; + case DEPTHFUNC_NOTEQUAL: state.depth_func = depth_notequal; break; + case DEPTHFUNC_GEQUAL: state.depth_func = depth_gequer; break; + default: ssr_assert(FALSE); + } } void ssrU_viewport(Vec2* p, Vec2* out) { ssr_assert(p && out); - float halfw = config.width / 2.f, halfh = config.height / 2.f; - //out->x = (int)round(p->x * halfw + halfw); - //out->y = (int)round(halfh - p->y * halfh); - out->x = (int)round((p->x + 1) * (halfw - 0.5f)); - out->y = (int)round((1 - p->y) * (halfh - 0.5f)); + float l = state.viewport.x, + r = state.viewport.y, + b = state.viewport.z, + t = state.viewport.w, + w2 = (r - l) * 0.5f, + h2 = (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); } void ssr_blend(Color32* src, Color32* dst, Color32* out) { - ssrU_blend(state.blendfactor.src, state.blendfactor.dst, src, dst, out); + ssrU_blend(state.blend_factor.src, state.blend_factor.dst, src, dst, out); } static _blend(ssr_BlendFactor factor, Color32* src, Color32* dst, Color32* out) { @@ -391,18 +456,12 @@ void ssrU_blend( out->a = src->a + dst->a; } -Color32 ssr_getfbocolor(uint x, uint y) { - Color c = state.framebuffer[x + y * config.width]; - Color32 c32; color_tocolor32(c, &c32); - return c32; -} - -void ssr_bindvertices(Vert* verts, int nverts, uint* indices, int nprims) { +void ssr_bindvertices(Vert* verts, int vert_count, uint* indices, int prim_count) { ssr_assert(verts && indices); state.verts = verts; - state.nverts = nverts; + state.vert_count = vert_count; state.indices = indices; - state.nprims = nprims; + state.prim_count = prim_count; } void ssr_useprogram(Program* program) { @@ -444,30 +503,31 @@ void ssr_draw(ssr_PrimitiveType primitive) { /*prepare registers if necessary*/ if (use_extra_varyings) { ssrS_openregs(varying_flag); - ssrS_setregisters(state.nverts); + ssrS_setregisters(state.vert_count); ssrS_setactiveregr(); } /*resize clipping coords buffer*/ - if (clip_coords.length < state.nverts) { + if (clip_coords.length < state.vert_count) { ssrM_resizevector( Vec4, clip_coords.coords, clip_coords.length, - state.nverts, + state.vert_count, FALSE ); } /*vertex operation*/ - for (int i = 0; i < state.nverts; ++i) { + VertexShader vert_shader = state.program->vertexshader; + for (int i = 0; i < state.vert_count; ++i) { Vert* vert = &state.verts[i]; ssr_vert_in.vertex = vert; /*set register pointers*/ if (use_extra_varyings) { ssrS_setupregisterpointers(vert->index); } - state.program->vertexshader(&state.uniforms, &ssr_vert_in, &clip_coords.coords[i]); + vert_shader(&state.uniforms, &ssr_vert_in, &clip_coords.coords[i]); } /*set register pointer to frag-in*/ @@ -479,9 +539,8 @@ void ssr_draw(ssr_PrimitiveType primitive) { if (primitive == PRIMITIVE_TRIANGLE) { uint i0, i1, i2; Vec4 *h0, *h1, *h2; - Vert *v0, *v1, *v2; bool reset_active_reg = FALSE; - for (int i = 0; i < state.nprims; ++i) { + 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]; @@ -490,10 +549,6 @@ void ssr_draw(ssr_PrimitiveType primitive) { h1 = &clip_coords.coords[i1], h2 = &clip_coords.coords[i2]; - v0 = &state.verts[i0]; - v1 = &state.verts[i1]; - v2 = &state.verts[i2]; - /*back face culling*/ if (ssr_isenable(ENABLE_BACKFACECULL)) { float w0 = 1 / h0->w, w1 = 1 / h1->w, w2 = 1 / h2->w; @@ -508,7 +563,7 @@ void ssr_draw(ssr_PrimitiveType primitive) { } /*clipping*/ - bool clipped = clip_triangle(h0, h1, h2, v0, v1, v2, varying_flag, &clip_buffer); + bool clipped = clip_triangle(h0, h1, h2, i0, i1, i2, varying_flag, &clip_buffer); /*rasterization*/ if (!clipped) { @@ -516,7 +571,7 @@ void ssr_draw(ssr_PrimitiveType primitive) { reset_active_reg = FALSE; ssrS_setactiveregr(); } - ssrR_triangle(h0, h1, h2, v0, v1, v2, state.program, &state.uniforms); + ssrR_triangle(h0, h1, h2, i0, i1, i2, state.program, &state.uniforms); } else { if (!reset_active_reg) { reset_active_reg = TRUE; @@ -528,14 +583,14 @@ void ssr_draw(ssr_PrimitiveType primitive) { vt1 = &clip_buffer.vertices[i]; vt2 = &clip_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, state.program, &state.uniforms); + 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) { } @@ -574,3 +629,130 @@ void ssr_setuniformtex(uint idx, Texture* tex) { void ssr_setuniformu(void* userdata) { state.uniforms.userdata = userdata; } + +bool ssr_teststencil(uint x, uint y, bool pass_depth_test) { + int index = x + config.width * y; + byte mask = state.stencil_read_mask; + byte val = state.stencil_buffer[index]; + return state.stencil_func(val, state.stencil_ref); +} + +void ssr_writestencil(uint x, uint y, bool pass_depth_test, bool pass_stencil_test) { + byte write_mask = state.stencil_write_mask; + if (write_mask == 0) return;/*dont write*/ + int index = x + config.width * y; + byte read_mask = state.stencil_read_mask; + byte val = state.stencil_buffer[index]; + if (pass_stencil_test && pass_depth_test) { + val = state.stencil_passop(val & read_mask, state.stencil_ref & read_mask); + } + else if (pass_stencil_test && !pass_depth_test) { + val = state.stencil_dpfailop(val & read_mask, state.stencil_ref & read_mask); + } + else if (!pass_stencil_test) { + val = state.stencil_failop(val & read_mask, state.stencil_ref & read_mask); + } + /*https://stackoverflow.com/questions/31660747/what-exactly-does-glstencilmask-do*/ + state.stencil_buffer[index] &= ~write_mask; + state.stencil_buffer[index] |= (val & write_mask); +} + +void ssr_setstencilfunc(ssr_StencilFunc func, byte ref, uint mask) { + switch (func) + { + case STENCILFUNC_ALWAYS: state.stencil_func = stencil_always; break; + case STENCILFUNC_NEVER: state.stencil_func = stencil_never; break; + case STENCILFUNC_LESS: state.stencil_func = stencil_less; break; + case STENCILFUNC_EQUAL: state.stencil_func = stencil_equal; break; + case STENCILFUNC_LEQUAL: state.stencil_func = stencil_leuqal; break; + case STENCILFUNC_GREATER: state.stencil_func = stencil_greater; break; + case STENCILFUNC_NOTEQUAL: state.stencil_func = stencil_notequal; break; + case STENCILFUNC_GEQUAL: state.stencil_func = stencil_gequer; break; + default: ssr_assert(FALSE); + } + state.stencil_ref = ref; + state.stencil_read_mask = mask; +} + +static void setstencilop(ssr_StencilOp v, StencilOp* op) { + switch (v) { + case STENCILOP_KEEP: *op = stencilop_keep; break; + case STENCILOP_ZERO: *op = stencilop_zero; break; + case STENCILOP_REPLACE: *op = stencilop_replace; break; + case STENCILOP_INCR: *op = stencilop_incr; break; + case STENCILOP_INCR_WRAP: *op = stencilop_incrwrap; break; + case STENCILOP_DECR: *op = stencilop_decr; break; + case STENCILOP_DECR_WRAP: *op = stencilop_decrwrap; break; + case STENCILOP_INVERT: *op = stencilop_invert; break; + default: + ssr_assert(FALSE); + } +} + +void ssr_setstencilop(ssr_StencilOp fail, ssr_StencilOp dpfail, ssr_StencilOp pass) { + setstencilop(fail, &state.stencil_failop); + setstencilop(dpfail, &state.stencil_dpfailop); + setstencilop(pass, &state.stencil_passop); +} + +void ssr_setstencilmask(byte mask) { + state.stencil_write_mask = mask; +} + +bool ssr_iswritesencil() { + return state.stencil_write_mask != 0x00; +} + +void ssr_blendandputpoint(int x, int y, bool blend) { + if (!state.frame_buffer) { /*directly onto screen*/ + if (blend) { + ssrU_blendscreencolor(x, y, out_color[0]); + } + color32_saturate(out_color[0]); + ssr_putpoint32(x, y, out_color[0]); + } + else { /*onto framebuffer color buffer*/ + Color32 *src, *dst; + Texture* rt; + for (int i = 0; i < RENDER_TARGET_COUNT; ++i) { + rt = state.frame_buffer->render_textures[i]; + if (rt == NULL || !contains(x, y, 0, rt->width, 0, rt->height)) + continue; + dst = &rt->pixels[x + y * rt->width]; + src = out_color[i]; + if (blend) + ssr_blend(src, dst, src); + *dst = *src; + } + } +} + +FrameBuffer* fbo_create() { + FrameBuffer* fb = ssrM_new(FrameBuffer); + fbo_attachdepthbuffer(fb, 0); + fbo_attachstencilbuffer(fb, 0); + ssrM_zero(fb->render_textures, sizeof(Texture*) * RENDER_TARGET_COUNT); + return fb; +} + +void fbo_attachrendertexture(FrameBuffer* fb, uint attachment, Texture* rt) { + fb->render_textures[attachment] = rt; +} + +void fbo_attachdepthbuffer(FrameBuffer* fb, float* depthbuffer) { + if (depthbuffer == NULL) + fb->depth_buffer = state.depth_screen_buffer; + else + fb->depth_buffer = depthbuffer; +} + +void fbo_attachstencilbuffer(FrameBuffer* fb, byte* stencilbuffer) { + if (stencilbuffer == NULL) + fb->stencil_buffer = state.stencil_screen_buffer; + else + fb->stencil_buffer = stencilbuffer; +} + +void fbo_free(FrameBuffer* fb) { + ssrM_free(fb); +} diff --git a/src/core/device.h b/src/core/device.h index 6dc8143..0b27b70 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -34,9 +34,21 @@ typedef enum { ENABLE_MULTISAMPLE = 1 << 2, ENABLE_BLEND = 1 << 3, ENABLE_WRITEDEPTH = 1 << 4, + ENABLE_STENCILTEST = 1 << 5, } ssr_EnableMask; typedef enum { + DEPTHFUNC_ALWAYS, + DEPTHFUNC_NEVER, + DEPTHFUNC_LESS, + DEPTHFUNC_EQUAL, + DEPTHFUNC_LEQUAL, + DEPTHFUNC_GREATER, + DEPTHFUNC_NOTEQUAL, + DEPTHFUNC_GEQUAL, +} ssr_DepthFunc; + +typedef enum { BLEND_ONE, BLEND_ZERO, BLEND_SRC_COLOR, @@ -49,6 +61,28 @@ typedef enum { BLEND_ONE_MINUS_DST_ALPHA, } ssr_BlendFactor; +typedef enum { + STENCILFUNC_ALWAYS, + STENCILFUNC_NEVER, + STENCILFUNC_LESS, + STENCILFUNC_EQUAL, + STENCILFUNC_LEQUAL, + STENCILFUNC_GREATER, + STENCILFUNC_NOTEQUAL, + STENCILFUNC_GEQUAL, +} ssr_StencilFunc; + +typedef enum { + STENCILOP_KEEP, + STENCILOP_ZERO, + STENCILOP_REPLACE, + STENCILOP_INCR, + STENCILOP_INCR_WRAP, + STENCILOP_DECR, + STENCILOP_DECR_WRAP, + STENCILOP_INVERT, +} ssr_StencilOp; + void ssr_init(ssr_Config* config); float ssr_getaspect(); @@ -56,9 +90,6 @@ float ssr_getaspect(); int ssr_getframebufferw(); int ssr_getframebufferh(); -void ssr_setfiltermode(FilterMode filter_mode); -void ssr_setwrapmode(WrapMode wrap_mode); - void ssr_matrixmode(ssr_MatrixMode mode); void ssr_loadidentity(); void ssr_pushmatrix(); @@ -87,7 +118,7 @@ void ssr_disable(uint mask); bool ssr_isenable(uint mask); /* 绑定顶点数据 */ -void ssr_bindvertices(Vert* verts, int nverts, uint* indices, int nprims); +void ssr_bindvertices(Vert* verts, int vert_count, uint* indices, int prim_count); void ssr_unbindvertices(); void ssr_useprogram(Program* program); @@ -103,8 +134,10 @@ void ssr_setuniformu(void* userdata); void ssr_draw(ssr_PrimitiveType primitive); void ssr_clearcolor(Color color); void ssr_cleardepth(); +void ssr_clearstencil(byte val); -void ssr_putpoint(uint screenx, uint screeny, Color color); /*直接修改某个位置的颜色*/ +/*put point onto screen*/ +void ssr_putpoint(uint screenx, uint screeny, Color color); void ssr_putpoint32(uint screenx, uint screeny, Color32* c32); void ssr_present(); @@ -113,20 +146,29 @@ Color ssr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char bool ssr_testdepth(uint x, uint y, float depth); void ssr_writedepth(uint x, uint y, float depth); +void ssr_setdepthfunc(ssr_DepthFunc func); void ssr_blend(Color32* src, Color32* dst, Color32* out); void ssrU_viewport(Vec2* p, Vec2* out); void ssrU_blend(ssr_BlendFactor sfactor, ssr_BlendFactor dfactor, Color32* src, Color32* dst, Color* out); -Color32 ssr_getfbocolor(uint x, uint y); - -FilterMode ssr_getfiltermode(); -WrapMode ssr_getwrapmode(); - void ssr_bindframebuffer(FrameBuffer* fbo); void ssr_unbindframebuffer(); void ssr_setblendfunc(ssr_BlendFactor sfactor, ssr_BlendFactor dfactor); +void ssrU_blendscreencolor(uint x, uint y, Color32* src); + +/*将颜色写入对应的屏幕位置*/ +void ssrU_putpointwithblend(uint x, uint y, Color32* color, bool blend); + +bool ssr_teststencil(uint x, uint y, bool pass_depth_test); +void ssr_writestencil(uint x, uint y, bool pass_depth_test, bool pass_stencil_test); +void ssr_setstencilfunc(ssr_StencilFunc func, byte ref, uint mask); +void ssr_setstencilop(ssr_StencilOp fail, ssr_StencilOp dpfail, ssr_StencilOp pass); +void ssr_setstencilmask(byte mask); +bool ssr_iswritesencil(); + +void ssr_blendandputpoint(int x, int y, bool blend); #endif
\ No newline at end of file diff --git a/src/core/framebuffer.c b/src/core/framebuffer.c deleted file mode 100644 index 7fa0865..0000000 --- a/src/core/framebuffer.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "framebuffer.h" - -FrameBuffer* fbo_create(uint height, uint width) { - -} diff --git a/src/core/framebuffer.h b/src/core/framebuffer.h index 3f03200..78ead0e 100644 --- a/src/core/framebuffer.h +++ b/src/core/framebuffer.h @@ -2,15 +2,31 @@ #define _SOFTSHADEROOM_FRAMEBUFFER_H_ #include "texture.h" +#include "depth.h" +#include "stencil.h" /*frame buffer object*/ -typedef Texture RenderTexture; +#define RENDER_TARGET_COUNT 6 +/* +** OpenGL中fbo的三个挂点可以用renderbuffer或者texture2d绑定,这里考虑效率只提供 +** 8个texture2d可以绑定到color attachment。 +** 如果开启了深度测试或模板测试,那么应该绑定对应的深度缓存和模板缓存 +*/ typedef struct FrameBuffer{ - RenderTexture rt; + Texture* render_textures[RENDER_TARGET_COUNT]; /*color attachments*/ + float* depth_buffer; /*depth attachment*/ + byte* stencil_buffer; /*stencil attachment*/ } FrameBuffer; -FrameBuffer* fbo_create(uint height, uint width); +FrameBuffer* fbo_create(); + +void fbo_attachrendertexture(FrameBuffer* fb, uint attachment, Texture* rt); +/*depth buffer和stencil buffer如果传0,绑定到屏幕缓冲区*/ +void fbo_attachdepthbuffer(FrameBuffer* fb, float* depthbuffer); +void fbo_attachstencilbuffer(FrameBuffer* fb, byte* stencilbuffer); + +void fbo_free(FrameBuffer* fb); #endif
\ No newline at end of file diff --git a/src/core/rasterizer.c b/src/core/rasterizer.c index 2319d44..5618fde 100644 --- a/src/core/rasterizer.c +++ b/src/core/rasterizer.c @@ -80,28 +80,33 @@ static void puttriangle(Vec2* A, Vec2* B, Vec2* C, Color c) { ssrR_putline(C->x, C->y, B->x, B->y, c); } -#define discardif(condition) if(condition) continue - extern FragmentShaderIn ssr_frag_in; -void ssrR_triangle( Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Program* program, UniformCollection* uniforms ) { +void ssrR_triangle( + Vec4* CA, Vec4* CB, Vec4* CC, + uint IA, uint IB, uint IC, + Program* program, + UniformCollection* uniforms +) { ssr_assert(CA && CB && CC && program); - static Vec3 SA, SB, SC; - static Vec3 bc; - + Vec3 SA, SB, SC; vec4_dividew(CA, &SA); ssrU_viewport(&SA, &SA); vec4_dividew(CB, &SB); ssrU_viewport(&SB, &SB); vec4_dividew(CC, &SC); ssrU_viewport(&SC, &SC); + /* puttriangle(&SA, &SB, &SC, 0xffff0000); return; */ - Vec3 *sa = &SA, *sb = &SB, *sc = &SC, *tmp; Vec4* v4tmp; Vert* vtemp; + + Vec3 *sa = &SA, *sb = &SB, *sc = &SC, *tmp; + Vec4 *v4tmp; + uint itmp; #define swap(t, a, b) {t = a; a = b; b = t;} /*sort in y axis*/ - if (sb->y < sa->y) { swap(tmp, sa, sb); swap(v4tmp, CA, CB); swap(vtemp, A, B); } - if (sc->y < sb->y) { swap(tmp, sb, sc); swap(v4tmp, CB, CC); swap(vtemp, B, C); } - if (sb->y < sa->y) { swap(tmp, sa, sb); swap(v4tmp, CA, CB); swap(vtemp, A, B); } + if (sb->y < sa->y) { swap(tmp, sa, sb); swap(v4tmp, CA, CB); swap(itmp, IA, IB); } + if (sc->y < sb->y) { swap(tmp, sb, sc); swap(v4tmp, CB, CC); swap(itmp, IB, IC); } + if (sb->y < sa->y) { swap(tmp, sa, sb); swap(v4tmp, CA, CB); swap(itmp, IA, IB); } #undef swap Vec2 AB = {sb->x - sa->x, sb->y - sa->y}, AC = { sc->x - sa->x, sc->y - sa->y }; @@ -111,60 +116,75 @@ void ssrR_triangle( Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Pro float invkAB = (sb->x - sa->x) / (sb->y - sa->y + EPSILON); float invkBC = (sc->x - sb->x) / (sc->y - sb->y + EPSILON); - Color32 color; float from, to; - Vec2 p; float depth; float CAw = 1.f / CA->w, CBw = 1.f / CB->w, CCw = 1.f / CC->w; - uint varying_flag = program->varying_flag; + 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); + bool write_stencil = ssr_iswritesencil(); + + bool pass_depth_test = TRUE; + bool pass_stencil_test = TRUE; + bool discard = FALSE; + + FragmentShader frag_shader = program->fragmentshader; + + Vec3 s[2], u; /*edge of triangle*/ - Vec3 s[2], u; s[0].x = sc->x - sa->x; s[0].y = sb->x - sa->x; s[1].x = sc->y - sa->y; s[1].y = sb->y - sa->y; - 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); + Vec2 p; + Vec3 bc; + +#define discardif(condition) if(condition) continue #define RENDER_TRIANGLE \ - for (p.y = FROM->y; p.y < TO->y + OFFSET; ++p.y) { \ - SET_FROM_AND_TO \ - s[1].z = sa->y - p.y; \ - for (p.x = from; order * (p.x - to) <= 0; p.x += order) { \ - s[0].z = sa->x - p.x; \ - vec3_cross(&s[0], &s[1], &u); \ - discardif(compare(u.z, 0)); \ - u.z = 1.f / u.z; \ - bc.x = 1.f - (u.x + u.y) * u.z; \ - bc.y = u.y * u.z; \ - bc.z = u.x * u.z; \ - discardif(bc.x < 0 || bc.y < 0 || bc.z < 0); \ - /*perspective correction*/ \ - bc.x *= CAw; bc.y *= CBw; bc.z *= CCw; \ - vec3_scale(&bc, 1.f / (bc.x + bc.y + bc.z), &bc); \ - /*early depth testing*/ \ - if(depth_test ){ \ - depth = bc.x*sa->z+bc.y*sb->z+bc.z*sc->z; \ - discardif(!ssr_testdepth(p.x, p.y, depth)); \ - } \ - /*set varying variables*/ \ - ssrS_solveregs(&bc, A->index, B->index, C->index); \ - /*enter fragment shader*/ \ - if(program->fragmentshader(uniforms, &ssr_frag_in, &color)) { \ - /*blend*/ \ - if(blend) { \ - Color32 dst; dst = ssr_getfbocolor(p.x, p.y); \ - ssr_blend(&color, &dst, &color); \ - } \ - if(write_depth) { \ - ssr_writedepth(p.x, p.y, depth); \ - } \ - color32_saturate(&color); \ - ssr_putpoint32(p.x, p.y, &color); \ - } \ - } \ + for (p.y = FROM->y; p.y < TO->y + OFFSET; ++p.y) { \ + SET_FROM_AND_TO \ + s[1].z = sa->y - p.y; \ + for (p.x = from; order * (p.x - to) <= 0; p.x += order) { \ + /*calculate barycentric coordinate*/ \ + s[0].z = sa->x - p.x; \ + vec3_cross(&s[0], &s[1], &u); \ + discardif(compare(u.z, 0)); \ + u.z = 1.f / u.z; \ + bc.x = 1.f - (u.x + u.y) * u.z; \ + bc.y = u.y * u.z; \ + bc.z = u.x * u.z; \ + discardif(bc.x < 0 || bc.y < 0 || bc.z < 0); \ + /*perspective correction*/ \ + bc.x *= CAw; bc.y *= CBw; bc.z *= CCw; \ + vec3_scale(&bc, 1.f / (bc.x + bc.y + bc.z), &bc); \ + /*early depth testing*/ \ + if(depth_test){ \ + depth = bc.x*sa->z+bc.y*sb->z+bc.z*sc->z; \ + pass_depth_test = ssr_testdepth(p.x, p.y, depth); \ + } \ + /*early stencil testing*/ \ + if(stencil_test){ \ + pass_stencil_test = ssr_teststencil(p.x, p.y, pass_depth_test); \ + } \ + discardif(!pass_depth_test || !pass_stencil_test); \ + /*interpolate varying variables*/ \ + ssrS_solveregs(&bc, IA, IB, IC); \ + /*enter fragment shader*/ \ + discard = !frag_shader(uniforms, &ssr_frag_in, out_color[0]); \ + discardif(discard); \ + /*put point*/ \ + ssr_blendandputpoint(p.x, p.y, blend); \ + /*write depth and stencil*/ \ + if(write_depth) { \ + ssr_writedepth(p.x, p.y, depth); \ + } \ + if(write_stencil) { \ + ssr_writestencil(p.x, p.y, pass_depth_test, pass_stencil_test); \ + } \ + } \ } #define FROM sa @@ -194,6 +214,8 @@ void ssrR_triangle( Vec4* CA, Vec4* CB, Vec4* CC, Vert* A, Vert* B, Vert* C, Pro } RENDER_TRIANGLE + +#undef discardif #undef FROM #undef TO diff --git a/src/core/rasterizer.h b/src/core/rasterizer.h index 4fa2482..5f29677 100644 --- a/src/core/rasterizer.h +++ b/src/core/rasterizer.h @@ -13,6 +13,6 @@ bool ssrR_barycentric(Vec2* A, Vec2* B, Vec2* C, Vec2* p, Vec3* out); /*计算重心 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, Vert* A, Vert* B, Vert* C, Program* program, UniformCollection* uniforms); +void ssrR_triangle(Vec4* CA, Vec4* CB, Vec4* CC, uint IA, uint IB, uint IC, Program* program, UniformCollection* uniforms); #endif
\ No newline at end of file diff --git a/src/core/shader.c b/src/core/shader.c index aa271ed..b28a5e2 100644 --- a/src/core/shader.c +++ b/src/core/shader.c @@ -3,42 +3,6 @@ #include "vert.h" #include "device.h" -float* reg_num_00; -float* reg_num_01; -float* reg_num_02; -float* reg_num_03; - -Vec2* reg_v2_00; -Vec2* reg_v2_01; -Vec2* reg_v2_02; -Vec2* reg_v2_03; -Vec2* reg_v2_04; -Vec2* reg_v2_05; -Vec2* reg_v2_06; -Vec2* reg_v2_07; - -Vec3* reg_v3_00; -Vec3* reg_v3_01; -Vec3* reg_v3_02; -Vec3* reg_v3_03; -Vec3* reg_v3_04; -Vec3* reg_v3_05; -Vec3* reg_v3_06; -Vec3* reg_v3_07; -Vec3* reg_v3_08; -Vec3* reg_v3_09; -Vec3* reg_v3_10; -Vec3* reg_v3_11; - -Vec4* reg_v4_00; -Vec4* reg_v4_01; -Vec4* reg_v4_02; -Vec4* reg_v4_03; -Vec4* reg_v4_04; -Vec4* reg_v4_05; -Vec4* reg_v4_06; -Vec4* reg_v4_07; - extern FragmentShaderIn ssr_frag_in; Register registers[REG_TOTAL] = { @@ -164,7 +128,7 @@ void ssrS_setactiveregc() { /*set active reg data from clipping buffer*/ } /*计算寄存器中的值并输出*/ -void ssrS_solveregs(Vec3* bc, uint a, uint b, uint c) { +void ssrS_solveregs(Vec3* bc, uint ia, uint ib, uint ic) { int index = 0; uint stride = 0; ActiveReg* reg; @@ -175,9 +139,9 @@ void ssrS_solveregs(Vec3* bc, uint a, uint b, uint c) { stride = reg->element_size; *reg->accessor = reg->bcp_interpolator( bc - , ®->data[a*stride] - , ®->data[b*stride] - , ®->data[c*stride] + , ®->data[ia*stride] + , ®->data[ib*stride] + , ®->data[ic*stride] , reg->output ); } @@ -299,3 +263,14 @@ void ssrS_lerpvec4(float t, Vec4* A, Vec4* B, Vec4* out) { out->z = lerp(A->z, B->z, t); out->w = lerp(A->w, B->w, t); } + +static Color32 _out_color[RENDER_TARGET_COUNT]; + +Color32* out_color[RENDER_TARGET_COUNT] = { + &_out_color[0], + &_out_color[1], + &_out_color[2], + &_out_color[3], + &_out_color[4], + &_out_color[5], +}; diff --git a/src/core/shader.h b/src/core/shader.h index 15edf4c..9ae757b 100644 --- a/src/core/shader.h +++ b/src/core/shader.h @@ -4,6 +4,7 @@ #include "../math/math.h" #include "vert.h" #include "texture.h" +#include "framebuffer.h" typedef struct { /*built in varaibles*/ @@ -174,10 +175,13 @@ void ssrS_setregisters(int capacity); /*设置寄存器指针,指向寄存器(在fragment阶段,指针会指向fragmentIn结构)*/ void ssrS_setupregisterpointers(int idx); -/*设置寄存器指针,指向fragIn结构*/ +/*set register accessor, point to fragin struct*/ void ssrS_setregtofragin(); #define tex2d(tex, uv) \ -texture_sampling(tex, ssr_getfiltermode(), ssr_getwrapmode(), (uv)->x, (uv)->y) +texture_sampling(tex, (uv)->x, (uv)->y) + +/*frame color buffer output*/ +Color32* out_color[RENDER_TARGET_COUNT]; #endif
\ No newline at end of file diff --git a/src/core/stencil.c b/src/core/stencil.c new file mode 100644 index 0000000..3127544 --- /dev/null +++ b/src/core/stencil.c @@ -0,0 +1,69 @@ +#include "stencil.h" +#include "mem.h" +#include "../util/assert.h" + +bool stencil_always(byte src, byte ref) { + return 1; +} + +bool stencil_never(byte src, byte ref) { + return 0; +} + +bool stencil_less(byte src, byte ref) { + return src < ref; +} + +bool stencil_equal(byte src, byte ref) { + return src == ref; +} + +bool stencil_leuqal(byte src, byte ref) { + return src <= ref; +} + +bool stencil_greater(byte src, byte ref) { + return src > ref; +} + +bool stencil_notequal(byte src, byte ref) { + return src != ref; +} + +bool stencil_gequer(byte src, byte ref) { + return src >= ref; +} + +/*stencil op*/ + +byte stencilop_keep(byte src, byte ref) { + return src; +} + +byte stencilop_zero(byte src, byte ref) { + return 0; +} + +byte stencilop_replace(byte src, byte ref) { + return ref; +} + +byte stencilop_incr(byte src, byte ref) { + return src == 0xff ? 0xff : src + 1; +} + +byte stencilop_incrwrap(byte src, byte ref) { + return src == 0xff ? 0 : src + 1; +} + +byte stencilop_decr(byte src, byte ref) { + return src == 0 ? 0 : src - 1; +} + +byte stencilop_decrwrap(byte src, byte ref) { + return src == 0 ? 0xff : src - 1; +} + +byte stencilop_invert(byte src, byte ref) { + return (~src) & 0xff; +} diff --git a/src/core/stencil.h b/src/core/stencil.h new file mode 100644 index 0000000..8af73d0 --- /dev/null +++ b/src/core/stencil.h @@ -0,0 +1,28 @@ +#ifndef _SOFTSHADEROOM_STENCIL_H_ +#define _SOFTSHADEROOM_STENCIL_H_ + +#include "../util/type.h" + +typedef bool(*StencilFunc)(byte src, byte ref); + +bool stencil_always(byte src, byte ref); +bool stencil_never(byte src, byte ref); +bool stencil_less(byte src, byte ref); +bool stencil_equal(byte src, byte ref); +bool stencil_leuqal(byte src, byte ref); +bool stencil_greater(byte src, byte ref); +bool stencil_notequal(byte src, byte ref); +bool stencil_gequer(byte src, byte ref); + +typedef byte (*StencilOp)(byte src, byte ref); + +byte stencilop_keep(byte src, byte ref); +byte stencilop_zero(byte src, byte ref); +byte stencilop_replace(byte src, byte ref); +byte stencilop_incr(byte src, byte ref); +byte stencilop_incrwrap(byte src, byte ref); +byte stencilop_decr(byte src, byte ref); +byte stencilop_decrwrap(byte src, byte ref); +byte stencilop_invert(byte src, byte ref); + +#endif
\ No newline at end of file diff --git a/src/core/texture.c b/src/core/texture.c index c7dc884..33a00c5 100644 --- a/src/core/texture.c +++ b/src/core/texture.c @@ -48,11 +48,23 @@ Texture* texture_loadfromfile(const char* path) { 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; } +Texture* texture_create(uint width, uint height) { + Texture* tex = ssrM_new(Texture); + tex->pixels = ssrM_newvector(Color32, width*height); + tex->width = width; + tex->height = height; + tex->filter_mode = FILTERMODE_POINT; + tex->wrap_mode = WRAPMODE_CLAMP; + return tex; +} + 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); @@ -64,8 +76,10 @@ static Color32 sampling(Texture* tex, WrapMode wrap_mode, int x, int y) { return tex->pixels[x + y * tex->width]; } -Color32 texture_sampling(Texture* tex, FilterMode filter_mode, WrapMode wrap_mode, float x01, float y01) { +Color32 texture_sampling(Texture* tex, float x01, float y01) { ssr_assert(tex); + 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); @@ -94,3 +108,19 @@ Color32 texture_sampling(Texture* tex, FilterMode filter_mode, WrapMode wrap_mod } */ } + +void texture_setfiltermode(Texture* tex, FilterMode filter) { + ssr_assert(tex); + tex->filter_mode = filter; +} + +void texture_setwrapmode(Texture* tex, WrapMode wrap) { + ssr_assert(tex); + tex->wrap_mode = wrap; +} + +void texture_free(Texture* tex) { + if (tex->pixels) + ssrM_free(tex->pixels); + ssrM_free(tex); +} diff --git a/src/core/texture.h b/src/core/texture.h index 9e0d884..06016ad 100644 --- a/src/core/texture.h +++ b/src/core/texture.h @@ -14,13 +14,26 @@ typedef enum { WRAPMODE_CLAMP, } WrapMode; +typedef enum { + COMPONENT_RGBA, + COMPONENT_DEPTH +} TextureComponent; + typedef struct { uint width, height; - Color32* pixels; + Color32* pixels; /*RGBA*/ + FilterMode filter_mode; + WrapMode wrap_mode; } Texture; Texture* texture_loadfromfile(const char* path); +Texture* texture_create(uint width, uint height); + +void texture_setfiltermode(Texture* tex, FilterMode filter); +void texture_setwrapmode(Texture* tex, WrapMode wrap); + +Color32 texture_sampling(Texture* tex, float x, float y); -Color32 texture_sampling(Texture* tex, FilterMode filter_mode, WrapMode wrap_mode, float x, float y); +void texture_free(Texture* tex); #endif
\ No newline at end of file diff --git a/src/core/vert.h b/src/core/vert.h index faf027e..8578d87 100644 --- a/src/core/vert.h +++ b/src/core/vert.h @@ -16,6 +16,8 @@ typedef uint Color; // ARGB typedef Vec4 Color32; +Color32 COLOR32_WHITE; + Color color32_tocolor(Color32* c); void color_tocolor32(Color c, Color32* out); void color32_saturate(Color32* c); |