From e5e995103377f9bb79123ef8257d8680ed0945fc Mon Sep 17 00:00:00 2001 From: chai Date: Sat, 18 Jul 2020 02:48:39 +0800 Subject: *late culling --- Release/SoftShadeRoom.exe | Bin 130560 -> 131584 bytes src/core/clip.c | 2 +- src/core/device.c | 38 +++++++++--- src/core/rasterizer.c | 22 +++++-- src/example/03_texture/03_texture.c | 21 ++++--- src/extend/mesh.c | 120 ++++++++++++++++++++++++++++++++++-- src/extend/mesh.h | 17 ++++- src/main.c | 12 ++-- src/shaders/pbr.c | 2 +- 9 files changed, 197 insertions(+), 37 deletions(-) diff --git a/Release/SoftShadeRoom.exe b/Release/SoftShadeRoom.exe index db29a49..99c9fda 100644 Binary files a/Release/SoftShadeRoom.exe and b/Release/SoftShadeRoom.exe differ 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 +#include +#include + #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 \n" -"Options: \n" -" -b set baking target image\n" +" SoftShadeRoom \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; } -- cgit v1.1-26-g67d0