Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
1,283 changes: 1,283 additions & 0 deletions assets/example_meshes/gltf/SpecularTest/SpecularTest.gltf

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 15 additions & 2 deletions examples/render/950-pbr/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ int main(int argc, char** argv)
NORMAL_TENGENT_MIRROR_TEST,
COMPARE_AMBIENT_OCCLUSION,
DAMAGED_HELMET,
SPECULAR_TEST,
COUNT_EXAMPLES
};

Expand All @@ -29,9 +30,10 @@ int main(int argc, char** argv)
"/gltf/MetalRoughSpheres/MetalRoughSpheres.gltf",
"/gltf/NormalTangentMirrorTest/NormalTangentMirrorTest.gltf",
"/gltf/CompareAmbientOcclusion/CompareAmbientOcclusion.gltf",
"/gltf/DamagedHelmet/DamagedHelmet.gltf"};
"/gltf/DamagedHelmet/DamagedHelmet.gltf",
"/gltf/SpecularTest/SpecularTest.gltf"};

uint selectedExample = METAL_ROUGH_SPHERES;
uint selectedExample = SPECULAR_TEST;

enum PanoramasExamples {
COLOSSEUM_HDR,
Expand Down Expand Up @@ -73,6 +75,12 @@ int main(int argc, char** argv)
else if (type == EMISSIVE) {
typeName = "emissive";
}
else if (type == SPECULAR) {
typeName = "specular";
}
else if (type == SPECULAR_COLOR) {
typeName = "specularColor";
}

std::cout << " " << typeName << "Texture: ";
if (!texture.isNull()) {
Expand Down Expand Up @@ -105,11 +113,16 @@ int main(int argc, char** argv)
std::cout << " normalScale: " << mat.normalScale() << std::endl;
std::cout << " occlusionStrength: " << mat.occlusionStrength()
<< std::endl;
std::cout << " specularFactor: " << mat.specular() << std::endl;
std::cout << " specularColorFactor: " << mat.specularColor()
<< std::endl;
printTextureInfo(mat, BASE_COLOR);
printTextureInfo(mat, METALLIC_ROUGHNESS);
printTextureInfo(mat, NORMAL);
printTextureInfo(mat, OCCLUSION);
printTextureInfo(mat, EMISSIVE);
printTextureInfo(mat, SPECULAR);
printTextureInfo(mat, SPECULAR_COLOR);
std::cout << " ------------------------" << std::endl;
}
std::cout << "------------------------" << std::endl;
Expand Down
3 changes: 2 additions & 1 deletion tests/render/006-mesh-pbr-headless/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ TEST_CASE("PBR Rendering")
"DamagedHelmet/DamagedHelmet.gltf",
"MetalRoughSpheres/MetalRoughSpheres.gltf",
"CompareAmbientOcclusion/CompareAmbientOcclusion.gltf",
"NormalTangentMirrorTest/NormalTangentMirrorTest.gltf"};
"NormalTangentMirrorTest/NormalTangentMirrorTest.gltf",
"SpecularTest/SpecularTest.gltf"};
std::vector<float> angles = {0.0f, 3.14159265f / 4.0f};

