summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2023-01-06 09:25:11 -0800
committer3gg <3gg@shellblade.net>2023-01-06 09:25:11 -0800
commitc447ba1064ec9b170dfbee30d3b49da4cf8e0ffd (patch)
tree0ed81dc5b2e1c3f4441a941733815dfe46a5ef53
parent3db2b6fe574ce7d2e0b49720f0453b824a4d8312 (diff)
More spec-compliant rendering of albedo and metal-roughness.
-rw-r--r--gfx/shaders/cook_torrance.frag24
-rw-r--r--gfx/src/renderer/renderer.c1
-rw-r--r--gfx/src/util/scene.c64
-rw-r--r--gltfview/src/game.c15
4 files changed, 71 insertions, 33 deletions
diff --git a/gfx/shaders/cook_torrance.frag b/gfx/shaders/cook_torrance.frag
index 18d9d18..fcedef6 100644
--- a/gfx/shaders/cook_torrance.frag
+++ b/gfx/shaders/cook_torrance.frag
@@ -5,8 +5,12 @@ uniform float MetallicFactor;
5uniform float RoughnessFactor; 5uniform float RoughnessFactor;
6uniform vec3 EmissiveFactor; 6uniform vec3 EmissiveFactor;
7 7
8#ifdef HAS_ALBEDO_MAP
8uniform sampler2D BaseColorTexture; 9uniform sampler2D BaseColorTexture;
10#endif
11#ifdef HAS_METALLIC_ROUGHNESS_MAP
9uniform sampler2D MetallicRoughnessTexture; 12uniform sampler2D MetallicRoughnessTexture;
13#endif
10#ifdef HAS_EMISSIVE_MAP 14#ifdef HAS_EMISSIVE_MAP
11uniform sampler2D EmissiveTexture; 15uniform sampler2D EmissiveTexture;
12#endif 16#endif
@@ -161,10 +165,22 @@ void main()
161 //float HdotV = clamp(dot(H,V), 0.0, 1.0); // Clamp to prevent black spots. 165 //float HdotV = clamp(dot(H,V), 0.0, 1.0); // Clamp to prevent black spots.
162 166
163 // TODO: BaseColorFactor and BaseColorTexture are vec4/rgba quantities 167 // TODO: BaseColorFactor and BaseColorTexture are vec4/rgba quantities
164 // respectively. Handle the alpha channel later. 168 // respectively. Handle the alpha channel.
165 // TODO: Other factors. 169 // TODO: Other factors.
170#ifdef HAS_ALBEDO_MAP
166 vec3 albedo = vec3(BaseColorFactor) * texture(BaseColorTexture, Texcoord).rgb; 171 vec3 albedo = vec3(BaseColorFactor) * texture(BaseColorTexture, Texcoord).rgb;
167 vec3 metal_roughness = texture(MetallicRoughnessTexture, Texcoord).rgb; 172#else
173 vec3 albedo = vec3(BaseColorFactor);
174#endif
175#ifdef HAS_METALLIC_ROUGHNESS_MAP
176 // Spec: "Its green channel contains roughness values and its blue channel
177 // contains metalness values."
178 vec2 metal_roughness
179 = vec2(MetallicFactor, RoughnessFactor)
180 * texture(MetallicRoughnessTexture, Texcoord).bg;
181#else
182 vec2 metal_roughness = vec2(MetallicFactor, RoughnessFactor);
183#endif
168#ifdef HAS_EMISSIVE_MAP 184#ifdef HAS_EMISSIVE_MAP
169 vec3 emissive = texture(EmissiveTexture, Texcoord).rgb; 185 vec3 emissive = texture(EmissiveTexture, Texcoord).rgb;
170#else 186#else
@@ -175,8 +191,8 @@ void main()
175#else 191#else
176 float occlusion = 0.0; 192 float occlusion = 0.0;
177#endif 193#endif
178 float metallic = MetallicFactor * metal_roughness.b; 194 float metallic = metal_roughness.x;
179 float roughness = metal_roughness.g; 195 float roughness = metal_roughness.y;
180 196
181 // For a single light direction: 197 // For a single light direction:
182 // vec3 brdf = cook_torrance(albedo, metallic, roughness, emissive, NdotL, NdotV, NdotH, HdotV); 198 // vec3 brdf = cook_torrance(albedo, metallic, roughness, emissive, NdotL, NdotV, NdotH, HdotV);
diff --git a/gfx/src/renderer/renderer.c b/gfx/src/renderer/renderer.c
index 6b77ffe..3654546 100644
--- a/gfx/src/renderer/renderer.c
+++ b/gfx/src/renderer/renderer.c
@@ -29,6 +29,7 @@ bool renderer_make(Renderer* renderer, RenderBackend* render_backend) {
29 assert(renderer); 29 assert(renderer);
30 assert(render_backend); 30 assert(render_backend);
31 31
32 // TODO: Load the IBL stuff lazily.
32 if (!(renderer->ibl = gfx_make_ibl(render_backend))) { 33 if (!(renderer->ibl = gfx_make_ibl(render_backend))) {
33 renderer_destroy(renderer, render_backend); 34 renderer_destroy(renderer, render_backend);
34 return false; 35 return false;
diff --git a/gfx/src/util/scene.c b/gfx/src/util/scene.c
index 52812e9..35d6dd0 100644
--- a/gfx/src/util/scene.c
+++ b/gfx/src/util/scene.c
@@ -130,12 +130,14 @@
130#define UNIFORM_NORMAL_MAP "NormalMap" 130#define UNIFORM_NORMAL_MAP "NormalMap"
131 131
132// Shader compiler defines. Must match the names in shaders. 132// Shader compiler defines. Must match the names in shaders.
133#define DEFINE_HAS_TEXCOORDS "HAS_TEXCOORDS" 133#define DEFINE_HAS_TEXCOORDS "HAS_TEXCOORDS"
134#define DEFINE_HAS_NORMALS "HAS_NORMALS" 134#define DEFINE_HAS_NORMALS "HAS_NORMALS"
135#define DEFINE_HAS_TANGENTS "HAS_TANGENTS" 135#define DEFINE_HAS_TANGENTS "HAS_TANGENTS"
136#define DEFINE_HAS_NORMAL_MAP "HAS_NORMAL_MAP" 136#define DEFINE_HAS_ALBEDO_MAP "HAS_ALBEDO_MAP"
137#define DEFINE_HAS_OCCLUSION_MAP "HAS_OCCLUSION_MAP" 137#define DEFINE_HAS_METALLIC_ROUGHNESS_MAP "HAS_METALLIC_ROUGHNESS_MAP"
138#define DEFINE_HAS_EMISSIVE_MAP "HAS_EMISSIVE_MAP" 138#define DEFINE_HAS_NORMAL_MAP "HAS_NORMAL_MAP"
139#define DEFINE_HAS_OCCLUSION_MAP "HAS_OCCLUSION_MAP"
140#define DEFINE_HAS_EMISSIVE_MAP "HAS_EMISSIVE_MAP"
139 141
140typedef enum TextureType { 142typedef enum TextureType {
141 BaseColorTexture, 143 BaseColorTexture,
@@ -155,9 +157,11 @@ typedef struct MeshPermutation {
155 bool has_normals : 1; 157 bool has_normals : 1;
156 bool has_tangents : 1; 158 bool has_tangents : 1;
157 // Textures. 159 // Textures.
158 bool has_normal_map : 1; 160 bool has_albedo_map : 1;
159 bool has_occlusion_texture : 1; 161 bool has_metallic_roughness_map : 1;
160 bool has_emissive_texture : 1; 162 bool has_normal_map : 1;
163 bool has_occlusion_map : 1;
164 bool has_emissive_map : 1;
161 }; 165 };
162 int32_t all; 166 int32_t all;
163 }; 167 };
@@ -179,9 +183,11 @@ static size_t make_defines(
179 check(has_texcoords, DEFINE_HAS_TEXCOORDS); 183 check(has_texcoords, DEFINE_HAS_TEXCOORDS);
180 check(has_normals, DEFINE_HAS_NORMALS); 184 check(has_normals, DEFINE_HAS_NORMALS);
181 check(has_tangents, DEFINE_HAS_TANGENTS); 185 check(has_tangents, DEFINE_HAS_TANGENTS);
186 check(has_albedo_map, DEFINE_HAS_ALBEDO_MAP);
187 check(has_metallic_roughness_map, DEFINE_HAS_METALLIC_ROUGHNESS_MAP);
182 check(has_normal_map, DEFINE_HAS_NORMAL_MAP); 188 check(has_normal_map, DEFINE_HAS_NORMAL_MAP);
183 check(has_occlusion_texture, DEFINE_HAS_OCCLUSION_MAP); 189 check(has_occlusion_map, DEFINE_HAS_OCCLUSION_MAP);
184 check(has_emissive_texture, DEFINE_HAS_EMISSIVE_MAP); 190 check(has_emissive_map, DEFINE_HAS_EMISSIVE_MAP);
185 191
186 return next; 192 return next;
187} 193}
@@ -191,10 +197,11 @@ static ShaderProgram* make_shader_permutation(
191 RenderBackend* render_backend, MeshPermutation perm) { 197 RenderBackend* render_backend, MeshPermutation perm) {
192 LOGD( 198 LOGD(
193 "Compiling Cook-Torrance shader permutation: texcoords: %d, normals: " 199 "Compiling Cook-Torrance shader permutation: texcoords: %d, normals: "
194 "%d, tangents: %d, normal map: %d, AO map: %d, emissive map: %d", 200 "%d, tangents: %d, albedo map: %d, metallic-roughness map: %d, normal "
201 "map: %d, AO map: %d, emissive map: %d",
195 perm.has_texcoords, perm.has_normals, perm.has_tangents, 202 perm.has_texcoords, perm.has_normals, perm.has_tangents,
196 perm.has_normal_map, perm.has_occlusion_texture, 203 perm.has_albedo_map, perm.has_metallic_roughness_map, perm.has_normal_map,
197 perm.has_emissive_texture); 204 perm.has_occlusion_map, perm.has_emissive_map);
198 205
199 ShaderCompilerDefine defines[GFX_MAX_SHADER_COMPILER_DEFINES]; 206 ShaderCompilerDefine defines[GFX_MAX_SHADER_COMPILER_DEFINES];
200 const size_t num_defines = make_defines(perm, defines); 207 const size_t num_defines = make_defines(perm, defines);
@@ -436,9 +443,11 @@ static bool load_materials(
436 Material** materials) { 443 Material** materials) {
437 assert(data); 444 assert(data);
438 assert(render_backend); 445 assert(render_backend);
439 assert(load_texture_cmds);
440 assert(textures);
441 assert(materials); 446 assert(materials);
447 if (data->textures_count > 0) {
448 assert(load_texture_cmds);
449 assert(textures);
450 }
442 451
443 for (cgltf_size i = 0; i < data->materials_count; ++i) { 452 for (cgltf_size i = 0; i < data->materials_count; ++i) {
444 const cgltf_material* mat = &data->materials[i]; 453 const cgltf_material* mat = &data->materials[i];
@@ -446,7 +455,7 @@ static bool load_materials(
446 int next_uniform = 0; 455 int next_uniform = 0;
447 MaterialDesc desc = {0}; 456 MaterialDesc desc = {0};
448 457
449 // TODO: emissive texture/factor and other material parameters. 458 // TODO: specular/glossiness and other material parameters.
450 if (mat->has_pbr_metallic_roughness) { 459 if (mat->has_pbr_metallic_roughness) {
451 const cgltf_pbr_metallic_roughness* pbr = &mat->pbr_metallic_roughness; 460 const cgltf_pbr_metallic_roughness* pbr = &mat->pbr_metallic_roughness;
452 461
@@ -579,10 +588,17 @@ static bool load_meshes(
579 const cgltf_primitive* prim = &mesh->primitives[p]; 588 const cgltf_primitive* prim = &mesh->primitives[p];
580 const cgltf_material* mat = prim->material; 589 const cgltf_material* mat = prim->material;
581 590
582 MeshPermutation perm = {0}; 591 MeshPermutation perm = {0};
583 perm.has_normal_map = mat->normal_texture.texture != 0; 592 perm.has_normal_map = mat->normal_texture.texture != 0;
584 perm.has_occlusion_texture = mat->occlusion_texture.texture != 0; 593 perm.has_occlusion_map = mat->occlusion_texture.texture != 0;
585 perm.has_emissive_texture = mat->emissive_texture.texture != 0; 594 perm.has_emissive_map = mat->emissive_texture.texture != 0;
595 // TODO: specular/glossiness and other material parameters.
596 if (mat->has_pbr_metallic_roughness) {
597 const cgltf_pbr_metallic_roughness* pbr = &mat->pbr_metallic_roughness;
598 perm.has_albedo_map = pbr->base_color_texture.texture != 0;
599 perm.has_metallic_roughness_map =
600 pbr->metallic_roughness_texture.texture != 0;
601 }
586 602
587 GeometryDesc geometry_desc = { 603 GeometryDesc geometry_desc = {
588 .type = from_gltf_primitive_type(prim->type)}; 604 .type = from_gltf_primitive_type(prim->type)};
@@ -949,8 +965,10 @@ static bool load_scene(
949 goto cleanup; 965 goto cleanup;
950 } 966 }
951 967
952 load_textures_lazy( 968 if (data->textures_count > 0) {
953 data, render_backend, mstring_cstring(&directory), load_texture_cmds); 969 load_textures_lazy(
970 data, render_backend, mstring_cstring(&directory), load_texture_cmds);
971 }
954 972
955 if (!load_materials( 973 if (!load_materials(
956 data, render_backend, load_texture_cmds, textures, materials)) { 974 data, render_backend, load_texture_cmds, textures, materials)) {
diff --git a/gltfview/src/game.c b/gltfview/src/game.c
index 54e498b..224200d 100644
--- a/gltfview/src/game.c
+++ b/gltfview/src/game.c
@@ -189,8 +189,8 @@ static bool load_texture_debugger_scene(Game* game) {
189 189
190bool game_new(Game* game, int argc, const char** argv) { 190bool game_new(Game* game, int argc, const char** argv) {
191 // TODO: getopt() to implement proper argument parsing. 191 // TODO: getopt() to implement proper argument parsing.
192 const char* view_mode = argc > 1 ? argv[1] : ""; 192 const char* scene_filepath = argc > 1 ? argv[1] : DEFAULT_SCENE_FILE;
193 const char* scene_filepath = argc > 2 ? argv[2] : DEFAULT_SCENE_FILE; 193 const char* view_mode = argc > 2 ? argv[2] : "";
194 194
195 game->gfx = gfx_init(); 195 game->gfx = gfx_init();
196 if (!game->gfx) { 196 if (!game->gfx) {
@@ -234,12 +234,15 @@ void game_update(Game* game, double t, double dt) {
234 usleep(1000); 234 usleep(1000);
235 game->elapsed -= 1.0; 235 game->elapsed -= 1.0;
236 } 236 }
237 Camera* camera = gfx_get_camera_camera(game->camera); 237 // TODO: Compute bounding boxes to then find a good orbit point and radius
238 // for each scene.
239 const vec3 orbit_point = vec3_make(0, 2, 0);
240 Camera* camera = gfx_get_camera_camera(game->camera);
238 spatial3_orbit( 241 spatial3_orbit(
239 &camera->spatial, vec3_make(0, 0, 0), 242 &camera->spatial, orbit_point,
240 /*radius=*/2, 243 /*radius=*/2.5,
241 /*azimuth=*/t * 0.5, /*zenith=*/0); 244 /*azimuth=*/t * 0.5, /*zenith=*/0);
242 spatial3_lookat(&camera->spatial, vec3_make(0, 0, 0)); 245 spatial3_lookat(&camera->spatial, orbit_point);
243} 246}
244 247
245void game_render(const Game* game) { 248void game_render(const Game* game) {