perf(gltf): optimize gltf material negotiation (#9038)

Co-authored-by: André Costa <andre_miguel_costa@hotmail.com>
This commit is contained in:
Matt
2025-10-30 12:34:13 -04:00
committed by GitHub
parent 7533a45cd1
commit 762d82f1ae
5 changed files with 57 additions and 40 deletions
+2 -1
View File
@@ -215,9 +215,10 @@ static unsigned int create_texture(int32_t w, int32_t h)
GL_CALL(glGenerateMipmap(GL_TEXTURE_2D));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
#else
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
#endif
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
GL_CALL(glBindTexture(GL_TEXTURE_2D, GL_NONE));
return texture;
@@ -467,6 +467,9 @@ bool injest_image(lv_opengl_shader_manager_t * shader_manager, lv_gltf_model_t *
LV_LOG_TRACE("Image (%s) [%d] [%u]", image.name.c_str(), texture_id, hash);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 20));
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
bool image_invalidated = false;
@@ -659,7 +662,7 @@ static bool injest_mesh(lv_gltf_model_t * data, fastgltf::Mesh & mesh)
if(material.transmission)
load_mesh_texture(data, material.transmission->transmissionTexture,
&primitive.transmissionTexture, (GLint *)&primitive.transmissionTexcoordIndex);
if(material.clearcoat) {
if(material.clearcoat && material.clearcoat->clearcoatFactor > 0.0f) {
load_mesh_texture(data, material.clearcoat->clearcoatTexture,
(GLuint *)&primitive.clearcoatTexture, &primitive.clearcoatTexcoordIndex);
load_mesh_texture(data, material.clearcoat->clearcoatRoughnessTexture,
@@ -669,7 +672,7 @@ static bool injest_mesh(lv_gltf_model_t * data, fastgltf::Mesh & mesh)
(GLuint *)&primitive.clearcoatNormalTexture,
&primitive.clearcoatNormalTexcoordIndex);
}
if(material.diffuseTransmission) {
if(material.diffuseTransmission && material.diffuseTransmission->diffuseTransmissionFactor > 0.0f) {
load_mesh_texture(data, material.diffuseTransmission->diffuseTransmissionTexture,
&primitive.diffuseTransmissionTexture,
&primitive.diffuseTransmissionTexcoordIndex);
@@ -2528,11 +2528,11 @@ static const lv_opengl_shader_t src_includes[] = {
#ifdef MATERIAL_UNLIT
//#ifdef HAS_EMISSIVE_MAP
// color = texture(u_EmissiveSampler, getEmissiveUV()).rgb;
//#else
#ifdef HAS_EMISSIVE_MAP
color = f_emissive;
#else
color = baseColor.rgb;
//#endif
#endif
#elif defined(NOT_TRIANGLE) && !defined(HAS_NORMAL_VEC3)
//Points or Lines with no NORMAL attribute SHOULD be rendered without lighting and instead use the sum of the base color value and the emissive value.
color = f_emissive + baseColor.rgb;
@@ -2767,7 +2767,9 @@ static const lv_opengl_shader_t src_includes[] = {
static const lv_opengl_shader_t env_src_includes[] = {
{
"fullscreen.vert", R"(
precision highp float;
precision lowp float;
// The vertex positions being supplied to this shader are
// always exactly 0 or 1, so low precision is fine here.
in vec2 aPosition;
in vec2 aTexCoord;
@@ -3437,7 +3439,7 @@ static const char *src_fragment_shader = R"(
// [5] "KHR_materials_clearcoat"
// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
precision highp float;
precision mediump float;
#include <tonemapping.glsl>
#include <textures1.glsl>
@@ -562,7 +562,7 @@ static void draw_material(lv_gltf_t * viewer, const lv_gltf_uniform_locations_t
uniforms->normal_uv_set, uniforms->normal_uv_transform);
}
if(gltfMaterial.clearcoat) {
if(gltfMaterial.clearcoat && gltfMaterial.clearcoat->clearcoatFactor > 0.0f) {
GL_CALL(glUniform1f(uniforms->clearcoat_factor, static_cast<float>(gltfMaterial.clearcoat->clearcoatFactor)));
GL_CALL(glUniform1f(uniforms->clearcoat_roughness_factor,
static_cast<float>(gltfMaterial.clearcoat->clearcoatRoughnessFactor)));
@@ -654,7 +654,7 @@ static void draw_material(lv_gltf_t * viewer, const lv_gltf_uniform_locations_t
}
#endif
if(gltfMaterial.diffuseTransmission) {
if(gltfMaterial.diffuseTransmission && gltfMaterial.diffuseTransmission->diffuseTransmissionFactor > 0.0f) {
render_uniform_color(uniforms->diffuse_transmission_color_factor,
gltfMaterial.diffuseTransmission->diffuseTransmissionColorFactor);
GL_CALL(glUniform1f(uniforms->diffuse_transmission_factor,
+40 -29
View File
@@ -99,40 +99,51 @@ lv_result_t lv_gltf_view_shader_injest_discover_defines(lv_array_t * result, lv_
if(add_define(result, "MATERIAL_UNLIT", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
if(add_define(result, "LINEAR_OUTPUT", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
}
else {
if(add_define(result, "MATERIAL_METALLICROUGHNESS", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
if(material.pbrData.baseColorFactor.x() == 0.0f
&& material.pbrData.baseColorFactor.y() == 0.0f
&& material.pbrData.baseColorFactor.z() == 0.0f
&& material.pbrData.metallicFactor == 1.0f
&& material.pbrData.roughnessFactor == 1.0f
&& material.emissiveStrength > 0.0f) {
/* Special case where settings preclude IBL's ability to have visible effect, so disable it entirely */
LV_LOG_TRACE("Special case identified, disabling IBL and enabling UNLIT\n");
if(add_define(result, "MATERIAL_UNLIT", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
}
if(add_define(result, "LINEAR_OUTPUT", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
else {
if(add_define(result, "MATERIAL_METALLICROUGHNESS", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
if(add_define(result, "USE_IBL", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
}
const size_t light_count = data->node_by_light_index.size();
if(light_count > 10) {
LV_LOG_ERROR("Too many scene lights, max is 10");
}
else if(light_count > 0) {
if(add_define(result, "USE_PUNCTUAL", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
char * count = (char *) lv_zalloc(5);
lv_snprintf(count, 5, "%zu", light_count);
if(add_define(result, "LIGHT_COUNT", count, true) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
}
else {
if(add_define(result, "LIGHT_COUNT", "0", false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
}
}
const size_t light_count = data->node_by_light_index.size();
if(add_define(result, "USE_IBL", NULL, false) == LV_RESULT_INVALID) {
if(add_define(result, "LINEAR_OUTPUT", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
if(light_count > 10) {
LV_LOG_ERROR("Too many scene lights, max is 10");
}
else if(light_count > 0) {
if(add_define(result, "USE_PUNCTUAL", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
char * count = (char *) lv_zalloc(5);
lv_snprintf(count, 5, "%zu", light_count);
if(add_define(result, "LIGHT_COUNT", count, true) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
}
else {
if(add_define(result, "LIGHT_COUNT", "0", false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
}
// only set cutoff value for mask material
if(material.alphaMode == fastgltf::AlphaMode::Mask) {
@@ -214,7 +225,7 @@ lv_result_t lv_gltf_view_shader_injest_discover_defines(lv_array_t * result, lv_
"HAS_THICKNESS_UV_TRANSFORM");
}
}
if(material.clearcoat) {
if(material.clearcoat && material.clearcoat->clearcoatFactor > 0.0f) {
if(add_define(result, "MATERIAL_CLEARCOAT", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}
@@ -232,7 +243,7 @@ lv_result_t lv_gltf_view_shader_injest_discover_defines(lv_array_t * result, lv_
return LV_RESULT_INVALID;
}
}
if(material.diffuseTransmission) {
if(material.diffuseTransmission && material.diffuseTransmission->diffuseTransmissionFactor > 0.0f) {
if(add_define(result, "MATERIAL_DIFFUSE_TRANSMISSION", NULL, false) == LV_RESULT_INVALID) {
return LV_RESULT_INVALID;
}