Add support for KHR_materials_Specular (#7564)
Co-authored-by: Todd Zhang <toddzx@amazon.com> Co-authored-by: Romain Guy <romain.guy@gmail.com> Co-authored-by: Mathias Agopian <mathias@google.com>
This commit is contained in:
co-authored by
Todd Zhang
Romain Guy
Mathias Agopian
parent
d15c53e530
commit
e4a0bb8fa0
@@ -176,6 +176,7 @@ steps:
|
||||
- [x] KHR_materials_unlit
|
||||
- [x] KHR_materials_variants
|
||||
- [x] KHR_materials_volume
|
||||
- [x] KHR_materials_specular
|
||||
- [x] KHR_mesh_quantization
|
||||
- [x] KHR_texture_basisu
|
||||
- [x] KHR_texture_transform
|
||||
|
||||
@@ -203,7 +203,7 @@ enum class ReflectionMode : uint8_t {
|
||||
// can't really use std::underlying_type<AttributeIndex>::type because the driver takes a uint32_t
|
||||
using AttributeBitset = utils::bitset32;
|
||||
|
||||
static constexpr size_t MATERIAL_PROPERTIES_COUNT = 27;
|
||||
static constexpr size_t MATERIAL_PROPERTIES_COUNT = 29;
|
||||
enum class Property : uint8_t {
|
||||
BASE_COLOR, //!< float4, all shading models
|
||||
ROUGHNESS, //!< float, lit shading models only
|
||||
@@ -232,6 +232,8 @@ enum class Property : uint8_t {
|
||||
IOR, //!< float, material's index of refraction
|
||||
MICRO_THICKNESS, //!< float, thickness of the thin layer
|
||||
BENT_NORMAL, //!< float3, all shading models only, except unlit
|
||||
SPECULAR_FACTOR, //!< float, lit shading models only, except subsurface and cloth
|
||||
SPECULAR_COLOR_FACTOR, //!< float3, lit shading models only, except subsurface and cloth
|
||||
|
||||
// when adding new Properties, make sure to update MATERIAL_PROPERTIES_COUNT
|
||||
};
|
||||
|
||||
+28
-26
@@ -21,33 +21,35 @@
|
||||
namespace filamat {
|
||||
|
||||
std::unordered_map<std::string, Property> Enums::mStringToProperty = {
|
||||
{ "baseColor", Property::BASE_COLOR },
|
||||
{ "roughness", Property::ROUGHNESS },
|
||||
{ "metallic", Property::METALLIC },
|
||||
{ "reflectance", Property::REFLECTANCE },
|
||||
{ "ambientOcclusion", Property::AMBIENT_OCCLUSION },
|
||||
{ "clearCoat", Property::CLEAR_COAT },
|
||||
{ "clearCoatRoughness", Property::CLEAR_COAT_ROUGHNESS },
|
||||
{ "clearCoatNormal", Property::CLEAR_COAT_NORMAL },
|
||||
{ "anisotropy", Property::ANISOTROPY },
|
||||
{ "anisotropyDirection", Property::ANISOTROPY_DIRECTION },
|
||||
{ "thickness", Property::THICKNESS },
|
||||
{ "subsurfacePower", Property::SUBSURFACE_POWER },
|
||||
{ "subsurfaceColor", Property::SUBSURFACE_COLOR },
|
||||
{ "sheenColor", Property::SHEEN_COLOR },
|
||||
{ "sheenRoughness", Property::SHEEN_ROUGHNESS },
|
||||
{ "glossiness", Property::GLOSSINESS },
|
||||
{ "specularColor", Property::SPECULAR_COLOR },
|
||||
{ "emissive", Property::EMISSIVE },
|
||||
{ "normal", Property::NORMAL },
|
||||
{ "postLightingColor", Property::POST_LIGHTING_COLOR },
|
||||
{ "baseColor", Property::BASE_COLOR },
|
||||
{ "roughness", Property::ROUGHNESS },
|
||||
{ "metallic", Property::METALLIC },
|
||||
{ "reflectance", Property::REFLECTANCE },
|
||||
{ "ambientOcclusion", Property::AMBIENT_OCCLUSION },
|
||||
{ "clearCoat", Property::CLEAR_COAT },
|
||||
{ "clearCoatRoughness", Property::CLEAR_COAT_ROUGHNESS },
|
||||
{ "clearCoatNormal", Property::CLEAR_COAT_NORMAL },
|
||||
{ "anisotropy", Property::ANISOTROPY },
|
||||
{ "anisotropyDirection", Property::ANISOTROPY_DIRECTION },
|
||||
{ "thickness", Property::THICKNESS },
|
||||
{ "subsurfacePower", Property::SUBSURFACE_POWER },
|
||||
{ "subsurfaceColor", Property::SUBSURFACE_COLOR },
|
||||
{ "sheenColor", Property::SHEEN_COLOR },
|
||||
{ "sheenRoughness", Property::SHEEN_ROUGHNESS },
|
||||
{ "glossiness", Property::GLOSSINESS },
|
||||
{ "specularColor", Property::SPECULAR_COLOR },
|
||||
{ "emissive", Property::EMISSIVE },
|
||||
{ "normal", Property::NORMAL },
|
||||
{ "postLightingColor", Property::POST_LIGHTING_COLOR },
|
||||
{ "postLightingMixFactor", Property::POST_LIGHTING_MIX_FACTOR },
|
||||
{ "clipSpaceTransform", Property::CLIP_SPACE_TRANSFORM },
|
||||
{ "absorption", Property::ABSORPTION },
|
||||
{ "transmission", Property::TRANSMISSION },
|
||||
{ "ior", Property::IOR },
|
||||
{ "microThickness", Property::MICRO_THICKNESS },
|
||||
{ "bentNormal", Property::BENT_NORMAL },
|
||||
{ "clipSpaceTransform", Property::CLIP_SPACE_TRANSFORM },
|
||||
{ "absorption", Property::ABSORPTION },
|
||||
{ "transmission", Property::TRANSMISSION },
|
||||
{ "ior", Property::IOR },
|
||||
{ "microThickness", Property::MICRO_THICKNESS },
|
||||
{ "bentNormal", Property::BENT_NORMAL },
|
||||
{ "specularFactor", Property::SPECULAR_FACTOR },
|
||||
{ "specularColorFactor", Property::SPECULAR_COLOR_FACTOR }
|
||||
};
|
||||
|
||||
template <>
|
||||
|
||||
@@ -1192,6 +1192,8 @@ char const* CodeGenerator::getConstantName(MaterialBuilder::Property property) n
|
||||
case Property::IOR: return "IOR";
|
||||
case Property::MICRO_THICKNESS: return "MICRO_THICKNESS";
|
||||
case Property::BENT_NORMAL: return "BENT_NORMAL";
|
||||
case Property::SPECULAR_FACTOR: return "SPECULAR_FACTOR";
|
||||
case Property::SPECULAR_COLOR_FACTOR: return "SPECULAR_COLOR_FACTOR";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,9 @@ build_ubershader(volume_opaque volume lit opaque)
|
||||
build_ubershader(volume_fade volume lit fade)
|
||||
build_ubershader(volume_masked volume lit masked)
|
||||
build_ubershader(sheen sheen _ _)
|
||||
build_ubershader(specular_opaque specular lit opaque)
|
||||
build_ubershader(specular_fade specular lit fade)
|
||||
build_ubershader(specular_masked specular lit masked)
|
||||
|
||||
add_custom_target(uberz_file DEPENDS ${UBERZ_OUTPUT_PATH})
|
||||
set_target_properties(uberz_file PROPERTIES FOLDER Libs)
|
||||
|
||||
@@ -93,10 +93,17 @@ struct alignas(4) MaterialKey {
|
||||
bool hasSheen : 1;
|
||||
bool hasIOR : 1;
|
||||
bool hasVolume : 1;
|
||||
uint8_t padding : 5;
|
||||
bool hasSpecular : 1;
|
||||
bool hasSpecularTexture : 1;
|
||||
bool hasSpecularColorTexture : 1;
|
||||
bool padding : 2;
|
||||
// -- 32 bit boundary --
|
||||
uint8_t specularTextureUV;
|
||||
uint8_t specularColorTextureUV;
|
||||
uint16_t padding2;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MaterialKey) == 16, "MaterialKey has unexpected size.");
|
||||
static_assert(sizeof(MaterialKey) == 20, "MaterialKey has unexpected size.");
|
||||
|
||||
UTILS_WARNING_POP
|
||||
|
||||
|
||||
@@ -30,3 +30,8 @@ TransmissionTexture = unsupported
|
||||
# Volume Features
|
||||
Volume = unsupported
|
||||
VolumeThicknessTexture = unsupported
|
||||
|
||||
# Specular Features
|
||||
Specular = unsupported
|
||||
SpecularTexture = unsupported
|
||||
SpecularColorTexture = unsupported
|
||||
|
||||
@@ -55,7 +55,16 @@ material {
|
||||
{ type : mat3, name : sheenRoughnessUvMatrix, precision: high },
|
||||
|
||||
// Reflectance
|
||||
{ type : float, name : reflectance }
|
||||
{ type : float, name : reflectance },
|
||||
|
||||
// KHR_materials_specular
|
||||
{ type : float, name : specularStrength },
|
||||
{ type : float3, name : specularColorFactor },
|
||||
{ type : int, name : specularIndex },
|
||||
{ type : sampler2d, name : specularMap },
|
||||
{ type : mat3, name : specularUvMatrix, precision: high },
|
||||
{ type : int, name : specularColorIndex },
|
||||
{ type : mat3, name : specularColorUvMatrix, precision: high }
|
||||
|
||||
${CUSTOM_PARAMS}
|
||||
],
|
||||
@@ -136,6 +145,15 @@ fragment {
|
||||
material.emissive.rgb *= texture(materialParams_emissiveMap, uv).rgb;
|
||||
}
|
||||
|
||||
material.specularFactor = materialParams.specularStrength;
|
||||
material.specularColorFactor = materialParams.specularColorFactor;
|
||||
|
||||
if (materialParams.specularIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.specularIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.specularUvMatrix).xy;
|
||||
material.specularFactor *= texture(materialParams_specularMap, uv).a;
|
||||
}
|
||||
|
||||
${CUSTOM_FRAGMENT}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,3 +17,8 @@ TextureTransforms=optional
|
||||
Sheen=optional
|
||||
SheenColorTexture=optional
|
||||
SheenRoughnessTexture=optional
|
||||
|
||||
# KHR_material_specular Features
|
||||
Specular=optional
|
||||
SpecularTexture=optional
|
||||
SpecularColorTexture=unsupported
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
material {
|
||||
name : specular_ubershader,
|
||||
requires : [ uv0, uv1, color ],
|
||||
shadingModel : lit,
|
||||
blending : ${BLENDING},
|
||||
doubleSided : ${DOUBLESIDED},
|
||||
transparency : ${TRANSPARENCY},
|
||||
flipUV : false,
|
||||
specularAmbientOcclusion : simple,
|
||||
specularAntiAliasing : true,
|
||||
clearCoatIorChange : false,
|
||||
reflections: screenspace,
|
||||
parameters : [
|
||||
|
||||
// Base Color
|
||||
{ type : int, name : baseColorIndex },
|
||||
{ type : float4, name : baseColorFactor },
|
||||
{ type : sampler2d, name : baseColorMap },
|
||||
{ type : mat3, name : baseColorUvMatrix, precision: high },
|
||||
|
||||
// Metallic-Roughness Map
|
||||
{ type : int, name : metallicRoughnessIndex },
|
||||
{ type : float, name : metallicFactor },
|
||||
{ type : float, name : roughnessFactor },
|
||||
{ type : sampler2d, name : metallicRoughnessMap },
|
||||
{ type : mat3, name : metallicRoughnessUvMatrix, precision: high },
|
||||
|
||||
// Normal Map
|
||||
{ type : int, name : normalIndex },
|
||||
{ type : float, name : normalScale },
|
||||
{ type : sampler2d, name : normalMap },
|
||||
{ type : mat3, name : normalUvMatrix, precision: high },
|
||||
|
||||
// Ambient Occlusion
|
||||
{ type : int, name : aoIndex },
|
||||
{ type : float, name : aoStrength },
|
||||
{ type : sampler2d, name : occlusionMap },
|
||||
{ type : mat3, name : occlusionUvMatrix, precision: high },
|
||||
|
||||
// Emissive Map
|
||||
{ type : int, name : emissiveIndex },
|
||||
{ type : float3, name : emissiveFactor },
|
||||
{ type : float, name : emissiveStrength },
|
||||
{ type : sampler2d, name : emissiveMap },
|
||||
{ type : mat3, name : emissiveUvMatrix, precision: high },
|
||||
|
||||
// Clear coat, we drop texture support for clear coat due to 8 texture limits.
|
||||
{ type : float, name : clearCoatFactor },
|
||||
{ type : float, name : clearCoatRoughnessFactor },
|
||||
{ type : int, name : clearCoatIndex },
|
||||
{ type : sampler2d, name : clearCoatMap },
|
||||
{ type : mat3, name : clearCoatUvMatrix, precision: high },
|
||||
{ type : int, name : clearCoatRoughnessIndex },
|
||||
{ type : mat3, name : clearCoatRoughnessUvMatrix, precision: high },
|
||||
{ type : int, name : clearCoatNormalIndex },
|
||||
{ type : mat3, name : clearCoatNormalUvMatrix, precision: high },
|
||||
{ type : float, name : clearCoatNormalScale },
|
||||
|
||||
// KHR_materials_specular
|
||||
{ type : float, name : specularStrength },
|
||||
{ type : float3, name : specularColorFactor },
|
||||
{ type : int, name : specularIndex },
|
||||
{ type : sampler2d, name : specularMap },
|
||||
{ type : mat3, name : specularUvMatrix, precision: high },
|
||||
{ type : int, name : specularColorIndex },
|
||||
{ type : sampler2d, name : specularColorMap },
|
||||
{ type : mat3, name : specularColorUvMatrix, precision: high },
|
||||
|
||||
// IOR
|
||||
{ type : float, name : ior }
|
||||
|
||||
${CUSTOM_PARAMS}
|
||||
],
|
||||
}
|
||||
|
||||
vertex {
|
||||
void materialVertex(inout MaterialVertexInputs material) {
|
||||
${CUSTOM_VERTEX}
|
||||
}
|
||||
}
|
||||
|
||||
fragment {
|
||||
void material(inout MaterialInputs material) {
|
||||
highp float2 uvs[2];
|
||||
uvs[0] = getUV0();
|
||||
uvs[1] = getUV1();
|
||||
|
||||
if (materialParams.normalIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.normalIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.normalUvMatrix).xy;
|
||||
material.normal = texture(materialParams_normalMap, uv).xyz * 2.0 - 1.0;
|
||||
material.normal.xy *= materialParams.normalScale;
|
||||
}
|
||||
|
||||
prepareMaterial(material);
|
||||
material.baseColor = materialParams.baseColorFactor;
|
||||
|
||||
if (materialParams.baseColorIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.baseColorIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.baseColorUvMatrix).xy;
|
||||
material.baseColor *= texture(materialParams_baseColorMap, uv);
|
||||
}
|
||||
|
||||
#if defined(BLEND_MODE_TRANSPARENT)
|
||||
material.baseColor.rgb *= material.baseColor.a;
|
||||
#endif
|
||||
|
||||
material.baseColor *= getColor();
|
||||
|
||||
material.roughness = materialParams.roughnessFactor;
|
||||
material.metallic = materialParams.metallicFactor;
|
||||
material.ior = materialParams.ior;
|
||||
|
||||
material.emissive = vec4(materialParams.emissiveStrength *
|
||||
materialParams.emissiveFactor.rgb, 0.0);
|
||||
|
||||
// KHR_materials_clearcoat forbids clear coat from
|
||||
// being applied in the specular/glossiness model
|
||||
material.clearCoat = materialParams.clearCoatFactor;
|
||||
material.clearCoatRoughness = materialParams.clearCoatRoughnessFactor;
|
||||
|
||||
if (materialParams.clearCoatIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.clearCoatIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.clearCoatUvMatrix).xy;
|
||||
material.clearCoat *= texture(materialParams_clearCoatMap, uv).r;
|
||||
}
|
||||
|
||||
material.specularFactor = materialParams.specularStrength;
|
||||
material.specularColorFactor = materialParams.specularColorFactor;
|
||||
|
||||
if (materialParams.specularIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.specularIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.specularUvMatrix).xy;
|
||||
material.specularFactor *= texture(materialParams_specularMap, uv).a;
|
||||
}
|
||||
|
||||
if (materialParams.specularColorIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.specularColorIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.specularColorUvMatrix).xy;
|
||||
vec4 sc = texture(materialParams_specularColorMap, uv);
|
||||
material.specularColorFactor.r *= sc.r;
|
||||
material.specularColorFactor.g *= sc.g;
|
||||
material.specularColorFactor.b *= sc.b;
|
||||
}
|
||||
|
||||
if (materialParams.metallicRoughnessIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.metallicRoughnessIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.metallicRoughnessUvMatrix).xy;
|
||||
vec4 mr = texture(materialParams_metallicRoughnessMap, uv);
|
||||
material.roughness *= mr.g;
|
||||
material.metallic *= mr.b;
|
||||
}
|
||||
|
||||
if (materialParams.aoIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.aoIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.occlusionUvMatrix).xy;
|
||||
float occlusion = texture(materialParams_occlusionMap, uv).r;
|
||||
material.ambientOcclusion = 1.0 + materialParams.aoStrength * (occlusion - 1.0);
|
||||
}
|
||||
if (materialParams.emissiveIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.emissiveIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.emissiveUvMatrix).xy;
|
||||
material.emissive.rgb *= texture(materialParams_emissiveMap, uv).rgb;
|
||||
}
|
||||
|
||||
${CUSTOM_FRAGMENT}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
ShadingModel=lit
|
||||
|
||||
# Required Aspects
|
||||
BlendingMode = ${BLENDING}
|
||||
|
||||
VertexColors = optional
|
||||
BaseColorTexture = optional
|
||||
NormalTexture = optional
|
||||
OcclusionTexture = optional
|
||||
EmissiveTexture = optional
|
||||
MetallicRoughnessTexture = optional
|
||||
TextureTransforms = optional
|
||||
|
||||
# KHR_materials_specular Features
|
||||
Specular = optional
|
||||
SpecularTexture = optional
|
||||
SpecularColorTexture = optional
|
||||
|
||||
# ClearCoat Features
|
||||
ClearCoat = optional
|
||||
ClearCoatTexture = optional
|
||||
|
||||
# Sheen Features
|
||||
Sheen = unsupported
|
||||
SheenColorTexture = unsupported
|
||||
SheenRoughnessTexture = unsupported
|
||||
|
||||
# Transmission and IOR Features
|
||||
Transmission = unsupported
|
||||
Ior = optional
|
||||
TransmissionTexture = unsupported
|
||||
|
||||
# Volume Features
|
||||
Volume = unsupported
|
||||
VolumeThicknessTexture = unsupported
|
||||
@@ -52,7 +52,18 @@ material {
|
||||
{ type : mat3, name : transmissionUvMatrix, precision: high },
|
||||
|
||||
// IOR
|
||||
{ type : float, name : ior }
|
||||
{ type : float, name : ior },
|
||||
|
||||
// KHR_materials_specular
|
||||
{ type : float, name : specularStrength },
|
||||
{ type : float3, name : specularColorFactor },
|
||||
{ type : int, name : specularIndex },
|
||||
{ type : sampler2d, name : specularMap },
|
||||
{ type : mat3, name : specularUvMatrix, precision: high },
|
||||
{ type : int, name : specularColorIndex },
|
||||
{ type : sampler2d, name : specularColorMap },
|
||||
{ type : mat3, name : specularColorUvMatrix, precision: high }
|
||||
|
||||
|
||||
${CUSTOM_PARAMS}
|
||||
],
|
||||
@@ -126,6 +137,24 @@ fragment {
|
||||
material.emissive.rgb *= texture(materialParams_emissiveMap, uv).rgb;
|
||||
}
|
||||
|
||||
material.specularFactor = materialParams.specularStrength;
|
||||
material.specularColorFactor = materialParams.specularColorFactor;
|
||||
|
||||
if (materialParams.specularIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.specularIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.specularUvMatrix).xy;
|
||||
material.specularFactor *= texture(materialParams_specularMap, uv).a;
|
||||
}
|
||||
|
||||
if (materialParams.specularColorIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.specularColorIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.specularColorUvMatrix).xy;
|
||||
vec4 sc = texture(materialParams_specularColorMap, uv);
|
||||
material.specularColorFactor.r *= sc.r;
|
||||
material.specularColorFactor.g *= sc.g;
|
||||
material.specularColorFactor.b *= sc.b;
|
||||
}
|
||||
|
||||
${CUSTOM_FRAGMENT}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ EmissiveTexture=optional
|
||||
MetallicRoughnessTexture=optional
|
||||
TextureTransforms=optional
|
||||
|
||||
# KHR_materials_specular Features
|
||||
Specular=optional
|
||||
SpecularTexture=optional
|
||||
SpecularColorTexture=optional
|
||||
|
||||
Transmission=optional
|
||||
Ior=optional
|
||||
TransmissionTexture=optional
|
||||
|
||||
@@ -58,6 +58,15 @@ material {
|
||||
{ type : sampler2d, name : volumeThicknessMap },
|
||||
{ type : mat3, name : volumeThicknessUvMatrix, precision: high },
|
||||
|
||||
// KHR_materials_specular
|
||||
{ type : float, name : specularStrength },
|
||||
{ type : float3, name : specularColorFactor },
|
||||
{ type : int, name : specularIndex },
|
||||
{ type : sampler2d, name : specularMap },
|
||||
{ type : mat3, name : specularUvMatrix, precision: high },
|
||||
{ type : int, name : specularColorIndex },
|
||||
{ type : mat3, name : specularColorUvMatrix, precision: high },
|
||||
|
||||
// IOR
|
||||
{ type : float, name : ior }
|
||||
|
||||
@@ -142,6 +151,15 @@ fragment {
|
||||
material.emissive.rgb *= texture(materialParams_emissiveMap, uv).rgb;
|
||||
}
|
||||
|
||||
material.specularFactor = materialParams.specularStrength;
|
||||
material.specularColorFactor = materialParams.specularColorFactor;
|
||||
|
||||
if (materialParams.specularIndex > -1) {
|
||||
highp float2 uv = uvs[materialParams.specularIndex];
|
||||
uv = (vec3(uv, 1.0) * materialParams.specularUvMatrix).xy;
|
||||
material.specularFactor *= texture(materialParams_specularMap, uv).a;
|
||||
}
|
||||
|
||||
${CUSTOM_FRAGMENT}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,3 +26,8 @@ TransmissionTexture=optional
|
||||
# Volume Features
|
||||
Volume=optional
|
||||
VolumeThicknessTexture=optional
|
||||
|
||||
# KHR_materials_specular Features
|
||||
Specular=optional
|
||||
SpecularTexture=optional
|
||||
SpecularColorTexture=unsupported
|
||||
|
||||
@@ -1222,6 +1222,7 @@ MaterialKey FAssetLoader::getMaterialKey(const cgltf_data* srcAsset,
|
||||
auto trConfig = inputMat->transmission;
|
||||
auto shConfig = inputMat->sheen;
|
||||
auto vlConfig = inputMat->volume;
|
||||
auto spConfig = inputMat->specular;
|
||||
*baseColorTexture = mrConfig.base_color_texture;
|
||||
*metallicRoughnessTexture = mrConfig.metallic_roughness_texture;
|
||||
|
||||
@@ -1238,7 +1239,9 @@ MaterialKey FAssetLoader::getMaterialKey(const cgltf_data* srcAsset,
|
||||
ccConfig.clearcoat_normal_texture.has_transform ||
|
||||
shConfig.sheen_color_texture.has_transform ||
|
||||
shConfig.sheen_roughness_texture.has_transform ||
|
||||
trConfig.transmission_texture.has_transform;
|
||||
trConfig.transmission_texture.has_transform ||
|
||||
spConfig.specular_color_texture.has_transform ||
|
||||
spConfig.specular_texture.has_transform;
|
||||
|
||||
MaterialKey matkey {
|
||||
.doubleSided = !!inputMat->double_sided,
|
||||
@@ -1273,6 +1276,11 @@ MaterialKey FAssetLoader::getMaterialKey(const cgltf_data* srcAsset,
|
||||
.hasSheen = !!inputMat->has_sheen,
|
||||
.hasIOR = !!inputMat->has_ior,
|
||||
.hasVolume = !!inputMat->has_volume,
|
||||
.hasSpecular = !!inputMat->has_specular,
|
||||
.hasSpecularTexture = spConfig.specular_texture.texture != nullptr,
|
||||
.hasSpecularColorTexture = spConfig.specular_color_texture.texture != nullptr,
|
||||
.specularTextureUV = (uint8_t) spConfig.specular_texture.texcoord,
|
||||
.specularColorTextureUV = (uint8_t) spConfig.specular_color_texture.texcoord,
|
||||
};
|
||||
|
||||
if (inputMat->has_pbr_specular_glossiness) {
|
||||
@@ -1361,6 +1369,7 @@ MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_material* inp
|
||||
auto trConfig = inputMat->transmission;
|
||||
auto shConfig = inputMat->sheen;
|
||||
auto vlConfig = inputMat->volume;
|
||||
auto spConfig = inputMat->specular;
|
||||
|
||||
// Check the material blending mode, not the cgltf blending mode, because the provider
|
||||
// might have selected an alternative blend mode (e.g. to support transmission).
|
||||
@@ -1560,6 +1569,30 @@ MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_material* inp
|
||||
inputMat->emissive_strength.emissive_strength : 1.0f);
|
||||
}
|
||||
|
||||
if (matkey.hasSpecular) {
|
||||
const float* s = spConfig.specular_color_factor;
|
||||
mi->setParameter("specularColorFactor", float3{s[0], s[1], s[2]});
|
||||
mi->setParameter("specularStrength", spConfig.specular_factor);
|
||||
|
||||
if (matkey.hasSpecularColorTexture) {
|
||||
fAsset->addTextureBinding(mi, "specularColorMap", spConfig.specular_color_texture.texture, sRGB);
|
||||
if (matkey.hasTextureTransforms) {
|
||||
const cgltf_texture_transform uvt = spConfig.specular_color_texture.transform;
|
||||
auto uvmat = matrixFromUvTransform(uvt.offset, uvt.rotation, uvt.scale);
|
||||
mi->setParameter("specularColorUvMatrix", uvmat);
|
||||
}
|
||||
}
|
||||
if (matkey.hasSpecularTexture) {
|
||||
bool sameTexture = spConfig.specular_color_texture.texture == spConfig.specular_texture.texture;
|
||||
fAsset->addTextureBinding(mi, "specularMap", spConfig.specular_texture.texture, sameTexture ? sRGB : LINEAR);
|
||||
if (matkey.hasTextureTransforms) {
|
||||
const cgltf_texture_transform uvt = spConfig.specular_texture.transform;
|
||||
auto uvmat = matrixFromUvTransform(uvt.offset, uvt.rotation, uvt.scale);
|
||||
mi->setParameter("specularUvMatrix", uvmat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*cacheEntry = { mi, *uvmap };
|
||||
return mi;
|
||||
}
|
||||
|
||||
@@ -308,6 +308,35 @@ std::string shaderFromKey(const MaterialKey& config) {
|
||||
material.ior = materialParams.ior;
|
||||
)SHADER";
|
||||
}
|
||||
|
||||
if (config.hasSpecular) {
|
||||
shader += R"SHADER(
|
||||
material.specularFactor = materialParams.specularStrength;
|
||||
material.specularColorFactor = materialParams.specularColorFactor;
|
||||
)SHADER";
|
||||
|
||||
if (config.hasSpecularTexture) {
|
||||
shader += "highp float2 specularUV = ${specular};\n";
|
||||
if (config.hasTextureTransforms) {
|
||||
shader += "specularUV = (vec3(specularUV, 1.0) * "
|
||||
"materialParams.specularUvMatrix).xy;\n";
|
||||
}
|
||||
shader += R"SHADER(
|
||||
material.specularFactor *= texture(materialParams_specularMap, specularUV).a;
|
||||
)SHADER";
|
||||
}
|
||||
|
||||
if (config.hasSpecularColorTexture) {
|
||||
shader += "highp float2 specularColorUV = ${specularColor};\n";
|
||||
if (config.hasTextureTransforms) {
|
||||
shader += "specularColorUV = (vec3(specularColorUV, 1.0) * "
|
||||
"materialParams.specularColorUvMatrix).xy;\n";
|
||||
}
|
||||
shader += R"SHADER(
|
||||
material.specularColorFactor *= texture(materialParams_specularColorMap, specularColorUV).rgb;
|
||||
)SHADER";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shader += "}\n";
|
||||
@@ -463,6 +492,26 @@ Material* createMaterial(Engine* engine, const MaterialKey& config, const UvMap&
|
||||
}
|
||||
}
|
||||
|
||||
// SPECULAR
|
||||
if (config.hasSpecular) {
|
||||
builder.parameter("specularStrength", MaterialBuilder::UniformType::FLOAT);
|
||||
builder.parameter("specularColorFactor", MaterialBuilder::UniformType::FLOAT3);
|
||||
if (config.hasSpecularTexture) {
|
||||
builder.parameter("specularMap", MaterialBuilder::SamplerType::SAMPLER_2D);
|
||||
if (config.hasTextureTransforms) {
|
||||
builder.parameter("specularUvMatrix", MaterialBuilder::UniformType::MAT3,
|
||||
MaterialBuilder::ParameterPrecision::HIGH);
|
||||
}
|
||||
}
|
||||
if (config.hasSpecularColorTexture) {
|
||||
builder.parameter("specularColorMap", MaterialBuilder::SamplerType::SAMPLER_2D);
|
||||
if (config.hasTextureTransforms) {
|
||||
builder.parameter("specularColorUvMatrix", MaterialBuilder::UniformType::MAT3,
|
||||
MaterialBuilder::ParameterPrecision::HIGH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BLENDING
|
||||
switch (config.alphaMode) {
|
||||
case AlphaMode::OPAQUE:
|
||||
|
||||
@@ -143,6 +143,21 @@ void constrainMaterial(MaterialKey* key, UvMap* uvmap) {
|
||||
retval[key->volumeThicknessUV] = (UvSet) index++;
|
||||
}
|
||||
}
|
||||
if (key->hasSpecularTexture && retval[key->specularTextureUV] == UNUSED) {
|
||||
if (index > MAX_INDEX) {
|
||||
key->hasSpecularTexture = false;
|
||||
} else {
|
||||
retval[key->specularTextureUV] = (UvSet) index++;
|
||||
}
|
||||
}
|
||||
if (key->hasSpecularColorTexture && retval[key->specularColorTextureUV] == UNUSED) {
|
||||
if (index > MAX_INDEX) {
|
||||
key->hasSpecularColorTexture = false;
|
||||
} else {
|
||||
retval[key->specularColorTextureUV] = (UvSet) index++;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: KHR_materials_clearcoat does not provide separate UVs, we'll assume UV0
|
||||
*uvmap = retval;
|
||||
}
|
||||
@@ -167,6 +182,8 @@ void processShaderString(std::string* shader, const UvMap& uvmap, const Material
|
||||
const auto& sheenColorUV = uvstrings[uvmap[config.sheenColorUV]];
|
||||
const auto& sheenRoughnessUV = uvstrings[uvmap[config.sheenRoughnessUV]];
|
||||
const auto& volumeThicknessUV = uvstrings[uvmap[config.volumeThicknessUV]];
|
||||
const auto& specularUV = uvstrings[uvmap[config.specularTextureUV]];
|
||||
const auto& specularColorUV = uvstrings[uvmap[config.specularColorTextureUV]];
|
||||
|
||||
replaceAll("${normal}", normalUV);
|
||||
replaceAll("${color}", baseColorUV);
|
||||
@@ -180,6 +197,8 @@ void processShaderString(std::string* shader, const UvMap& uvmap, const Material
|
||||
replaceAll("${sheenColor}", sheenColorUV);
|
||||
replaceAll("${sheenRoughness}", sheenRoughnessUV);
|
||||
replaceAll("${volumeThickness}", volumeThicknessUV);
|
||||
replaceAll("${specular}", specularUV);
|
||||
replaceAll("${specularColor}", specularColorUV);
|
||||
}
|
||||
|
||||
} // namespace filament::gltfio
|
||||
|
||||
@@ -63,6 +63,42 @@ static void prepareConfig(MaterialKey* config, const char* label) {
|
||||
config->hasSheen = false;
|
||||
config->hasIOR = false;
|
||||
}
|
||||
|
||||
if (config->useSpecularGlossiness && config->hasSpecular) {
|
||||
slog.w << "SpecularGlossiness and specular are not supported together in ubershader mode,"
|
||||
" removing specularGlossiness (" << label << ")." << io::endl;
|
||||
|
||||
config->useSpecularGlossiness = false;
|
||||
}
|
||||
|
||||
if (config->unlit && config->hasSpecular) {
|
||||
slog.w << "Unlit and specular are not supported together in ubershader mode,"
|
||||
" removing unlit (" << label << ")." << io::endl;
|
||||
|
||||
config->unlit = false;
|
||||
}
|
||||
|
||||
// Also due to sampler overload, clearcoat with specular, we can only support with specular map.
|
||||
if ((config->hasClearCoatNormalTexture || config->hasClearCoatRoughnessTexture) && config->hasSpecular) {
|
||||
slog.w << "Specular can only work with clearcoat that does not use clear coat normal or clear coat roughness map,"
|
||||
" removing clear coat normal and roughness (" << label << ")." << io::endl;
|
||||
config->hasClearCoatNormalTexture = false;
|
||||
config->hasClearCoatRoughnessTexture = false;
|
||||
}
|
||||
|
||||
// Also due to sampler overload, sheen with specular, we can only support without specular color texture.
|
||||
if (config->hasSpecularColorTexture && config->hasSheen) {
|
||||
slog.w << "Sheen can only work with specular that does not use specular color map,"
|
||||
" removing specular color (" << label << ")." << io::endl;
|
||||
config->hasSpecularColorTexture = false;
|
||||
}
|
||||
|
||||
// Also due to sampler overload, volume with specular, we can only support without specular color texture.
|
||||
if (config->hasSpecularColorTexture && config->hasVolume) {
|
||||
slog.w << "Volume can only work with specular that does not use specular color map,"
|
||||
"removing specular color (" << label << ")." << io::endl;
|
||||
config->hasSpecularColorTexture = false;
|
||||
}
|
||||
}
|
||||
|
||||
class UbershaderProvider : public MaterialProvider {
|
||||
@@ -155,6 +191,9 @@ Material* UbershaderProvider::getMaterial(const MaterialKey& config) const {
|
||||
requirements.features["SheenColorTexture"] = config.hasSheenColorTexture;
|
||||
requirements.features["SheenRoughnessTexture"] = config.hasSheenRoughnessTexture;
|
||||
requirements.features["VolumeThicknessTexture"] = config.hasVolumeThicknessTexture;
|
||||
requirements.features["Specular"] = config.hasSpecular;
|
||||
requirements.features["SpecularTexture"] = config.hasSpecularTexture;
|
||||
requirements.features["SpecularColorTexture"] = config.hasSpecularColorTexture;
|
||||
|
||||
if (Material* mat = mMaterials.getMaterial(requirements); mat != nullptr) {
|
||||
return mat;
|
||||
@@ -250,6 +289,14 @@ MaterialInstance* UbershaderProvider::createMaterialInstance(MaterialKey* config
|
||||
mi->setParameter("transmissionIndex",
|
||||
getUvIndex(config->transmissionUV, config->hasTransmissionTexture));
|
||||
}
|
||||
if (config->hasSpecular) {
|
||||
mi->setParameter("specularUvMatrix", identity);
|
||||
mi->setParameter("specularIndex",
|
||||
getUvIndex(config->specularTextureUV, config->hasSpecularTexture));
|
||||
mi->setParameter("specularColorUvMatrix", identity);
|
||||
mi->setParameter("specularColorIndex",
|
||||
getUvIndex(config->specularColorTextureUV, config->hasSpecularColorTexture));
|
||||
}
|
||||
}
|
||||
|
||||
TextureSampler sampler;
|
||||
@@ -300,6 +347,14 @@ MaterialInstance* UbershaderProvider::createMaterialInstance(MaterialKey* config
|
||||
mi->setParameter("reflectance", 0.5f);
|
||||
}
|
||||
|
||||
if (needsTexture("SpecularTexture")) {
|
||||
mi->setParameter("specularMap", mDummyTexture, sampler);
|
||||
}
|
||||
|
||||
if (needsTexture("SpecularColorTexture")) {
|
||||
mi->setParameter("specularColorMap", mDummyTexture, sampler);
|
||||
}
|
||||
|
||||
return mi;
|
||||
}
|
||||
|
||||
|
||||
@@ -181,6 +181,16 @@ vec3 fresnel(const vec3 f0, float LoH) {
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 fresnel(const vec3 f0, const float f90, float LoH) {
|
||||
#if BRDF_SPECULAR_F == SPECULAR_F_SCHLICK
|
||||
#if FILAMENT_QUALITY == FILAMENT_QUALITY_LOW
|
||||
return F_Schlick(f0, LoH); // f90 = 1.0
|
||||
#else
|
||||
return F_Schlick(f0, f90, LoH);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
float distributionAnisotropic(float at, float ab, float ToH, float BoH, float NoH) {
|
||||
#if BRDF_ANISOTROPIC_D == SPECULAR_D_GGX_ANISOTROPIC
|
||||
return D_GGX_Anisotropic(at, ab, ToH, BoH, NoH);
|
||||
|
||||
@@ -18,6 +18,11 @@ struct PixelParams {
|
||||
float perceptualRoughness;
|
||||
float perceptualRoughnessUnclamped;
|
||||
vec3 f0;
|
||||
#if defined(MATERIAL_HAS_SPECULAR_COLOR_FACTOR) || defined(MATERIAL_HAS_SPECULAR_FACTOR)
|
||||
float f90;
|
||||
float specular;
|
||||
vec3 specularColor;
|
||||
#endif
|
||||
float roughness;
|
||||
vec3 dfg;
|
||||
vec3 energyCompensation;
|
||||
|
||||
@@ -136,9 +136,13 @@ vec3 getSpecularDominantDirection(const vec3 n, const vec3 r, float roughness) {
|
||||
vec3 specularDFG(const PixelParams pixel) {
|
||||
#if defined(SHADING_MODEL_CLOTH)
|
||||
return pixel.f0 * pixel.dfg.z;
|
||||
#else
|
||||
#if defined(MATERIAL_HAS_SPECULAR_COLOR_FACTOR) || defined(MATERIAL_HAS_SPECULAR_FACTOR)
|
||||
return mix(pixel.dfg.xxx, pixel.dfg.yyy, pixel.f0) * pixel.specular;
|
||||
#else
|
||||
return mix(pixel.dfg.xxx, pixel.dfg.yyy, pixel.f0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 getReflectedVector(const PixelParams pixel, const vec3 n) {
|
||||
@@ -663,7 +667,6 @@ void evaluateIBL(const MaterialInputs material, const PixelParams pixel, inout v
|
||||
|
||||
// Combine all terms
|
||||
// Note: iblLuminance is already premultiplied by the exposure
|
||||
|
||||
color.rgb += Fr + Fd;
|
||||
#if defined(MATERIAL_HAS_REFRACTION)
|
||||
color.rgb += Ft;
|
||||
|
||||
@@ -89,6 +89,15 @@ struct MaterialInputs {
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MATERIAL_HAS_SPECULAR_FACTOR)
|
||||
float specularFactor;
|
||||
#endif
|
||||
|
||||
#if defined(MATERIAL_HAS_SPECULAR_COLOR_FACTOR)
|
||||
vec3 specularColorFactor;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
void initMaterial(out MaterialInputs material) {
|
||||
@@ -177,6 +186,15 @@ void initMaterial(out MaterialInputs material) {
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MATERIAL_HAS_SPECULAR_FACTOR)
|
||||
material.specularFactor = 1.0;
|
||||
#endif
|
||||
|
||||
#if defined(MATERIAL_HAS_SPECULAR_COLOR_FACTOR)
|
||||
material.specularColorFactor = vec3(1.0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if defined(MATERIAL_HAS_CUSTOM_SURFACE_SHADING)
|
||||
|
||||
@@ -75,7 +75,21 @@ void getCommonPixelParams(const MaterialInputs material, inout PixelParams pixel
|
||||
// Assumes an interface from air to an IOR of 1.5 for dielectrics
|
||||
float reflectance = computeDielectricF0(material.reflectance);
|
||||
#endif
|
||||
#if !defined(MATERIAL_HAS_SPECULAR_FACTOR) && !defined(MATERIAL_HAS_SPECULAR_COLOR_FACTOR)
|
||||
pixel.f0 = computeF0(baseColor, material.metallic, reflectance);
|
||||
#else
|
||||
vec3 dielectricSpecularF0 = vec3(0.0);
|
||||
float dielectricSpecularF90 = 0.0;
|
||||
#if defined(MATERIAL_HAS_SPECULAR_COLOR_FACTOR)
|
||||
dielectricSpecularF0 = min(reflectance * material.specularColorFactor, vec3(1.0));
|
||||
#endif
|
||||
#if defined(MATERIAL_HAS_SPECULAR_FACTOR)
|
||||
dielectricSpecularF0 *= material.specularFactor;
|
||||
dielectricSpecularF90 = material.specularFactor;
|
||||
#endif
|
||||
pixel.f0 = baseColor.rgb * material.metallic + dielectricSpecularF0 * (1.0 - material.metallic);
|
||||
pixel.f90 = material.metallic + dielectricSpecularF90 * (1.0 - material.metallic);
|
||||
#endif
|
||||
#else
|
||||
pixel.diffuseColor = baseColor.rgb;
|
||||
pixel.f0 = material.sheenColor;
|
||||
@@ -123,6 +137,16 @@ void getCommonPixelParams(const MaterialInputs material, inout PixelParams pixel
|
||||
#endif
|
||||
}
|
||||
|
||||
void getSpecularPixelParams(const MaterialInputs material, inout PixelParams pixel) {
|
||||
#if defined(MATERIAL_HAS_SPECULAR_FACTOR)
|
||||
pixel.specular = material.specularFactor;
|
||||
#endif
|
||||
|
||||
#if defined(MATERIAL_HAS_SPECULAR_COLOR_FACTOR)
|
||||
pixel.specularColor = material.specularColorFactor;
|
||||
#endif
|
||||
}
|
||||
|
||||
void getSheenPixelParams(const MaterialInputs material, inout PixelParams pixel) {
|
||||
#if defined(MATERIAL_HAS_SHEEN_COLOR) && !defined(SHADING_MODEL_CLOTH) && !defined(SHADING_MODEL_SUBSURFACE)
|
||||
pixel.sheenColor = material.sheenColor;
|
||||
@@ -232,6 +256,7 @@ void getEnergyCompensationPixelParams(inout PixelParams pixel) {
|
||||
* testing fails.
|
||||
*/
|
||||
void getPixelParams(const MaterialInputs material, out PixelParams pixel) {
|
||||
getSpecularPixelParams(material, pixel);
|
||||
getCommonPixelParams(material, pixel);
|
||||
getSheenPixelParams(material, pixel);
|
||||
getClearCoatPixelParams(material, pixel);
|
||||
|
||||
@@ -63,8 +63,11 @@ vec3 isotropicLobe(const PixelParams pixel, const Light light, const vec3 h,
|
||||
|
||||
float D = distribution(pixel.roughness, NoH, h);
|
||||
float V = visibility(pixel.roughness, NoV, NoL);
|
||||
#if defined(MATERIAL_HAS_SPECULAR_COLOR_FACTOR) || defined(MATERIAL_HAS_SPECULAR_FACTOR)
|
||||
vec3 F = fresnel(pixel.f0, pixel.f90, LoH);
|
||||
#else
|
||||
vec3 F = fresnel(pixel.f0, LoH);
|
||||
|
||||
#endif
|
||||
return (D * V) * F;
|
||||
}
|
||||
|
||||
@@ -144,7 +147,6 @@ vec3 surfaceShading(const PixelParams pixel, const Light light, float occlusion)
|
||||
color += clearCoat;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return (color * light.colorIntensity.rgb) *
|
||||
(light.colorIntensity.w * light.attenuation * NoL * occlusion);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user