for (const auto& meshName : meshes) {
Expand Down
43 changes: 43 additions & 0 deletions vclib/core/include/vclib/io/mesh/gltf/detail/load_mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ int loadGltfPrimitiveMaterial(
bool doubleSided;
int baseColorTextureId, metallicRoughnessTextureId, normalTextureId,
occlusionTextureId, emissiveTextureId;

double specular = 1.0;
Point3f specularColor = Point3f(1.0, 1.0, 1.0);
int specularTextureId = -1;
int specularColorTextureId = -1;

const tinygltf::Material& mat = model.materials[p.material];

std::string matName = mat.name;
Expand Down Expand Up @@ -108,6 +114,37 @@ int loadGltfPrimitiveMaterial(
// occlusionStrength
occlusionStrength = mat.occlusionTexture.strength;

// specular
if(mat.extensions.contains("KHR_materials_specular"))
{
const auto& specularExt = mat.extensions.at("KHR_materials_specular");

if(specularExt.Has("specularFactor"))
specular = specularExt
.Get("specularFactor")
.GetNumberAsDouble();

if(specularExt.Has("specularColorFactor"))
for(uint i = 0; i < 3; i++)
specularColor[i] = specularExt
.Get("specularColorFactor")
.Get(i)
.GetNumberAsDouble();

if(specularExt.Has("specularTexture"))
specularTextureId = specularExt
.Get("specularTexture")
.Get("index")
.GetNumberAsInt();

if(specularExt.Has("specularColorTexture"))
specularColorTextureId = specularExt
.Get("specularColorTexture")
.Get("index")
.GetNumberAsInt();

}
Comment thread
alemuntoni marked this conversation as resolved.

// function to load a texture in a material
auto loadTextureInMaterial = [&](Material& mat,
int textureId,
Expand Down Expand Up @@ -181,6 +218,8 @@ int loadGltfPrimitiveMaterial(
mat.doubleSided() = doubleSided;
mat.normalScale() = normalScale;
mat.occlusionStrength() = occlusionStrength;
mat.specular() = specular;
mat.specularColor() = specularColor;
loadTextureInMaterial(
mat, baseColorTextureId, Material::TextureType::BASE_COLOR);
loadTextureInMaterial(
Expand All @@ -193,6 +232,10 @@ int loadGltfPrimitiveMaterial(
mat, occlusionTextureId, Material::TextureType::OCCLUSION);
loadTextureInMaterial(
mat, emissiveTextureId, Material::TextureType::EMISSIVE);
loadTextureInMaterial(
mat, specularTextureId, Material::TextureType::SPECULAR);
loadTextureInMaterial(
mat, specularColorTextureId, Material::TextureType::SPECULAR_COLOR);
m.pushMaterial(mat);
idx = m.materialCount() - 1; // index of the added material
if constexpr (HasColor<MeshType>) {
Expand Down
43 changes: 41 additions & 2 deletions vclib/core/include/vclib/space/core/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class Material
OCCLUSION, ///< The ambient occlusion map (R channel). Stored in linear
///< color space.
EMISSIVE, ///< The emissive color texture. Stored in sRGB color space.
SPECULAR,
SPECULAR_COLOR,
COUNT ///< Utility value to get the number of texture types.
};

Expand All @@ -63,7 +65,9 @@ class Material
"metallicRoughnessTex",
"normalTex",
"occlusionTex",
"emissiveTex"};
"emissiveTex",
"specularTex",
"specularColorTex"};

private:
inline static const uint N_TEXTURE_TYPE =
Expand Down Expand Up @@ -93,6 +97,11 @@ class Material

bool mDoubleSided = false;

float mSpecular = 1.0f;

// needs to be HDR
Point3f mSpecularColor = Point3f(1.0, 1.0, 1.0);

public:
/**
* @brief Default constructor.
Expand Down Expand Up @@ -238,6 +247,30 @@ class Material
*/
float& occlusionStrength() { return mOcclusionStrength; }

/**
* @brief Gets the strength of the specular effect.
* @return The specular strength, in the range [0.0, 1.0].
*/
float specular() const { return mSpecular; }

/**
* @brief Gets a mutable reference to the specular strength.
* @return A reference to the specular strength.
*/
float& specular() { return mSpecular; }

/**
* @brief Gets the specular color of the material.
* @return A const reference to the specular color.
*/
const Point3f& specularColor() const { return mSpecularColor; }

/**
* @brief Gets a mutable reference to the specular color of the material.
* @return A reference to the specular color.
*/
Point3f& specularColor() { return mSpecularColor; }

/**
* @brief Gets the texture descriptor for the base color texture.
* @return A const reference to the base color texture descriptor.
Expand Down Expand Up @@ -318,6 +351,8 @@ class Material
vcl::serialize(os, mAlphaMode, mAlphaCutoff);
vcl::serialize(os, mNormalScale);
vcl::serialize(os, mOcclusionStrength);
vcl::serialize(os, mSpecular);
mSpecularColor.serialize(os);
vcl::serialize(os, mTextureDescriptors);
vcl::serialize(os, mDoubleSided);
}
Expand All @@ -335,6 +370,8 @@ class Material
vcl::deserialize(is, mAlphaMode, mAlphaCutoff);
vcl::deserialize(is, mNormalScale);
vcl::deserialize(is, mOcclusionStrength);
vcl::deserialize(is, mSpecular);
mSpecularColor.deserialize(is);
vcl::deserialize(is, mTextureDescriptors);
vcl::deserialize(is, mDoubleSided);
}
Expand All @@ -361,10 +398,12 @@ class Material
{
switch (type) {
case TextureType::BASE_COLOR:
case TextureType::EMISSIVE: return Image::ColorSpace::SRGB;
case TextureType::EMISSIVE:
case TextureType::SPECULAR_COLOR: return Image::ColorSpace::SRGB;
case TextureType::METALLIC_ROUGHNESS:
case TextureType::NORMAL:
case TextureType::OCCLUSION:
case TextureType::SPECULAR:
default: return Image::ColorSpace::LINEAR;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class DrawableEnvironment
Uniform("s_specular", bgfx::UniformType::Sampler);
// Sampler of mBrdfLuTexture
const Uniform mBrdfLutSamplerUniform =
Uniform("s_tex5", bgfx::UniformType::Sampler);
Uniform("s_brdfLut", bgfx::UniformType::Sampler);

// The number of mip levels in the specular cubemap,
// this value is needed by the shader to correctly sample the specular map.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class DrawableMeshUniforms
// sMeshData[1]: as uint, first chunk primitive id drawn
// sMeshData[2]: 8 texture stages with 4 bit each, to specify if texture is
// used (value != 15) and which stage is used for each texture (as uint):
// none|none|brdfLut|emissive|occlusion|normal|metallRough|baseColor
// brdfLut|specularColor|specular|emissive|occlusion|normal|metallRough|baseColor
inline static std::array<float, 4> sMeshData =
{0.0, 0.0, std::bit_cast<float>(0xFFFFFFFF), 0.0};

Expand All @@ -46,6 +46,8 @@ class DrawableMeshUniforms
NORMAL,
OCCLUSION,
EMISSIVE,
SPECULAR,
SPECULAR_COLOR,
BRDF_LUT,
COUNT
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ class MaterialUniforms
static inline std::array<float, 4> sEmissiveAlphaCutoffPack =
{0.0, 0.0, 0.0, 0.5};

// settings packed in a vec4
// .x : pbr settings
static inline std::array<float, 4> sSettings = {0.0, 0.0, 0.0, 0.0};

// specular color (RGB) and specular (A)
static inline std::array<float, 4> sSpecularPack = {1.0, 1.0, 1.0, 1.0};

static inline StaticUniform sBaseColorUniform {
"u_baseColorFactor",
bgfx::UniformType::Vec4};
Expand All @@ -50,6 +57,12 @@ class MaterialUniforms
static inline StaticUniform sEmissiveAlphaCutoffPackUniform {
"u_emissiveAlphaCutoffPack",
bgfx::UniformType::Vec4};
static inline StaticUniform sSettingsUniform {
"u_settings",
bgfx::UniformType::Vec4};
static inline StaticUniform sSpecularPackUniform {
"u_specularPack",
bgfx::UniformType::Vec4};

public:
MaterialUniforms() = delete;
Expand Down Expand Up @@ -79,13 +92,20 @@ class MaterialUniforms
sEmissiveAlphaCutoffPack[0] = m.emissiveColor().redF();
sEmissiveAlphaCutoffPack[1] = m.emissiveColor().greenF();
sEmissiveAlphaCutoffPack[2] = m.emissiveColor().blueF();

sSpecularPack[0] = m.specularColor()[0];
sSpecularPack[1] = m.specularColor()[1];
sSpecularPack[2] = m.specularColor()[2];
sSpecularPack[3] = m.specular();
}

static void bind()
{
sBaseColorUniform.bind(sBaseColor.data());
sFactorsPackUniform.bind(sFactorsPack.data());
sEmissiveAlphaCutoffPackUniform.bind(sEmissiveAlphaCutoffPack.data());
sSettingsUniform.bind(sSettings.data());
sSpecularPackUniform.bind(sSpecularPack.data());
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
uniform vec4 u_baseColorFactor;
uniform vec4 u_FactorsPack;
uniform vec4 u_emissiveAlphaCutoffPack;
uniform vec4 u_settings;
uniform vec4 u_specularPack;

#define u_occlusionStrength u_FactorsPack.r
#define u_roughnessFactor u_FactorsPack.g
Expand All @@ -22,4 +24,7 @@ uniform vec4 u_emissiveAlphaCutoffPack;

#define isAlphaModeMask() (u_alphaCutoff >= 0.0)

#define u_specularColorFactor u_specularPack.rgb
#define u_specularFactor u_specularPack.a

#endif // VCL_BGFX_DRAWABLE_DRAWABLE_MESH_MATERIAL_UNIFORMS_SH
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,8 @@ float pbrSpecular(
* the amount of light reflected when looking at a surface with a 0 degree angle (right above).
* @return The IBL Fresnel term.
*/
vec3 iblGgxFresnel(vec2 brdf, float NoV, float roughness, vec3 F0)
vec3 iblGgxFresnel(vec2 brdf, float NoV, float roughness, vec3 F0, float specularWeight)
{
float specularWeight = 1.0; // related to some extension, for now use a neutral value
// see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results
// Roughness dependent fresnel, from Fdez-Aguera
vec3 Fr = max(vec3_splat(1.0 - roughness), F0) - F0;
Expand Down Expand Up @@ -226,12 +225,15 @@ vec4 pbrColorLights(
float metallic,
float roughness,
vec3 emissive,
float specular,
vec3 specularColor,
float exposure,
int toneMapping)
{
vec3 finalColor = vec3_splat(0.0);
vec3 f0_dielectric = vec3_splat(0.04);
vec3 f0_dielectric = min(vec3_splat(0.04) * specularColor, vec3_splat(1.0));
vec3 f90 = vec3_splat(1.0);
vec3 f90_dielectric = vec3_splat(specular);

// view direction
vec3 V = normalize(cameraEyePos - vPos);
Expand All @@ -255,7 +257,7 @@ vec4 pbrColorLights(

// Fresnel factors for both dielectric and metallic surfaces
// 0.04 is an approximation of F0 averaged around many dielectric materials
vec3 dielectric_fresnel = F_Schlick(f0_dielectric, f90, abs(VoH));
vec3 dielectric_fresnel = F_Schlick(f0_dielectric * specular, f90_dielectric, abs(VoH));
// Metals have the surface color as base reflectivity since no light gets absorbed
vec3 metal_fresnel = F_Schlick(color.rgb, f90, abs(VoH));

Expand Down
Loading
Loading