summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2020-07-18 02:48:39 +0800
committerchai <chaifix@163.com>2020-07-18 02:48:39 +0800
commite5e995103377f9bb79123ef8257d8680ed0945fc (patch)
tree1831f3d2242c8173075576816b9032001580d20b /src
parent275bf123ff505eef3333ba41385ed3814eb9a507 (diff)
*late culling
Diffstat (limited to 'src')
-rw-r--r--src/core/clip.c2
-rw-r--r--src/core/device.c38
-rw-r--r--src/core/rasterizer.c22
-rw-r--r--src/example/03_texture/03_texture.c21
-rw-r--r--src/extend/mesh.c120
-rw-r--r--src/extend/mesh.h17
-rw-r--r--src/main.c12
-rw-r--r--src/shaders/pbr.c2
8 files changed, 197 insertions, 37 deletions
diff --git a/src/core/clip.c b/src/core/clip.c
index 2880448..d5de4fc 100644
--- a/src/core/clip.c
+++ b/src/core/clip.c
@@ -145,7 +145,7 @@ static bool is_inside_plane(Vec4* c, Plane plane) {
case NEGATIVE_Y:
return c->y >= -c->w;
case POSITIVE_Z:
- return c->z <= +c->w;
+ return c->z <= c->w;
case NEGATIVE_Z:
return c->z >= -c->w;
default:
diff --git a/src/core/device.c b/src/core/device.c
index ac055c9..923a2fa 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -498,18 +498,36 @@ static void render_prims_triangle(uint varying_flag) {
c1 = &clip_coords.coords[i1];
c2 = &clip_coords.coords[i2];
- /*back face culling*/
+ /*early back face culling*/
+ bool early_culled = FALSE;
if (ssr_isenable(ENABLE_BACKFACECULL)) {
/*cull in ndc*/
float w0 = 1 / c0->w, w1 = 1 / c1->w, w2 = 1 / c2->w;
- Vec3 ab, ac;
- ab.x = c1->x * w1 - c0->x * w0;
- ab.y = c1->y * w1 - c0->y * w0;
- ac.x = c2->x * w2 - c0->x * w0;
- ac.y = c2->y * w2 - c0->y * w0;
- if (ab.x * ac.y - ab.y * ac.x <= 0) {
- continue; /*cull*/
+ bool all_front = w0 > 0 && w1 > 0 && w2 > 0;
+ if (all_front)
+ {
+ early_culled = TRUE;
+ Vec2 ab, ac;
+ ab.x = c1->x * w1 - c0->x * w0;
+ ab.y = c1->y * w1 - c0->y * w0;
+ ac.x = c2->x * w2 - c0->x * w0;
+ ac.y = c2->y * w2 - c0->y * w0;
+ if (ab.x * ac.y - ab.y * ac.x <= 0) {
+ continue; /*cull*/
+ }
}
+ //OpenGL algrithm:
+ //float w0 = max(1 / c0->w, 0), w1 = 1 / c1->w, w2 = 1 / c2->w;
+ //Vec2 a = { c0->x * w0, c0->y * w0 };
+ //Vec2 b = { c1->x * w1, c1->y * w1 };
+ //Vec2 c = { c2->x * w2, c2->y * w2 };
+ //float signed_area = 0;
+ //signed_area += a.x * b.y - a.y * b.x;
+ //signed_area += b.x * c.y - b.y * c.x;
+ //signed_area += c.x * a.y - c.y * a.x;
+ //if (signed_area <= 0) {
+ // continue; /*cull*/
+ //}
}
/*clipping*/
@@ -521,7 +539,7 @@ static void render_prims_triangle(uint varying_flag) {
reset_active_reg = FALSE;
ssrS_setactiveregr();
}
- ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program, &state.uniforms);
+ ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program, &state.uniforms, early_culled);
}
else {
if (!reset_active_reg) {
@@ -535,7 +553,7 @@ static void render_prims_triangle(uint varying_flag) {
vt2 = &clip_buffer.vertices[i + 1];
c0 = &vt0->clip_coord; c1 = &vt1->clip_coord; c2 = &vt2->clip_coord;
i0 = vt0->index; i1 = vt1->index; i2 = vt2->index;
- ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program, &state.uniforms);
+ ssrR_triangle(c0, c1, c2, i0, i1, i2, state.program, &state.uniforms, early_culled);
}
}
}
diff --git a/src/core/rasterizer.c b/src/core/rasterizer.c
index 28ae639..c5745ba 100644
--- a/src/core/rasterizer.c
+++ b/src/core/rasterizer.c
@@ -86,19 +86,31 @@ void ssrR_triangle(
Vec4* CA, Vec4* CB, Vec4* CC,
uint IA, uint IB, uint IC,
Program* program,
- UniformCollection* uniforms
+ UniformCollection* uniforms,
+ bool early_culled
) {
ssr_assert(CA && CB && CC && program);
+ /*late back face culling*/
+ if (!early_culled && ssr_isenable(ENABLE_BACKFACECULL)) {
+ float w0 = 1 / CA->w, w1 = 1 / CB->w, w2 = 1 / CC->w;
+ Vec2 ab, ac;
+ ab.x = CB->x * w1 - CA->x * w0;
+ ab.y = CB->y * w1 - CA->y * w0;
+ ac.x = CC->x * w2 - CA->x * w0;
+ ac.y = CC->y * w2 - CA->y * w0;
+ if (ab.x * ac.y - ab.y * ac.x <= 0) {
+ return;
+ }
+ }
+
Vec4 SA, SB, SC;
internal_vec4_dividewnoz(CA, &SA); ssrU_viewport(&SA, &SA);
internal_vec4_dividewnoz(CB, &SB); ssrU_viewport(&SB, &SB);
internal_vec4_dividewnoz(CC, &SC); ssrU_viewport(&SC, &SC);
-/*
- puttriangle(&SA, &SB, &SC, 0xffff0000);
- return;
-*/
+ //puttriangle(&SA, &SB, &SC, 0xffff0000);
+ //return;
Vec4 *sa = &SA, *sb = &SB, *sc = &SC, *tmp;
Vec4 *v4tmp;
diff --git a/src/example/03_texture/03_texture.c b/src/example/03_texture/03_texture.c
index 5afb3de..09d8f97 100644
--- a/src/example/03_texture/03_texture.c
+++ b/src/example/03_texture/03_texture.c
@@ -46,11 +46,14 @@ static Mesh* ball_mesh;
EXAMPLE void onload_texture(void* data) {
CameraConfig* conf = (CameraConfig*)data;
- mech_albedo = texture_loadfromfile("res/dieselpunk/mech_basecolor.tga");
+ //mech_albedo = texture_loadfromfile("res/dieselpunk/mech_basecolor.tga");
+ mech_albedo = texture_loadfromfile("res/gun/gun.png");
mech_normal = texture_loadfromfile("res/dieselpunk/mech_normal.tga");
mech_roughness = texture_loadfromfile("res/dieselpunk/mech_roughness.tga");
mech_metalness = texture_loadfromfile("res/dieselpunk/mech_metalness.tga");
- mech_mesh = mesh_loadfromobj("res/dieselpunk/mech.obj");
+ //mech_mesh = mesh_loadfromobj("res/dieselpunk/mech.obj");
+ mech_mesh = mesh_loadfromobj("res/gun/gun.obj");
+ //mech_mesh = mesh_loadfromobj("res/gun/triangle.obj");
ground_albedo = texture_loadfromfile("res/dieselpunk/ground_basecolor.tga");
ground_mesh = mesh_loadfromobj("res/dieselpunk/ground.obj");
yingham_albedo = texture_loadfromfile("res/dieselpunk/yingham_basecolor.tga");
@@ -78,7 +81,7 @@ EXAMPLE void onupdate_texture(void*data) {
}
EXAMPLE void ondraw_texture(void*data) {
- ssr_bindvertices(verts, 8, cube, 12);
+ //ssr_bindvertices(verts, 8, cube, 12);
ssr_useprogram(&ssr_built_in_shader_pbr);
ssr_enable(ENABLE_BACKFACECULL | ENABLE_DEPTHTEST | ENABLE_WRITEDEPTH | ENABLE_BLEND);
@@ -106,14 +109,14 @@ EXAMPLE void ondraw_texture(void*data) {
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);
+ //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, ground_albedo);
+ //ssr_bindvertices(ground_mesh->vertices, ground_mesh->vert_count, ground_mesh->triangles, ground_mesh->tris_count);
+ //ssr_draw(PRIMITIVE_TRIANGLE);
//draw_tbn(mech_mesh, VISUAL_ALL, 4);
diff --git a/src/extend/mesh.c b/src/extend/mesh.c
index 90e8bf5..394a7e8 100644
--- a/src/extend/mesh.c
+++ b/src/extend/mesh.c
@@ -1,11 +1,19 @@
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
#include "mesh.h"
#include "../util/darray.h"
#include "../shaders/common/mathlib.h"
+#include "../math/math.h"
#define GENERATE_TANGNET
//#define GENERATE_NORMAL
//#define OPTIMIZE_MESH
+#define SMOOTH_TANGENT 1
+#define IMPORT_POLYGON 1
+
#define LINE_SIZE 1024
#define UNUSED_VAR(x) ((void)(x))
@@ -225,6 +233,7 @@ Mesh* mesh_loadfromobj(const char* path) {
FILE *file;
file = fopen(path, "rb");
assert(file != NULL);
+
char line[LINE_SIZE];
while (1) {
@@ -232,6 +241,9 @@ Mesh* mesh_loadfromobj(const char* path) {
if (fgets(line, LINE_SIZE, file) == NULL) {
break;
}
+ else if (strncmp(line, "o ", 2) == 0) { /* submesh name */
+ // ignore
+ }
else if (strncmp(line, "v ", 2) == 0) { /* position */
Vec3 position;
items = sscanf(line, "v %f %f %f",
@@ -242,6 +254,16 @@ Mesh* mesh_loadfromobj(const char* path) {
VertexListElement element = { 0 };
darray_push(vertex_list, element);
}
+ else if (strncmp(line, "v ", 3) == 0) { /* position */
+ Vec3 position;
+ items = sscanf(line, "v %f %f %f",
+ &position.x, &position.y, &position.z);
+ assert(items == 3);
+ darray_push(position_list, position);
+ // init vertex_list
+ VertexListElement element = { 0 };
+ darray_push(vertex_list, element);
+ }
else if (strncmp(line, "vt ", 3) == 0) { /* texcoord */
Vec2 texcoord;
items = sscanf(line, "vt %f %f",
@@ -257,6 +279,29 @@ Mesh* mesh_loadfromobj(const char* path) {
darray_push(normal_list, normal);
}
else if (strncmp(line, "f ", 2) == 0) { /* face */
+#if IMPORT_POLYGON
+ FaceVertex face_vert = { 0 };
+ FaceVertex *face_verts = NULL;
+ char* p = line + 1; // skip f
+ while (p && *p != 0) {
+ items = sscanf(p, " %d/%d/%d", &face_vert.posIndex, &face_vert.uvIndex, &face_vert.normalIndex);
+ if (items == 3) {
+ darray_push(face_verts, face_vert);
+ ++p;// skip \s
+ p = strchr(p, ' ');
+ }
+ else ++p;
+ }
+ assert(face_verts && darray_size(face_verts) > 0);
+ FaceVertex* v0 = &face_verts[0];
+ for (int i = 1; i < darray_size(face_verts) - 1; ++i) {
+ FaceVertex* v1 = &face_verts[i];
+ FaceVertex* v2 = &face_verts[i + 1];
+ FaceInfo face = { *v0, *v1, *v2};
+ darray_push(face_list, face);
+ }
+ darray_free(face_verts);
+#else
FaceInfo face;
items = sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", // only support triangle
&face.vertices[0].posIndex, &face.vertices[0].uvIndex, &face.vertices[0].normalIndex,
@@ -264,11 +309,13 @@ Mesh* mesh_loadfromobj(const char* path) {
&face.vertices[2].posIndex, &face.vertices[2].uvIndex, &face.vertices[2].normalIndex);
assert(items == 9);
darray_push(face_list, face);
+#endif
}
else
{
- // skip
+ // ignore
}
+ memset(&line, 0, LINE_SIZE);
}
int vert_counts = darray_size(vertex_list);
@@ -331,6 +378,18 @@ Mesh* mesh_loadfromobj(const char* path) {
darray_push(mesh_info.triangles, triangle);
}
+ fclose(file);
+
+ darray_free(position_list);
+ darray_free(normal_list);
+ darray_free(uv_list);
+ darray_free(face_list);
+ for (int i = 0; i < darray_size(vertex_list); ++i) {
+ VertexListElement* v = &vertex_list[i];
+ darray_free(v->vertices);
+ }
+ darray_free(vertex_list);
+
#ifdef GENERATE_TANGNET
calc_face_tanget(&mesh_info);
calc_vertex_tangnet(&mesh_info);
@@ -364,6 +423,8 @@ Mesh* build_mesh(MeshInfo* mesh_info) {
void calc_face_tanget(MeshInfo* mesh) {
MeshVertexInfo* vertices = mesh->vertices;
Triangle* faces = mesh->triangles;
+
+#if !SMOOTH_TANGENT
for (int i = 0; i < darray_size(faces); ++i) {
Triangle* face = &faces[i];
int v0 = face->vertices[0];
@@ -375,13 +436,62 @@ void calc_face_tanget(MeshInfo* mesh) {
// edge
Vec3 dp1 = vec3_minus(vertices[v1].props.position, vertices[v0].props.position);
Vec3 dp2 = vec3_minus(vertices[v2].props.position, vertices[v0].props.position);
- float f = 1.0f / (duv1.x * duv2.y - duv2.x * duv1.y);
+ float d = (duv1.x * duv2.y - duv2.x * duv1.y);
+ if (d == 0) d = 0.0000001f;
+ float f = 1.0f / d;
face->tangent.x = f * (duv2.y * dp1.x - duv1.y * dp2.x);
face->tangent.y = f * (duv2.y * dp1.y - duv1.y * dp2.y);
face->tangent.z = f * (duv2.y * dp1.z - duv1.y * dp2.z);
face->tangent = vec3_normalize(face->tangent);
}
- // 平均化三角形切线
+#else
+ Vec3* temp_tangents = NULL;
+ Vec3 tangent = {0};
+ for (int i = 0; i < darray_size(faces); ++i) {
+ Triangle* face = &faces[i];
+ int v0 = face->vertices[0];
+ int v1 = face->vertices[1];
+ int v2 = face->vertices[2];
+ // delta uv
+ Vec2 duv1 = vec2_minus(vertices[v1].props.texcoord, vertices[v0].props.texcoord);
+ Vec2 duv2 = vec2_minus(vertices[v2].props.texcoord, vertices[v0].props.texcoord);
+ // edge
+ Vec3 dp1 = vec3_minus(vertices[v1].props.position, vertices[v0].props.position);
+ Vec3 dp2 = vec3_minus(vertices[v2].props.position, vertices[v0].props.position);
+ float d = duv1.x * duv2.y - duv2.x * duv1.y;
+ if (d == 0) d = 0.0000001f;
+ float f = 1.0f / d;
+ tangent.x = f * (duv2.y * dp1.x - duv1.y * dp2.x);
+ tangent.y = f * (duv2.y * dp1.y - duv1.y * dp2.y);
+ tangent.z = f * (duv2.y * dp1.z - duv1.y * dp2.z);
+ tangent = vec3_normalize(tangent);
+ darray_push(temp_tangents, tangent);
+ }
+
+ float smooth_angle = 60;
+ float cos_smooth = cos(smooth_angle * DEG2RAG);
+
+ for (int i = 0; i < darray_size(faces); ++i) {
+ Triangle* face = &faces[i];
+ Vec3 tangent = temp_tangents[i];
+ Vec3 avarage_tangent = tangent;
+ for (int j = 0; j < 3; ++j)
+ {
+ MeshVertexInfo* vert = &vertices[face->vertices[j]];
+ for (int k = 0; k < darray_size(vert->related_triangles); ++k)
+ {
+ Vec3 related_triangle_tangent = temp_tangents[vert->related_triangles[k]];
+ if (vec3_dot(tangent, related_triangle_tangent) < cos_smooth) {
+ avarage_tangent = vec3_plus(avarage_tangent, related_triangle_tangent);
+ }
+ }
+ }
+ avarage_tangent = vec3_normalize(avarage_tangent);
+ face->tangent = avarage_tangent;
+ }
+
+ darray_free(temp_tangents);
+#endif
}
void calc_vertex_tangnet(MeshInfo* mesh) {
@@ -395,14 +505,14 @@ void calc_vertex_tangnet(MeshInfo* mesh) {
for (int j = 0; j < face_count; ++j) {
int face_index = vert->related_triangles[j];
Triangle* face = &faces[face_index];
- tangent = vec3_plus(tangent, face->tangent);
+ tangent = vec3_plus(tangent, face->tangent);
}
tangent = vec3_normalize(tangent);
- vert->props.tangent = vec4(tangent.x, tangent.y, tangent.z, 1);
// orthogonalize
bitangent = vec3_normalize(vec3_cross(vert->props.normal, tangent));
internal_vec3_orthogonalize(
&tangent, &bitangent, &vert->props.normal, &tangent, &bitangent, &vert->props.normal);
+ vert->props.tangent = vec4(tangent.x, tangent.y, tangent.z, 1);
}
}
diff --git a/src/extend/mesh.h b/src/extend/mesh.h
index b9b07f8..6bbb571 100644
--- a/src/extend/mesh.h
+++ b/src/extend/mesh.h
@@ -2,12 +2,25 @@
#define _SOFTSHADEROOM_MESH_H_
#include "../core/vert.h"
-
-typedef struct Mesh {
+/*
+typedef struct {
+ Vert* vertices;
+ uint vert_count;
+ uint* triangles;
+ uint tris_count;
+ const char* name;
+} SubMesh;
+*/
+typedef struct {
Vert* vertices;
uint vert_count;
uint* triangles;
uint tris_count;
+ //const char* name;
+ /*
+ SubMesh* submesh;
+ uint submesh_count;
+ */
} Mesh;
Mesh* mesh_loadfromobj(const char* path);
diff --git a/src/main.c b/src/main.c
index 850951b..2b6e853 100644
--- a/src/main.c
+++ b/src/main.c
@@ -31,10 +31,14 @@ static char* instruction =
" key-g show\\hide grid \n"
" key-b bake scene and save to png file(require -b option)\n"
"Usage: \n"
-" SoftShadeRoom <options> <example> \n"
-"Options: \n"
-" -b <image> set baking target image\n"
+" SoftShadeRoom <example> \n"
"Examples: \n"
+" dot \n"
+" cube \n"
+" texture \n"
+" bloom \n"
+" fog \n"
+" shadow \n"
" \n";
typedef void(*Callback)(void*);
@@ -144,7 +148,7 @@ int main(int argc, char* argv[]) {
ssr_present();
wog_updateSurface(wnd);
- //Sleep(1); /*reduce cpu using*/
+ Sleep(1); /*reduce cpu using*/
}
quit:
diff --git a/src/shaders/pbr.c b/src/shaders/pbr.c
index e4afbf4..556208e 100644
--- a/src/shaders/pbr.c
+++ b/src/shaders/pbr.c
@@ -27,7 +27,7 @@ static void vert(UniformCollection* uniforms, VertexShaderIn* in, Vec4* clipcoor
//*rough = 1 - internal_vec3_dot(&worldnormal, light);
//*vnormal = in->vertex->normal;
*_texcoord = in->vertex->texcoord;
- _clip_pos->x = clipcoord->z;
+ _clip_pos->x = clipcoord->z;
_clip_pos->y = clipcoord->w;
}