summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-12-21 22:24:15 +0800
committerchai <chaifix@163.com>2019-12-21 22:24:15 +0800
commitec111247c614663d8231245a17c314b9b8b4a28c (patch)
treea66058508161da488371c90316865ae850b8be15
parentc3f45735ecfab6e567be371758f21395e92dfef6 (diff)
*misc
-rw-r--r--src/core/clip.c44
-rw-r--r--src/core/clip.h9
-rw-r--r--src/core/color.c2
-rw-r--r--src/core/depth.c35
-rw-r--r--src/core/depth.h17
-rw-r--r--src/core/device.c396
-rw-r--r--src/core/device.h62
-rw-r--r--src/core/framebuffer.c5
-rw-r--r--src/core/framebuffer.h22
-rw-r--r--src/core/rasterizer.c130
-rw-r--r--src/core/rasterizer.h2
-rw-r--r--src/core/shader.c55
-rw-r--r--src/core/shader.h8
-rw-r--r--src/core/stencil.c69
-rw-r--r--src/core/stencil.h28
-rw-r--r--src/core/texture.c32
-rw-r--r--src/core/texture.h17
-rw-r--r--src/core/vert.h2
-rw-r--r--src/example/01_dot/01_dot.c (renamed from src/example/01_dot.c)4
-rw-r--r--src/example/02_cube/02_cube.c (renamed from src/example/02_cube.c)2
-rw-r--r--src/example/03_texture/03_texture.c (renamed from src/example/03_texture.c)65
-rw-r--r--src/example/04_bloom.c0
-rw-r--r--src/example/04_bloom/04_bloom.c120
-rw-r--r--src/example/04_bloom/postprocess.c41
-rw-r--r--src/example/04_bloom/preprocess.c31
-rw-r--r--src/example/05_fog/05_fog.c (renamed from src/example/05_fog.c)0
-rw-r--r--src/example/06_shadow/06_shadow.c1
-rw-r--r--src/example/example.h1
-rw-r--r--src/extend/mesh.c4
-rw-r--r--src/extend/mesh.h2
-rw-r--r--src/extern/stb_image.h32
-rw-r--r--src/math/math.h7
-rw-r--r--src/math/vec4.c7
-rw-r--r--src/shaders/common.h13
34 files changed, 963 insertions, 302 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], &registers[index].data[v0->index*size], size);
- ssrM_copy(&temp_clip_buffer_data[index][size], &registers[index].data[v1->index*size], size);
- ssrM_copy(&temp_clip_buffer_data[index][2*size], &registers[index].data[v2->index*size], 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);
+ ssrM_copy(&temp_clip_buffer_data[index][2*size], &registers[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
- , &reg->data[a*stride]
- , &reg->data[b*stride]
- , &reg->data[c*stride]
+ , &reg->data[ia*stride]
+ , &reg->data[ib*stride]
+ , &reg->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);
diff --git a/src/example/01_dot.c b/src/example/01_dot/01_dot.c
index 0a88084..e2902ca 100644
--- a/src/example/01_dot.c
+++ b/src/example/01_dot/01_dot.c
@@ -1,5 +1,5 @@
-#include "example.h"
-#include "../core/rasterizer.h"
+#include "../example.h"
+#include "../../core/rasterizer.h"
Vec3 pos = { 0, 0, 2 }, target = { 0,0,-1 }, up = { 0, 1, 0 };
diff --git a/src/example/02_cube.c b/src/example/02_cube/02_cube.c
index c1f2796..4e540e0 100644
--- a/src/example/02_cube.c
+++ b/src/example/02_cube/02_cube.c
@@ -1,4 +1,4 @@
-#include "example.h"
+#include "../example.h"
/*正方体*/
Vec3 verts[] = {
diff --git a/src/example/03_texture.c b/src/example/03_texture/03_texture.c
index 0e48fcb..a0493bb 100644
--- a/src/example/03_texture.c
+++ b/src/example/03_texture/03_texture.c
@@ -1,5 +1,5 @@
-#include "example.h"
-#include "../extend/mesh.h"
+#include "../example.h"
+#include "../../extend/mesh.h"
static int cube[] = {
0, 1, 2, 0, 2, 3,
@@ -37,22 +37,19 @@ static Mesh* ground_mesh;
static Texture* yingham_albedo;
static Mesh* yingham_mesh;
-static Texture* gun_albedo;
-static Mesh* gun_mesh;
+static Texture* cyborg_albedo;
+static Mesh* cyborg_mesh;
void onloadtexture(void* data) {
ssr_matrixmode(MATRIX_PROJECTION);
ssr_loadidentity();
- ssr_perspective(90, ssr_getaspect(), 0.1f, 1500);
+ ssr_perspective(90, ssr_getaspect(), 0.1, 10);
//ssr_ortho(-5, 5, -4, 4, 0.1, 10);
ssr_bindvertices(verts, 8, cube, 12);
ssr_useprogram(&ssr_built_in_shader_pbr);
ssr_enable(ENABLE_BACKFACECULL | ENABLE_DEPTHTEST | ENABLE_WRITEDEPTH | ENABLE_BLEND);
- ssr_setwrapmode(WRAPMODE_CLAMP);
- ssr_setfiltermode(FILTERMODE_POINT);
-
ssr_setblendfunc(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
mech_albedo = texture_loadfromfile("res/dieselpunk/mech_basecolor.tga");
@@ -64,6 +61,9 @@ void onloadtexture(void* data) {
ground_mesh = mesh_loadfromobj("res/dieselpunk/ground.obj");
yingham_albedo = texture_loadfromfile("res/dieselpunk/yingham_basecolor.tga");
yingham_mesh = mesh_loadfromobj("res/dieselpunk/yingham.obj");
+
+ cyborg_albedo = texture_loadfromfile("res/cyborg/cyborg_diffuse.png");
+ cyborg_mesh = mesh_loadfromobj("res/cyborg/cyborg.obj");
}
void oneventtexture(void* data) {
@@ -79,8 +79,8 @@ void onupdatetexture(void*data) {
ssr_matrixmode(MATRIX_VIEW);
ssr_loadidentity();
- float distance = 800;
- Vec3 p = { distance * sin(_t), 300, distance * cos(_t) }, target = { 0, 0, 0 };
+ float distance = 2;
+ Vec3 p = { distance * sin(_t), 3, distance * cos(_t) }, target = { 0, 0, 0 };
//Vec3 p = { 0, 0, 700}, target = { 0, 0, 0 };
ssr_lookat(&p, &target, &vec3up);
@@ -103,20 +103,35 @@ void onupdatetexture(void*data) {
void ondrawtexture(void*data) {
ssr_clearcolor(0xff202020);
ssr_cleardepth();
-
- ssr_setuniformtex(0, mech_albedo);
- ssr_setuniformtex(1, mech_normal);
- ssr_setuniformtex(2, mech_roughness);
- ssr_setuniformtex(3, mech_metalness);
- ssr_bindvertices(mech_mesh->vertices, mech_mesh->verts_count, mech_mesh->triangles, mech_mesh->tris_count);
- ssr_draw(PRIMITIVE_TRIANGLE);
-
- ssr_setuniformtex(0, ground_albedo);
- ssr_bindvertices(ground_mesh->vertices, ground_mesh->verts_count, ground_mesh->triangles, ground_mesh->tris_count);
- ssr_draw(PRIMITIVE_TRIANGLE);
-
- ssr_setuniformtex(0, yingham_albedo);
- ssr_bindvertices(yingham_mesh->vertices, yingham_mesh->verts_count, yingham_mesh->triangles, yingham_mesh->tris_count);
- ssr_draw(PRIMITIVE_TRIANGLE);
+ ssr_clearstencil(0);
+///*
+// ssr_enable(ENABLE_STENCILTEST);
+// ssr_setstencilfunc(STENCILFUNC_ALWAYS, 1, 0xff);
+// ssr_setstencilop(STENCILOP_KEEP, STENCILOP_KEEP, STENCILOP_REPLACE);
+//*/
+// /*render mech*/
+// ssr_setuniformtex(0, mech_albedo);
+// ssr_setuniformtex(1, mech_normal);
+// ssr_setuniformtex(2, mech_roughness);
+// ssr_setuniformtex(3, mech_metalness);
+// ssr_bindvertices(mech_mesh->vertices, mech_mesh->vert_count, mech_mesh->triangles, mech_mesh->tris_count);
+// ssr_draw(PRIMITIVE_TRIANGLE);
+///*
+// ssr_setstencilfunc(STENCILFUNC_EQUAL, 1, 0xff);
+// ssr_setstencilop(STENCILOP_KEEP, STENCILOP_KEEP, STENCILOP_KEEP);
+//*/
+// /*render yingham*/
+// ssr_setuniformtex(0, yingham_albedo);
+// ssr_bindvertices(yingham_mesh->vertices, yingham_mesh->vert_count, yingham_mesh->triangles, yingham_mesh->tris_count);
+// ssr_draw(PRIMITIVE_TRIANGLE);
+//
+// /*render ground*/
+// ssr_setuniformtex(0, ground_albedo);
+// ssr_bindvertices(ground_mesh->vertices, ground_mesh->vert_count, ground_mesh->triangles, ground_mesh->tris_count);
+// ssr_draw(PRIMITIVE_TRIANGLE);
+//
+ ssr_setuniformtex(0, cyborg_albedo);
+ ssr_bindvertices(cyborg_mesh->vertices, cyborg_mesh->vert_count, cyborg_mesh->triangles, cyborg_mesh->tris_count);
+ ssr_draw(PRIMITIVE_TRIANGLE);
}
diff --git a/src/example/04_bloom.c b/src/example/04_bloom.c
deleted file mode 100644
index e69de29..0000000
--- a/src/example/04_bloom.c
+++ /dev/null
diff --git a/src/example/04_bloom/04_bloom.c b/src/example/04_bloom/04_bloom.c
new file mode 100644
index 0000000..6f37f62
--- /dev/null
+++ b/src/example/04_bloom/04_bloom.c
@@ -0,0 +1,120 @@
+#include "../example.h"
+#include "../../extend/mesh.h"
+
+static int cube[] = {
+ 0, 1, 2, 0, 2, 3,
+ 1, 5, 2, 2, 5, 6,
+ 4, 6, 5, 4, 7, 6,
+ 0, 3, 7, 0, 7, 4,
+ 0, 4, 1, 1, 4, 5,
+ 2, 6, 3, 3, 6, 7
+};
+
+static Vert verts[] = {
+ {0, {1, 1, 1}, {1, 1, 1}, zerovec4, {1, 1}, 0xffff0000},
+ {1, {-1, 1, 1}, {-1, 1, 1}, zerovec4, {0, 1},0xff00ff00},
+ {2, {-1, -1, 1}, {-1, -1, 1}, zerovec4, {0, 0}, 0xff0000ff},
+ {3, {1, -1, 1}, {1, -1, 1}, zerovec4, {1, 0}, 0xffff00ff},
+ {4, {1, 1, -1}, {1, 1, -1}, zerovec4, {1, 0} , 0xffaa28aa},
+ {5, {-1, 1, -1}, {-1, 1, -1}, zerovec4, {0, 0},0xffFFC58E},
+ {6, {-1, -1, -1}, {-1, -1, -1}, zerovec4, {0, 1}, 0xffA100FF},
+ {7, {1, -1, -1}, {1, -1, -1}, zerovec4, {1, 1} , 0xffFAFF00},
+};
+
+extern Program _04_bloom_preprocess;
+extern Program _04_bloom_postprocess;
+
+static Vec3 light = { -1, -1, -1 };
+
+static Texture* cyborg_albedo;
+static Mesh* cyborg_mesh;
+
+static FrameBuffer* fbo;
+static float* depth_buffer;
+static byte* stencil_buffer;
+
+static Texture* albedo_tex;
+static Texture* bright_tex;
+
+void onloadbloom(void* data) {
+ ssr_matrixmode(MATRIX_PROJECTION);
+ ssr_loadidentity();
+ ssr_perspective(90, ssr_getaspect(), 0.1, 10);
+ //ssr_ortho(-5, 5, -4, 4, 0.1, 10);
+
+
+ ssr_setblendfunc(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
+
+ albedo_tex = texture_create(600, 480);
+ bright_tex = texture_create(600, 480);
+
+ depth_buffer = ssrM_newvector(float, 600 * 480);
+ stencil_buffer = ssrM_newvector(byte, 600 * 480);
+
+ fbo = fbo_create();
+ fbo_attachrendertexture(fbo, 0, albedo_tex);
+ fbo_attachrendertexture(fbo, 1, bright_tex);
+ fbo_attachdepthbuffer(fbo, depth_buffer);
+ fbo_attachstencilbuffer(fbo, stencil_buffer);
+}
+
+void oneventbloom(void* data) {
+ SDL_Event* e = (SDL_Event*)data;
+}
+
+static float _t = 0;
+static Quat q;
+
+void onupdatebloom(void*data) {
+ uint dt = *(uint*)data;
+ _t += dt / 1000.f;
+
+ ssr_matrixmode(MATRIX_VIEW);
+ ssr_loadidentity();
+ float distance = 2;
+ Vec3 p = { distance * sin(_t), 5, distance * cos(_t) }, target = { 0, 0, 0 };
+ ssr_lookat(&p, &target, &vec3up);
+
+ ssr_matrixmode(MATRIX_MODEL);
+ ssr_loadidentity();
+}
+
+static void renderquad() {
+ /*全屏特效*/
+ static Vert verts[] = {
+ {0, {1, 1, 0}, zerovec3, zerovec3, {1, 1}, 0},
+ {1, {-1, 1, 0}, zerovec3, zerovec3, {0, 1},0},
+ {2, {-1, -1, 0}, zerovec3, zerovec3, {0, 0}, 0},
+ {3, {1, -1, 0}, zerovec3, zerovec3, {1, 0}, 0},
+ };
+ static int quad[] = {
+ 0, 1, 2, 0, 2, 3,
+ };
+ ssr_useprogram(&_04_bloom_postprocess);
+ ssr_bindvertices(verts, 4, quad, 2);
+ ssr_setuniformtex(0, albedo_tex);
+ ssr_setuniformtex(1, bright_tex);
+ ssr_draw(PRIMITIVE_TRIANGLE);
+}
+
+void ondrawbloom(void*data) {
+ ssr_enable(ENABLE_BACKFACECULL | ENABLE_DEPTHTEST | ENABLE_BLEND | ENABLE_WRITEDEPTH);
+
+ /*render cube*/
+ ssr_bindframebuffer(fbo);
+ ssr_clearcolor(0xff202020);
+ ssr_cleardepth();
+ ssr_clearstencil(0);
+ ssr_bindvertices(verts, 8, cube, 12);
+ ssr_useprogram(&_04_bloom_preprocess);
+ ssr_bindvertices(verts, 8, cube, 12);
+ ssr_draw(PRIMITIVE_TRIANGLE);
+
+ ssr_disable(ENABLE_BLEND | ENABLE_DEPTHTEST | ENABLE_WRITEDEPTH | ENABLE_BACKFACECULL);
+ ssr_unbindframebuffer();
+ ssr_clearcolor(0xff202020);
+ ssr_cleardepth();
+ ssr_clearstencil(0);
+
+ renderquad();
+}
diff --git a/src/example/04_bloom/postprocess.c b/src/example/04_bloom/postprocess.c
new file mode 100644
index 0000000..1ec10e4
--- /dev/null
+++ b/src/example/04_bloom/postprocess.c
@@ -0,0 +1,41 @@
+#include "../../shaders/common.h"
+
+/*uniforms*/
+#define _frag_tex UTEX(0)
+#define _bright_tex UTEX(1)
+
+/*varyings*/
+#define _texcoord reg_v2_00
+
+static float weight[5] = { 0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162 };
+
+static void vert(UniformCollection* uniforms, VertexShaderIn* in, Vec4* clipcoord) {
+ clipcoord->xyz = in->vertex->position;
+ clipcoord->w = 1;
+ *_texcoord = in->vertex->texcoord;
+}
+
+static bool frag(UniformCollection* uniforms, FragmentShaderIn* in, Color32* color) {
+ float off = 1 / 600.f;
+ //blur
+ *color = tex2d(_frag_tex, _texcoord);
+ vec4_scale(color, weight[0], color);
+ Vec2 p = {0, _texcoord->y};
+ Color32 c;
+ for (int i = 1; i < 5; ++i) {
+ p.x = _texcoord->x + off * i;
+ c = tex2d(_frag_tex, &p);
+ vec4_scale(&c, weight[i], &c);
+ vec4_add(color, &c, color);
+ p.x = _texcoord->x - off * i;
+ c = tex2d(_frag_tex, &p);
+ vec4_scale(&c, weight[i], &c);
+ vec4_add(color, &c, color);
+ }
+ return 1;
+}
+
+Program _04_bloom_postprocess = {
+ vert, frag,
+ VARYING_V2_00
+};
diff --git a/src/example/04_bloom/preprocess.c b/src/example/04_bloom/preprocess.c
new file mode 100644
index 0000000..def9fd8
--- /dev/null
+++ b/src/example/04_bloom/preprocess.c
@@ -0,0 +1,31 @@
+#include "../../shaders/common.h"
+
+/*uniforms*/
+
+/*varyings*/
+#define _color reg_v4_00
+
+static void vert(UniformCollection* uniforms, VertexShaderIn* in, Vec4* clipcoord) {
+ static Vec4 p; p.xyz = in->vertex->position; p.w = 1;
+ mat4_mulvec4(uniforms->mvp, &p, clipcoord);
+ color_tocolor32(in->vertex->color, _color);
+}
+
+/*multi target*/
+#define _frag_color out_color[0]
+#define _bright_color out_color[1]
+
+static bool frag(UniformCollection* uniforms, FragmentShaderIn* in, Color32* color) {
+ //_frag_color->r = 1;
+ //_frag_color->g = 1;
+ //_frag_color->b = 1;
+ //_frag_color->a = 1;
+ //*_bright_color = *_color;
+ *_frag_color = *_color;
+ return 1;
+}
+
+Program _04_bloom_preprocess = {
+ vert, frag,
+ VARYING_V4_00
+};
diff --git a/src/example/05_fog.c b/src/example/05_fog/05_fog.c
index e69de29..e69de29 100644
--- a/src/example/05_fog.c
+++ b/src/example/05_fog/05_fog.c
diff --git a/src/example/06_shadow/06_shadow.c b/src/example/06_shadow/06_shadow.c
new file mode 100644
index 0000000..015aafd
--- /dev/null
+++ b/src/example/06_shadow/06_shadow.c
@@ -0,0 +1 @@
+/*real time shadow*/
diff --git a/src/example/example.h b/src/example/example.h
index 15b547e..6cb9a64 100644
--- a/src/example/example.h
+++ b/src/example/example.h
@@ -19,5 +19,6 @@ EXAMPLE(cube);
EXAMPLE(line);
EXAMPLE(dot);
EXAMPLE(texture);
+EXAMPLE(bloom);
#endif \ No newline at end of file
diff --git a/src/extend/mesh.c b/src/extend/mesh.c
index 4993222..c8cdf2a 100644
--- a/src/extend/mesh.c
+++ b/src/extend/mesh.c
@@ -115,7 +115,7 @@ static Mesh *build_mesh(
}
mesh->tris_count = num_faces;
- mesh->verts_count = nvert;
+ mesh->vert_count = nvert;
mesh->vertices = vertices;
//mesh->center = vec3_div(vec3_add(bbox_min, bbox_max), 2);
@@ -199,7 +199,7 @@ Mesh* mesh_loadfromobj(const char *filename) {
darray_free(texcoord_indices);
darray_free(normal_indices);
- printf("%s: %d verts, %d tris\n", filename, mesh->verts_count, mesh->tris_count);
+ printf("%s: %d verts, %d tris\n", filename, mesh->vert_count, mesh->tris_count);
return mesh;
}
diff --git a/src/extend/mesh.h b/src/extend/mesh.h
index 40ac7ed..2c52669 100644
--- a/src/extend/mesh.h
+++ b/src/extend/mesh.h
@@ -4,7 +4,7 @@
#include "../core/vert.h"
typedef struct Mesh {
- Vert* vertices; uint verts_count;
+ Vert* vertices; uint vert_count;
uint* triangles; uint tris_count;
} Mesh;
diff --git a/src/extern/stb_image.h b/src/extern/stb_image.h
index 4df317a..37c4bf7 100644
--- a/src/extern/stb_image.h
+++ b/src/extern/stb_image.h
@@ -3823,7 +3823,7 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int
typedef struct
{
- stbi_uc *zbuffer, *zbuffer_end;
+ stbi_uc *depth_buffer, *depth_buffer_end;
int num_bits;
stbi__uint32 code_buffer;
@@ -3837,8 +3837,8 @@ typedef struct
stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
{
- if (z->zbuffer >= z->zbuffer_end) return 0;
- return *z->zbuffer++;
+ if (z->depth_buffer >= z->depth_buffer_end) return 0;
+ return *z->depth_buffer++;
}
static void stbi__fill_bits(stbi__zbuf *z)
@@ -4036,11 +4036,11 @@ static int stbi__parse_uncompressed_block(stbi__zbuf *a)
len = header[1] * 256 + header[0];
nlen = header[3] * 256 + header[2];
if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG");
- if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG");
+ if (a->depth_buffer + len > a->depth_buffer_end) return stbi__err("read past buffer","Corrupt PNG");
if (a->zout + len > a->zout_end)
if (!stbi__zexpand(a, a->zout, len)) return 0;
- memcpy(a->zout, a->zbuffer, len);
- a->zbuffer += len;
+ memcpy(a->zout, a->depth_buffer, len);
+ a->depth_buffer += len;
a->zout += len;
return 1;
}
@@ -4130,8 +4130,8 @@ STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int
stbi__zbuf a;
char *p = (char *) stbi__malloc(initial_size);
if (p == NULL) return NULL;
- a.zbuffer = (stbi_uc *) buffer;
- a.zbuffer_end = (stbi_uc *) buffer + len;
+ a.depth_buffer = (stbi_uc *) buffer;
+ a.depth_buffer_end = (stbi_uc *) buffer + len;
if (stbi__do_zlib(&a, p, initial_size, 1, 1)) {
if (outlen) *outlen = (int) (a.zout - a.zout_start);
return a.zout_start;
@@ -4151,8 +4151,8 @@ STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, i
stbi__zbuf a;
char *p = (char *) stbi__malloc(initial_size);
if (p == NULL) return NULL;
- a.zbuffer = (stbi_uc *) buffer;
- a.zbuffer_end = (stbi_uc *) buffer + len;
+ a.depth_buffer = (stbi_uc *) buffer;
+ a.depth_buffer_end = (stbi_uc *) buffer + len;
if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) {
if (outlen) *outlen = (int) (a.zout - a.zout_start);
return a.zout_start;
@@ -4165,8 +4165,8 @@ STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, i
STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
{
stbi__zbuf a;
- a.zbuffer = (stbi_uc *) ibuffer;
- a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
+ a.depth_buffer = (stbi_uc *) ibuffer;
+ a.depth_buffer_end = (stbi_uc *) ibuffer + ilen;
if (stbi__do_zlib(&a, obuffer, olen, 0, 1))
return (int) (a.zout - a.zout_start);
else
@@ -4178,8 +4178,8 @@ STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int
stbi__zbuf a;
char *p = (char *) stbi__malloc(16384);
if (p == NULL) return NULL;
- a.zbuffer = (stbi_uc *) buffer;
- a.zbuffer_end = (stbi_uc *) buffer+len;
+ a.depth_buffer = (stbi_uc *) buffer;
+ a.depth_buffer_end = (stbi_uc *) buffer+len;
if (stbi__do_zlib(&a, p, 16384, 1, 0)) {
if (outlen) *outlen = (int) (a.zout - a.zout_start);
return a.zout_start;
@@ -4192,8 +4192,8 @@ STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int
STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)
{
stbi__zbuf a;
- a.zbuffer = (stbi_uc *) ibuffer;
- a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
+ a.depth_buffer = (stbi_uc *) ibuffer;
+ a.depth_buffer_end = (stbi_uc *) ibuffer + ilen;
if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
return (int) (a.zout - a.zout_start);
else
diff --git a/src/math/math.h b/src/math/math.h
index 8793336..e63c603 100644
--- a/src/math/math.h
+++ b/src/math/math.h
@@ -151,9 +151,9 @@ extern Vec3 vec3zero; /*(0,0,0)*/
extern Vec2 vec2zero; /*(0,0,0)*/
extern Vec4 vec4zero; /*(0,0,0)*/
-#define zerovec3 {0, 0, 0}
#define zerovec2 {0, 0}
-#define zerovec4 {0, 0, 0}
+#define zerovec3 {0, 0, 0}
+#define zerovec4 {0, 0, 0, 0}
void vec3_tostring(Vec3* v, char buf[]);
void vec3_print(Vec3* v);
@@ -186,6 +186,9 @@ void vec4_lerp(Vec4* a, Vec4* b, float t, Vec4* out);
void vec4_scale(Vec4* v, float t, Vec4* out);
+void vec4_add(Vec4* v1, Vec4* v2, Vec4* out);
+
+
/************************************************************************/
/* Matrix */
/************************************************************************/
diff --git a/src/math/vec4.c b/src/math/vec4.c
index 202aabd..71ec6b6 100644
--- a/src/math/vec4.c
+++ b/src/math/vec4.c
@@ -38,3 +38,10 @@ void vec4_scale(Vec4* v, float t, Vec4* out) {
out->z = v->z * t;
out->w = v->w * t;
}
+
+void vec4_add(Vec4* v1, Vec4* v2, Vec4* out) {
+ out->x = v1->x + v2->x;
+ out->y = v1->y + v2->y;
+ out->z = v1->z + v2->z;
+ out->w = v1->w + v2->w;
+}
diff --git a/src/shaders/common.h b/src/shaders/common.h
index 2779c7b..8b74bec 100644
--- a/src/shaders/common.h
+++ b/src/shaders/common.h
@@ -13,4 +13,17 @@ Vec3 normal_from_color(Color32 c32);
Mat4 mat4(Vec4* c1, Vec4* c2, Vec4* c3, Vec4* c4);
Mat3 mat3(Vec3* c1, Vec3* c2, Vec3* c3);
+Vec2 texsize(Texture* texture);
+
+#define discardif(cond) \
+do{ \
+if(cond) return 0; \
+}while(0)
+
+#define MVP_PROCESS \
+do{ \
+static Vec4 p; p.xyz = in->vertex->position; p.w = 1; \
+mat4_mulvec4(uniforms->mvp, &p, clipcoord); \
+}while(0)
+
#endif \ No newline at end of file