mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 19:29:47 +02:00
Bringing the Scattering type to the pixels and having a different shading during the lighting pass (for global right now)
This commit is contained in:
parent
72c362f7b0
commit
0c882832bf
24 changed files with 405 additions and 127 deletions
|
@ -41,5 +41,5 @@ void main(void) {
|
||||||
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
|
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
|
||||||
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
|
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
|
||||||
|
|
||||||
packDeferredFragment(_normal, 1.0, vec3(diffuse), DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION);
|
packDeferredFragment(_normal, 1.0, vec3(diffuse), DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING);
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,10 @@ void FBXReader::consolidateFBXMaterials() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (material.name.contains("body_mat") || material.name.contains("skin")) {
|
||||||
|
material._material->setScattering(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
if (material.opacity <= 0.0f) {
|
if (material.opacity <= 0.0f) {
|
||||||
material._material->setOpacity(1.0f);
|
material._material->setOpacity(1.0f);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -104,6 +104,13 @@ void Material::setMetallic(float metallic) {
|
||||||
_schemaBuffer.edit<Schema>()._metallic = metallic;
|
_schemaBuffer.edit<Schema>()._metallic = metallic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Material::setScattering(float scattering) {
|
||||||
|
scattering = glm::clamp(scattering, 0.0f, 1.0f);
|
||||||
|
_key.setMetallic(scattering > 0.0f);
|
||||||
|
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
|
||||||
|
_schemaBuffer.edit<Schema>()._scattering = scattering;
|
||||||
|
}
|
||||||
|
|
||||||
void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) {
|
void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) {
|
||||||
if (textureMap) {
|
if (textureMap) {
|
||||||
_key.setMapChannel(channel, (true));
|
_key.setMapChannel(channel, (true));
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
OPACITY_VAL_BIT,
|
OPACITY_VAL_BIT,
|
||||||
OPACITY_MASK_MAP_BIT, // Opacity Map and Opacity MASK map are mutually exclusive
|
OPACITY_MASK_MAP_BIT, // Opacity Map and Opacity MASK map are mutually exclusive
|
||||||
OPACITY_TRANSLUCENT_MAP_BIT,
|
OPACITY_TRANSLUCENT_MAP_BIT,
|
||||||
|
SCATTERING_VAL_BIT,
|
||||||
|
|
||||||
// THe map bits must be in the same sequence as the enum names for the map channels
|
// THe map bits must be in the same sequence as the enum names for the map channels
|
||||||
EMISSIVE_MAP_BIT,
|
EMISSIVE_MAP_BIT,
|
||||||
|
@ -44,6 +45,7 @@ public:
|
||||||
NORMAL_MAP_BIT,
|
NORMAL_MAP_BIT,
|
||||||
OCCLUSION_MAP_BIT,
|
OCCLUSION_MAP_BIT,
|
||||||
LIGHTMAP_MAP_BIT,
|
LIGHTMAP_MAP_BIT,
|
||||||
|
SCATTERING_MAP_BIT,
|
||||||
|
|
||||||
NUM_FLAGS,
|
NUM_FLAGS,
|
||||||
};
|
};
|
||||||
|
@ -57,6 +59,7 @@ public:
|
||||||
NORMAL_MAP,
|
NORMAL_MAP,
|
||||||
OCCLUSION_MAP,
|
OCCLUSION_MAP,
|
||||||
LIGHTMAP_MAP,
|
LIGHTMAP_MAP,
|
||||||
|
SCATTERING_MAP,
|
||||||
|
|
||||||
NUM_MAP_CHANNELS,
|
NUM_MAP_CHANNELS,
|
||||||
};
|
};
|
||||||
|
@ -83,6 +86,8 @@ public:
|
||||||
|
|
||||||
Builder& withTranslucentFactor() { _flags.set(OPACITY_VAL_BIT); return (*this); }
|
Builder& withTranslucentFactor() { _flags.set(OPACITY_VAL_BIT); return (*this); }
|
||||||
|
|
||||||
|
Builder& withScattering() { _flags.set(SCATTERING_VAL_BIT); return (*this); }
|
||||||
|
|
||||||
Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT); return (*this); }
|
Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT); return (*this); }
|
||||||
Builder& withAlbedoMap() { _flags.set(ALBEDO_MAP_BIT); return (*this); }
|
Builder& withAlbedoMap() { _flags.set(ALBEDO_MAP_BIT); return (*this); }
|
||||||
Builder& withMetallicMap() { _flags.set(METALLIC_MAP_BIT); return (*this); }
|
Builder& withMetallicMap() { _flags.set(METALLIC_MAP_BIT); return (*this); }
|
||||||
|
@ -94,6 +99,7 @@ public:
|
||||||
Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); }
|
Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); }
|
||||||
Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT); return (*this); }
|
Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT); return (*this); }
|
||||||
Builder& withLightmapMap() { _flags.set(LIGHTMAP_MAP_BIT); return (*this); }
|
Builder& withLightmapMap() { _flags.set(LIGHTMAP_MAP_BIT); return (*this); }
|
||||||
|
Builder& withScatteringMap() { _flags.set(SCATTERING_MAP_BIT); return (*this); }
|
||||||
|
|
||||||
// Convenient standard keys that we will keep on using all over the place
|
// Convenient standard keys that we will keep on using all over the place
|
||||||
static MaterialKey opaqueAlbedo() { return Builder().withAlbedo().build(); }
|
static MaterialKey opaqueAlbedo() { return Builder().withAlbedo().build(); }
|
||||||
|
@ -135,7 +141,7 @@ public:
|
||||||
|
|
||||||
void setOpacityMaskMap(bool value) { _flags.set(OPACITY_MASK_MAP_BIT, value); }
|
void setOpacityMaskMap(bool value) { _flags.set(OPACITY_MASK_MAP_BIT, value); }
|
||||||
bool isOpacityMaskMap() const { return _flags[OPACITY_MASK_MAP_BIT]; }
|
bool isOpacityMaskMap() const { return _flags[OPACITY_MASK_MAP_BIT]; }
|
||||||
|
|
||||||
void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); }
|
void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); }
|
||||||
bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; }
|
bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; }
|
||||||
|
|
||||||
|
@ -145,6 +151,12 @@ public:
|
||||||
void setLightmapMap(bool value) { _flags.set(LIGHTMAP_MAP_BIT, value); }
|
void setLightmapMap(bool value) { _flags.set(LIGHTMAP_MAP_BIT, value); }
|
||||||
bool isLightmapMap() const { return _flags[LIGHTMAP_MAP_BIT]; }
|
bool isLightmapMap() const { return _flags[LIGHTMAP_MAP_BIT]; }
|
||||||
|
|
||||||
|
void setScattering(bool value) { _flags.set(SCATTERING_VAL_BIT, value); }
|
||||||
|
bool isScattering() const { return _flags[SCATTERING_VAL_BIT]; }
|
||||||
|
|
||||||
|
void setScatteringMap(bool value) { _flags.set(SCATTERING_MAP_BIT, value); }
|
||||||
|
bool isScatteringMap() const { return _flags[SCATTERING_MAP_BIT]; }
|
||||||
|
|
||||||
void setMapChannel(MapChannel channel, bool value) { _flags.set(EMISSIVE_MAP_BIT + channel, value); }
|
void setMapChannel(MapChannel channel, bool value) { _flags.set(EMISSIVE_MAP_BIT + channel, value); }
|
||||||
bool isMapChannel(MapChannel channel) const { return _flags[EMISSIVE_MAP_BIT + channel]; }
|
bool isMapChannel(MapChannel channel) const { return _flags[EMISSIVE_MAP_BIT + channel]; }
|
||||||
|
|
||||||
|
@ -218,6 +230,13 @@ public:
|
||||||
Builder& withoutLightmapMap() { _value.reset(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
|
Builder& withoutLightmapMap() { _value.reset(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
|
||||||
Builder& withLightmapMap() { _value.set(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
|
Builder& withLightmapMap() { _value.set(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
|
||||||
|
|
||||||
|
Builder& withoutScattering() { _value.reset(MaterialKey::SCATTERING_VAL_BIT); _mask.set(MaterialKey::SCATTERING_VAL_BIT); return (*this); }
|
||||||
|
Builder& withScattering() { _value.set(MaterialKey::SCATTERING_VAL_BIT); _mask.set(MaterialKey::SCATTERING_VAL_BIT); return (*this); }
|
||||||
|
|
||||||
|
Builder& withoutScatteringMap() { _value.reset(MaterialKey::SCATTERING_MAP_BIT); _mask.set(MaterialKey::SCATTERING_MAP_BIT); return (*this); }
|
||||||
|
Builder& withScatteringMap() { _value.set(MaterialKey::SCATTERING_MAP_BIT); _mask.set(MaterialKey::SCATTERING_MAP_BIT); return (*this); }
|
||||||
|
|
||||||
|
|
||||||
// Convenient standard keys that we will keep on using all over the place
|
// Convenient standard keys that we will keep on using all over the place
|
||||||
static MaterialFilter opaqueAlbedo() { return Builder().withAlbedo().withoutTranslucentFactor().build(); }
|
static MaterialFilter opaqueAlbedo() { return Builder().withAlbedo().withoutTranslucentFactor().build(); }
|
||||||
};
|
};
|
||||||
|
@ -275,6 +294,8 @@ public:
|
||||||
void setRoughness(float roughness);
|
void setRoughness(float roughness);
|
||||||
float getRoughness() const { return _schemaBuffer.get<Schema>()._roughness; }
|
float getRoughness() const { return _schemaBuffer.get<Schema>()._roughness; }
|
||||||
|
|
||||||
|
void setScattering(float scattering);
|
||||||
|
float getScattering() const { return _schemaBuffer.get<Schema>()._scattering; }
|
||||||
|
|
||||||
// Schema to access the attribute values of the material
|
// Schema to access the attribute values of the material
|
||||||
class Schema {
|
class Schema {
|
||||||
|
@ -288,7 +309,9 @@ public:
|
||||||
glm::vec3 _fresnel{ 0.03f }; // Fresnel value for a default non metallic
|
glm::vec3 _fresnel{ 0.03f }; // Fresnel value for a default non metallic
|
||||||
float _metallic{ 0.0f }; // Not Metallic
|
float _metallic{ 0.0f }; // Not Metallic
|
||||||
|
|
||||||
glm::vec3 _spare{ 0.0f };
|
float _scattering{ 0.0f }; // Scattering info
|
||||||
|
|
||||||
|
glm::vec2 _spare{ 0.0f };
|
||||||
|
|
||||||
uint32_t _key{ 0 }; // a copy of the materialKey
|
uint32_t _key{ 0 }; // a copy of the materialKey
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct Material {
|
||||||
vec4 _emissiveOpacity;
|
vec4 _emissiveOpacity;
|
||||||
vec4 _albedoRoughness;
|
vec4 _albedoRoughness;
|
||||||
vec4 _fresnelMetallic;
|
vec4 _fresnelMetallic;
|
||||||
vec4 _spareKey;
|
vec4 _scatteringSpare2Key;
|
||||||
};
|
};
|
||||||
|
|
||||||
uniform materialBuffer {
|
uniform materialBuffer {
|
||||||
|
@ -37,7 +37,9 @@ float getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }
|
||||||
|
|
||||||
float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }
|
float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }
|
||||||
|
|
||||||
int getMaterialKey(Material m) { return floatBitsToInt(m._spareKey.w); }
|
float getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }
|
||||||
|
|
||||||
|
int getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }
|
||||||
|
|
||||||
const int EMISSIVE_VAL_BIT = 0x00000001;
|
const int EMISSIVE_VAL_BIT = 0x00000001;
|
||||||
const int UNLIT_VAL_BIT = 0x00000002;
|
const int UNLIT_VAL_BIT = 0x00000002;
|
||||||
|
@ -47,14 +49,17 @@ const int GLOSSY_VAL_BIT = 0x00000010;
|
||||||
const int OPACITY_VAL_BIT = 0x00000020;
|
const int OPACITY_VAL_BIT = 0x00000020;
|
||||||
const int OPACITY_MASK_MAP_BIT = 0x00000040;
|
const int OPACITY_MASK_MAP_BIT = 0x00000040;
|
||||||
const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;
|
const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;
|
||||||
|
const int SCATTERING_VAL_BIT = 0x00000100;
|
||||||
|
|
||||||
const int EMISSIVE_MAP_BIT = 0x00000100;
|
|
||||||
const int ALBEDO_MAP_BIT = 0x00000200;
|
const int EMISSIVE_MAP_BIT = 0x00000200;
|
||||||
const int METALLIC_MAP_BIT = 0x00000400;
|
const int ALBEDO_MAP_BIT = 0x00000400;
|
||||||
const int ROUGHNESS_MAP_BIT = 0x00000800;
|
const int METALLIC_MAP_BIT = 0x00000800;
|
||||||
const int NORMAL_MAP_BIT = 0x00001000;
|
const int ROUGHNESS_MAP_BIT = 0x00001000;
|
||||||
const int OCCLUSION_MAP_BIT = 0x00002000;
|
const int NORMAL_MAP_BIT = 0x00002000;
|
||||||
const int LIGHTMAP_MAP_BIT = 0x00004000;
|
const int OCCLUSION_MAP_BIT = 0x00004000;
|
||||||
|
const int LIGHTMAP_MAP_BIT = 0x00008000;
|
||||||
|
const int SCATTERING_MAP_BIT = 0x00010000;
|
||||||
|
|
||||||
|
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
|
@ -111,6 +111,13 @@ static const std::string DEFAULT_LIGHTMAP_SHADER{
|
||||||
" }"
|
" }"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const std::string DEFAULT_SCATTERING_SHADER{
|
||||||
|
"vec4 getFragmentColor() {"
|
||||||
|
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
|
||||||
|
" return (frag.mode == FRAG_MODE_SCATTERING ? vec4(vec3(1.0), 1.0) : vec4(vec3(0.0), 1.0));"
|
||||||
|
" }"
|
||||||
|
};
|
||||||
|
|
||||||
static const std::string DEFAULT_DEPTH_SHADER {
|
static const std::string DEFAULT_DEPTH_SHADER {
|
||||||
"vec4 getFragmentColor() {"
|
"vec4 getFragmentColor() {"
|
||||||
" return vec4(vec3(texture(depthMap, uv).x), 1.0);"
|
" return vec4(vec3(texture(depthMap, uv).x), 1.0);"
|
||||||
|
@ -173,7 +180,7 @@ static const std::string DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER{
|
||||||
" }"
|
" }"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::string DEFAULT_SCATTERING_SHADER{
|
static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{
|
||||||
"vec4 getFragmentColor() {"
|
"vec4 getFragmentColor() {"
|
||||||
" return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);"
|
" return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);"
|
||||||
// " return vec4(vec3(texture(scatteringMap, uv).xyz), 1.0);"
|
// " return vec4(vec3(texture(scatteringMap, uv).xyz), 1.0);"
|
||||||
|
@ -239,6 +246,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust
|
||||||
return DEFAULT_OCCLUSION_SHADER;
|
return DEFAULT_OCCLUSION_SHADER;
|
||||||
case LightmapMode:
|
case LightmapMode:
|
||||||
return DEFAULT_LIGHTMAP_SHADER;
|
return DEFAULT_LIGHTMAP_SHADER;
|
||||||
|
case ScatteringMode:
|
||||||
|
return DEFAULT_SCATTERING_SHADER;
|
||||||
case LightingMode:
|
case LightingMode:
|
||||||
return DEFAULT_LIGHTING_SHADER;
|
return DEFAULT_LIGHTING_SHADER;
|
||||||
case ShadowMode:
|
case ShadowMode:
|
||||||
|
@ -253,8 +262,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust
|
||||||
return DEFAULT_DIFFUSED_CURVATURE_SHADER;
|
return DEFAULT_DIFFUSED_CURVATURE_SHADER;
|
||||||
case DiffusedNormalCurvatureMode:
|
case DiffusedNormalCurvatureMode:
|
||||||
return DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER;
|
return DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER;
|
||||||
case ScatteringMode:
|
case ScatteringDebugMode:
|
||||||
return DEFAULT_SCATTERING_SHADER;
|
return DEFAULT_DEBUG_SCATTERING_SHADER;
|
||||||
case AmbientOcclusionMode:
|
case AmbientOcclusionMode:
|
||||||
return DEFAULT_AMBIENT_OCCLUSION_SHADER;
|
return DEFAULT_AMBIENT_OCCLUSION_SHADER;
|
||||||
case AmbientOcclusionBlurredMode:
|
case AmbientOcclusionBlurredMode:
|
||||||
|
|
|
@ -57,6 +57,7 @@ protected:
|
||||||
UnlitMode,
|
UnlitMode,
|
||||||
OcclusionMode,
|
OcclusionMode,
|
||||||
LightmapMode,
|
LightmapMode,
|
||||||
|
ScatteringMode,
|
||||||
LightingMode,
|
LightingMode,
|
||||||
ShadowMode,
|
ShadowMode,
|
||||||
PyramidDepthMode,
|
PyramidDepthMode,
|
||||||
|
@ -64,7 +65,7 @@ protected:
|
||||||
NormalCurvatureMode,
|
NormalCurvatureMode,
|
||||||
DiffusedCurvatureMode,
|
DiffusedCurvatureMode,
|
||||||
DiffusedNormalCurvatureMode,
|
DiffusedNormalCurvatureMode,
|
||||||
ScatteringMode,
|
ScatteringDebugMode,
|
||||||
AmbientOcclusionMode,
|
AmbientOcclusionMode,
|
||||||
AmbientOcclusionBlurredMode,
|
AmbientOcclusionBlurredMode,
|
||||||
CustomMode // Needs to stay last
|
CustomMode // Needs to stay last
|
||||||
|
|
|
@ -20,11 +20,16 @@ const float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;
|
||||||
const float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;
|
const float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;
|
||||||
const float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);
|
const float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);
|
||||||
|
|
||||||
const float FRAG_PACK_UNLIT = 0.5;
|
const float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;
|
||||||
|
const float FRAG_PACK_SCATTERING_METALLIC = 0.5;
|
||||||
|
const float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);
|
||||||
|
|
||||||
|
const float FRAG_PACK_UNLIT = 0.6;
|
||||||
|
|
||||||
const int FRAG_MODE_UNLIT = 0;
|
const int FRAG_MODE_UNLIT = 0;
|
||||||
const int FRAG_MODE_SHADED = 1;
|
const int FRAG_MODE_SHADED = 1;
|
||||||
const int FRAG_MODE_LIGHTMAPPED = 2;
|
const int FRAG_MODE_LIGHTMAPPED = 2;
|
||||||
|
const int FRAG_MODE_SCATTERING = 3;
|
||||||
|
|
||||||
void unpackModeMetallic(float rawValue, out int mode, out float metallic) {
|
void unpackModeMetallic(float rawValue, out int mode, out float metallic) {
|
||||||
if (rawValue <= FRAG_PACK_SHADED_METALLIC) {
|
if (rawValue <= FRAG_PACK_SHADED_METALLIC) {
|
||||||
|
@ -32,7 +37,10 @@ void unpackModeMetallic(float rawValue, out int mode, out float metallic) {
|
||||||
metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);
|
metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);
|
||||||
} else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {
|
} else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {
|
||||||
mode = FRAG_MODE_LIGHTMAPPED;
|
mode = FRAG_MODE_LIGHTMAPPED;
|
||||||
metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);
|
metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);
|
||||||
|
} else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {
|
||||||
|
mode = FRAG_MODE_SCATTERING;
|
||||||
|
metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);
|
||||||
} else if (rawValue >= FRAG_PACK_UNLIT) {
|
} else if (rawValue >= FRAG_PACK_UNLIT) {
|
||||||
mode = FRAG_MODE_UNLIT;
|
mode = FRAG_MODE_UNLIT;
|
||||||
metallic = 0.0;
|
metallic = 0.0;
|
||||||
|
@ -47,6 +55,10 @@ float packLightmappedMetallic(float metallic) {
|
||||||
return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);
|
return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float packScatteringMetallic(float metallic) {
|
||||||
|
return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);
|
||||||
|
}
|
||||||
|
|
||||||
float packUnlit() {
|
float packUnlit() {
|
||||||
return FRAG_PACK_UNLIT;
|
return FRAG_PACK_UNLIT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,4 +111,24 @@ DeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<@func declareDeferredCurvature()@>
|
||||||
|
|
||||||
|
// the curvature texture
|
||||||
|
uniform sampler2D curvatureMap;
|
||||||
|
|
||||||
|
vec4 fetchCurvature(vec2 texcoord) {
|
||||||
|
return texture(curvatureMap, texcoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the curvature texture
|
||||||
|
uniform sampler2D diffusedCurvatureMap;
|
||||||
|
|
||||||
|
vec4 fetchDiffusedCurvature(vec2 texcoord) {
|
||||||
|
return texture(diffusedCurvatureMap, texcoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
|
@ -30,13 +30,14 @@ const float DEFAULT_METALLIC = 0;
|
||||||
const vec3 DEFAULT_SPECULAR = vec3(0.1);
|
const vec3 DEFAULT_SPECULAR = vec3(0.1);
|
||||||
const vec3 DEFAULT_EMISSIVE = vec3(0.0);
|
const vec3 DEFAULT_EMISSIVE = vec3(0.0);
|
||||||
const float DEFAULT_OCCLUSION = 1.0;
|
const float DEFAULT_OCCLUSION = 1.0;
|
||||||
|
const float DEFAULT_SCATTERING = 0.0;
|
||||||
const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;
|
const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;
|
||||||
|
|
||||||
void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion) {
|
void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {
|
||||||
if (alpha != 1.0) {
|
if (alpha != 1.0) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
_fragColor0 = vec4(albedo, packShadedMetallic(metallic));
|
_fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));
|
||||||
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
||||||
_fragColor2 = vec4(emissive, occlusion);
|
_fragColor2 = vec4(emissive, occlusion);
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,49 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
||||||
|
<@func declareEvalSkyboxGlobalColorScattering()@>
|
||||||
|
|
||||||
|
<$declareDeferredCurvature()$>
|
||||||
|
<@include SubsurfaceScattering.slh@>
|
||||||
|
<$declareSubsurfaceScatteringResource()$>
|
||||||
|
|
||||||
|
vec3 evalSkyboxGlobalColorScattering(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec4 blurredCurvature, vec4 diffusedCurvature, float roughness) {
|
||||||
|
// prepareGlobalLight
|
||||||
|
|
||||||
|
// Transform directions to worldspace
|
||||||
|
vec3 fragNormal = vec3((normal));
|
||||||
|
vec3 fragEyeVector = vec3(invViewMat * vec4(-position, 0.0));
|
||||||
|
vec3 fragEyeDir = normalize(fragEyeVector);
|
||||||
|
|
||||||
|
// Get light
|
||||||
|
Light light = getLight();
|
||||||
|
vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
|
||||||
|
float metallic = 1.0;
|
||||||
|
|
||||||
|
vec3 fragLightDir = -normalize(getLightDirection(light));
|
||||||
|
|
||||||
|
vec3 bentNormalHigh = normalize( (blurredCurvature.xyz - 0.5f) * 2.0f );
|
||||||
|
vec3 bentNormalLow = normalize( (diffusedCurvature.xyz - 0.5f) * 2.0f );
|
||||||
|
float curvature = unpackCurvature(diffusedCurvature.w);
|
||||||
|
|
||||||
|
|
||||||
|
vec3 rS = bentNormalHigh;
|
||||||
|
|
||||||
|
vec3 bendFactorSpectrum = getBendFactor();
|
||||||
|
vec3 rN = normalize(mix(normal, bentNormalLow, bendFactorSpectrum.x));
|
||||||
|
vec3 gN = normalize(mix(bentNormalHigh, bentNormalLow, bendFactorSpectrum.y));
|
||||||
|
vec3 bN = normalize(mix(bentNormalHigh, bentNormalLow, bendFactorSpectrum.z));
|
||||||
|
|
||||||
|
vec3 NdotLSpectrum = vec3(dot(rN, fragLightDir), dot(gN, fragLightDir), dot(bN, fragLightDir));
|
||||||
|
|
||||||
|
// --> Look up the pre-integrated curvature-dependent BDRF textures
|
||||||
|
vec3 bdrf = fetchBRDFSpectrum(NdotLSpectrum, curvature);
|
||||||
|
|
||||||
|
|
||||||
|
return vec3(bdrf);
|
||||||
|
}
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
||||||
<@func declareEvalGlobalLightingAlphaBlended()@>
|
<@func declareEvalGlobalLightingAlphaBlended()@>
|
||||||
|
|
||||||
|
|
|
@ -41,13 +41,14 @@
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
struct LightLocations {
|
struct LightLocations {
|
||||||
int radius;
|
int radius{ -1 };
|
||||||
int ambientSphere;
|
int ambientSphere{ -1 };
|
||||||
int lightBufferUnit;
|
int lightBufferUnit{ -1 };
|
||||||
int sphereParam;
|
int sphereParam{ -1 };
|
||||||
int coneParam;
|
int coneParam{ -1 };
|
||||||
int deferredFrameTransformBuffer;
|
int deferredFrameTransformBuffer{ -1 };
|
||||||
int shadowTransformBuffer;
|
int subsurfaceScatteringParametersBuffer{ -1 };
|
||||||
|
int shadowTransformBuffer{ -1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DeferredShader_MapSlot {
|
enum DeferredShader_MapSlot {
|
||||||
|
@ -58,10 +59,14 @@ enum DeferredShader_MapSlot {
|
||||||
DEFERRED_BUFFER_OBSCURANCE_UNIT = 4,
|
DEFERRED_BUFFER_OBSCURANCE_UNIT = 4,
|
||||||
SHADOW_MAP_UNIT = 5,
|
SHADOW_MAP_UNIT = 5,
|
||||||
SKYBOX_MAP_UNIT = 6,
|
SKYBOX_MAP_UNIT = 6,
|
||||||
|
DEFERRED_BUFFER_CURVATURE_UNIT,
|
||||||
|
DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT,
|
||||||
|
SCATTERING_LUT_UNIT,
|
||||||
};
|
};
|
||||||
enum DeferredShader_BufferSlot {
|
enum DeferredShader_BufferSlot {
|
||||||
DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT = 2,
|
DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT = 0,
|
||||||
LIGHT_GPU_SLOT = 3,
|
SCATTERING_PARAMETERS_BUFFER_SLOT,
|
||||||
|
LIGHT_GPU_SLOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
|
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
|
||||||
|
@ -167,7 +172,13 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), SHADOW_MAP_UNIT));
|
slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), SHADOW_MAP_UNIT));
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), SKYBOX_MAP_UNIT));
|
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), SKYBOX_MAP_UNIT));
|
||||||
|
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), DEFERRED_BUFFER_CURVATURE_UNIT));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("diffusedCurvatureMap"), DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), SCATTERING_LUT_UNIT));
|
||||||
|
|
||||||
|
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT));
|
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("subsurfaceScatteringParametersBuffer"), SCATTERING_PARAMETERS_BUFFER_SLOT));
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT));
|
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT));
|
||||||
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
@ -180,6 +191,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
|
||||||
|
|
||||||
locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
|
locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
|
||||||
locations->deferredFrameTransformBuffer = program->getBuffers().findLocation("deferredFrameTransformBuffer");
|
locations->deferredFrameTransformBuffer = program->getBuffers().findLocation("deferredFrameTransformBuffer");
|
||||||
|
locations->subsurfaceScatteringParametersBuffer = program->getBuffers().findLocation("subsurfaceScatteringParametersBuffer");
|
||||||
locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer");
|
locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer");
|
||||||
|
|
||||||
auto state = std::make_shared<gpu::State>();
|
auto state = std::make_shared<gpu::State>();
|
||||||
|
@ -338,7 +350,7 @@ void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform) {
|
void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform, const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource) {
|
||||||
|
|
||||||
auto args = renderContext->args;
|
auto args = renderContext->args;
|
||||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||||
|
@ -372,59 +384,68 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c
|
||||||
// need to assign the white texture if ao is off
|
// need to assign the white texture if ao is off
|
||||||
batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, textureCache->getWhiteTexture());
|
batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, textureCache->getWhiteTexture());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(deferredLightingEffect->getLightStage().lights.size() > 0);
|
|
||||||
const auto& globalShadow = deferredLightingEffect->getLightStage().lights[0]->shadow;
|
|
||||||
|
|
||||||
// Bind the shadow buffer
|
|
||||||
batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow.map);
|
|
||||||
|
|
||||||
|
// The Deferred Frame Transform buffer
|
||||||
batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, frameTransform->getFrameTransformBuffer());
|
batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, frameTransform->getFrameTransformBuffer());
|
||||||
|
|
||||||
|
// Subsurface scattering specific
|
||||||
|
batch.setResourceTexture(DEFERRED_BUFFER_CURVATURE_UNIT, framebufferCache->getCurvatureTexture());
|
||||||
|
batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, framebufferCache->getCurvatureTexture());
|
||||||
|
|
||||||
|
batch.setUniformBuffer(SCATTERING_PARAMETERS_BUFFER_SLOT, subsurfaceScatteringResource->getParametersBuffer());
|
||||||
|
|
||||||
|
|
||||||
|
batch.setResourceTexture(SCATTERING_LUT_UNIT, subsurfaceScatteringResource->getScatteringTable());
|
||||||
|
|
||||||
|
|
||||||
// Global directional light and ambient pass
|
// Global directional light and ambient pass
|
||||||
{
|
|
||||||
auto& program = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadow : deferredLightingEffect->_directionalLight;
|
|
||||||
LightLocationsPtr locations = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadowLocations : deferredLightingEffect->_directionalLightLocations;
|
|
||||||
const auto& keyLight = deferredLightingEffect->_allocatedLights[deferredLightingEffect->_globalLights.front()];
|
|
||||||
|
|
||||||
// Setup the global directional pass pipeline
|
|
||||||
{
|
|
||||||
if (deferredLightingEffect->_shadowMapEnabled) {
|
|
||||||
if (keyLight->getAmbientMap()) {
|
|
||||||
program = deferredLightingEffect->_directionalSkyboxLightShadow;
|
|
||||||
locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations;
|
|
||||||
} else {
|
|
||||||
program = deferredLightingEffect->_directionalAmbientSphereLightShadow;
|
|
||||||
locations = deferredLightingEffect->_directionalAmbientSphereLightShadowLocations;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (keyLight->getAmbientMap()) {
|
|
||||||
program = deferredLightingEffect->_directionalSkyboxLight;
|
|
||||||
locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
|
||||||
} else {
|
|
||||||
program = deferredLightingEffect->_directionalAmbientSphereLight;
|
|
||||||
locations = deferredLightingEffect->_directionalAmbientSphereLightLocations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (locations->shadowTransformBuffer >= 0) {
|
|
||||||
batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow.getBuffer());
|
|
||||||
}
|
|
||||||
batch.setPipeline(program);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ // Setup the global lighting
|
|
||||||
deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, SKYBOX_MAP_UNIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
|
||||||
|
|
||||||
if (keyLight->getAmbientMap()) {
|
assert(deferredLightingEffect->getLightStage().lights.size() > 0);
|
||||||
batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr);
|
const auto& globalShadow = deferredLightingEffect->getLightStage().lights[0]->shadow;
|
||||||
|
|
||||||
|
// Bind the shadow buffer
|
||||||
|
batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow.map);
|
||||||
|
|
||||||
|
auto& program = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadow : deferredLightingEffect->_directionalLight;
|
||||||
|
LightLocationsPtr locations = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadowLocations : deferredLightingEffect->_directionalLightLocations;
|
||||||
|
const auto& keyLight = deferredLightingEffect->_allocatedLights[deferredLightingEffect->_globalLights.front()];
|
||||||
|
|
||||||
|
// Setup the global directional pass pipeline
|
||||||
|
{
|
||||||
|
if (deferredLightingEffect->_shadowMapEnabled) {
|
||||||
|
if (keyLight->getAmbientMap()) {
|
||||||
|
program = deferredLightingEffect->_directionalSkyboxLightShadow;
|
||||||
|
locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations;
|
||||||
|
} else {
|
||||||
|
program = deferredLightingEffect->_directionalAmbientSphereLightShadow;
|
||||||
|
locations = deferredLightingEffect->_directionalAmbientSphereLightShadowLocations;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (keyLight->getAmbientMap()) {
|
||||||
|
program = deferredLightingEffect->_directionalSkyboxLight;
|
||||||
|
locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
||||||
|
} else {
|
||||||
|
program = deferredLightingEffect->_directionalAmbientSphereLight;
|
||||||
|
locations = deferredLightingEffect->_directionalAmbientSphereLightLocations;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (locations->shadowTransformBuffer >= 0) {
|
||||||
|
batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow.getBuffer());
|
||||||
|
}
|
||||||
|
batch.setPipeline(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ // Setup the global lighting
|
||||||
|
deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, SKYBOX_MAP_UNIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
||||||
|
if (keyLight->getAmbientMap()) {
|
||||||
|
batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr);
|
||||||
|
}
|
||||||
|
batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -562,9 +583,12 @@ void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext,
|
||||||
batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, nullptr);
|
batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, nullptr);
|
||||||
batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, nullptr);
|
batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, nullptr);
|
||||||
batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, nullptr);
|
batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, nullptr);
|
||||||
batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr);
|
|
||||||
batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr);
|
batch.setResourceTexture(DEFERRED_BUFFER_CURVATURE_UNIT, nullptr);
|
||||||
|
batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, nullptr);
|
||||||
|
batch.setResourceTexture(SCATTERING_LUT_UNIT, nullptr);
|
||||||
|
|
||||||
|
batch.setUniformBuffer(SCATTERING_PARAMETERS_BUFFER_SLOT, nullptr);
|
||||||
batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr);
|
batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -582,7 +606,12 @@ void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext,
|
||||||
|
|
||||||
|
|
||||||
void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const DeferredFrameTransformPointer& deferredTransform) {
|
void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const DeferredFrameTransformPointer& deferredTransform) {
|
||||||
setupJob.run(sceneContext, renderContext, deferredTransform);
|
if (!_subsurfaceScatteringResource) {
|
||||||
|
_subsurfaceScatteringResource = std::make_shared<SubsurfaceScatteringResource>();
|
||||||
|
_subsurfaceScatteringResource->generateScatteringTable(renderContext->args);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupJob.run(sceneContext, renderContext, deferredTransform, _subsurfaceScatteringResource);
|
||||||
lightsJob.run(sceneContext, renderContext, deferredTransform);
|
lightsJob.run(sceneContext, renderContext, deferredTransform);
|
||||||
|
|
||||||
cleanupJob.run(sceneContext, renderContext);
|
cleanupJob.run(sceneContext, renderContext);
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include "LightStage.h"
|
#include "LightStage.h"
|
||||||
|
|
||||||
|
#include "SubsurfaceScattering.h"
|
||||||
|
|
||||||
class RenderArgs;
|
class RenderArgs;
|
||||||
struct LightLocations;
|
struct LightLocations;
|
||||||
using LightLocationsPtr = std::shared_ptr<LightLocations>;
|
using LightLocationsPtr = std::shared_ptr<LightLocations>;
|
||||||
|
@ -111,9 +113,9 @@ public:
|
||||||
|
|
||||||
class RenderDeferredSetup {
|
class RenderDeferredSetup {
|
||||||
public:
|
public:
|
||||||
using JobModel = render::Job::ModelI<RenderDeferredSetup, DeferredFrameTransformPointer>;
|
// using JobModel = render::Job::ModelI<RenderDeferredSetup, DeferredFrameTransformPointer>;
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform, const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderDeferredLocals {
|
class RenderDeferredLocals {
|
||||||
|
@ -140,6 +142,8 @@ public:
|
||||||
RenderDeferredSetup setupJob;
|
RenderDeferredSetup setupJob;
|
||||||
RenderDeferredLocals lightsJob;
|
RenderDeferredLocals lightsJob;
|
||||||
RenderDeferredCleanup cleanupJob;
|
RenderDeferredCleanup cleanupJob;
|
||||||
|
|
||||||
|
SubsurfaceScatteringResourcePointer _subsurfaceScatteringResource;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_DeferredLightingEffect_h
|
#endif // hifi_DeferredLightingEffect_h
|
||||||
|
|
|
@ -38,26 +38,49 @@ enum ScatteringShaderMapSlots {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SubsurfaceScattering::SubsurfaceScattering() {
|
SubsurfaceScatteringResource::SubsurfaceScatteringResource() {
|
||||||
Parameters parameters;
|
Parameters parameters;
|
||||||
_parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) ¶meters));
|
_parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) ¶meters));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubsurfaceScatteringResource::setBentNormalFactors(const glm::vec4& rgbsBentFactors) {
|
||||||
|
if (rgbsBentFactors != getBentNormalFactors()) {
|
||||||
|
_parametersBuffer.edit<Parameters>().normalBentInfo = rgbsBentFactors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec4 SubsurfaceScatteringResource::getBentNormalFactors() const {
|
||||||
|
return _parametersBuffer.get<Parameters>().normalBentInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubsurfaceScatteringResource::setCurvatureFactors(const glm::vec2& sbCurvatureFactors) {
|
||||||
|
if (sbCurvatureFactors != getCurvatureFactors()) {
|
||||||
|
_parametersBuffer.edit<Parameters>().curvatureInfo = sbCurvatureFactors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 SubsurfaceScatteringResource::getCurvatureFactors() const {
|
||||||
|
return _parametersBuffer.get<Parameters>().curvatureInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubsurfaceScatteringResource::generateScatteringTable(RenderArgs* args) {
|
||||||
|
if (!_scatteringTable) {
|
||||||
|
_scatteringTable = generatePreIntegratedScattering(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SubsurfaceScattering::SubsurfaceScattering() {
|
||||||
|
_scatteringResource = std::make_shared<SubsurfaceScatteringResource>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsurfaceScattering::configure(const Config& config) {
|
void SubsurfaceScattering::configure(const Config& config) {
|
||||||
auto& params = _parametersBuffer.get<Parameters>();
|
|
||||||
|
|
||||||
glm::vec4 bentInfo(config.bentRed, config.bentGreen, config.bentBlue, config.bentScale);
|
glm::vec4 bentInfo(config.bentRed, config.bentGreen, config.bentBlue, config.bentScale);
|
||||||
|
_scatteringResource->setBentNormalFactors(bentInfo);
|
||||||
|
|
||||||
if (bentInfo != params.normalBentInfo) {
|
glm::vec2 curvatureInfo(config.curvatureOffset, config.curvatureScale);
|
||||||
_parametersBuffer.edit<Parameters>().normalBentInfo = bentInfo;
|
_scatteringResource->setCurvatureFactors(curvatureInfo);
|
||||||
}
|
|
||||||
|
|
||||||
if (config.curvatureOffset != params.curvatureInfo.x) {
|
|
||||||
_parametersBuffer.edit<Parameters>().curvatureInfo.x = config.curvatureOffset;
|
|
||||||
}
|
|
||||||
if (config.curvatureScale != params.curvatureInfo.y) {
|
|
||||||
_parametersBuffer.edit<Parameters>().curvatureInfo.y = config.curvatureScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
_showLUT = config.showLUT;
|
_showLUT = config.showLUT;
|
||||||
}
|
}
|
||||||
|
@ -164,9 +187,8 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext,
|
||||||
|
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
||||||
if (!_scatteringTable) {
|
_scatteringResource->generateScatteringTable(args);
|
||||||
_scatteringTable = SubsurfaceScattering::generatePreIntegratedScattering(args);
|
auto scatteringTable = _scatteringResource->getScatteringTable();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
auto pipeline = getScatteringPipeline();
|
auto pipeline = getScatteringPipeline();
|
||||||
|
@ -194,14 +216,14 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext,
|
||||||
batch.setPipeline(pipeline);
|
batch.setPipeline(pipeline);
|
||||||
|
|
||||||
batch.setUniformBuffer(ScatteringTask_FrameTransformSlot, frameTransform->getFrameTransformBuffer());
|
batch.setUniformBuffer(ScatteringTask_FrameTransformSlot, frameTransform->getFrameTransformBuffer());
|
||||||
batch.setUniformBuffer(ScatteringTask_ParamSlot, _parametersBuffer);
|
batch.setUniformBuffer(ScatteringTask_ParamSlot, _scatteringResource->getParametersBuffer());
|
||||||
if (theLight->light) {
|
if (theLight->light) {
|
||||||
batch.setUniformBuffer(ScatteringTask_LightSlot, theLight->light->getSchemaBuffer());
|
batch.setUniformBuffer(ScatteringTask_LightSlot, theLight->light->getSchemaBuffer());
|
||||||
if (theLight->light->getAmbientMap()) {
|
if (theLight->light->getAmbientMap()) {
|
||||||
batch.setResourceTexture(ScatteringTask_IBLMapSlot, theLight->light->getAmbientMap());
|
batch.setResourceTexture(ScatteringTask_IBLMapSlot, theLight->light->getAmbientMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch.setResourceTexture(ScatteringTask_ScatteringTableSlot, _scatteringTable);
|
batch.setResourceTexture(ScatteringTask_ScatteringTableSlot, scatteringTable);
|
||||||
batch.setResourceTexture(ScatteringTask_CurvatureMapSlot, curvatureFramebuffer->getRenderBuffer(0));
|
batch.setResourceTexture(ScatteringTask_CurvatureMapSlot, curvatureFramebuffer->getRenderBuffer(0));
|
||||||
batch.setResourceTexture(ScatteringTask_DiffusedCurvatureMapSlot, diffusedFramebuffer->getRenderBuffer(0));
|
batch.setResourceTexture(ScatteringTask_DiffusedCurvatureMapSlot, diffusedFramebuffer->getRenderBuffer(0));
|
||||||
batch.setResourceTexture(ScatteringTask_NormalMapSlot, framebufferCache->getDeferredNormalTexture());
|
batch.setResourceTexture(ScatteringTask_NormalMapSlot, framebufferCache->getDeferredNormalTexture());
|
||||||
|
@ -214,7 +236,7 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext,
|
||||||
auto viewportSize = std::min(args->_viewport.z, args->_viewport.w) >> 1;
|
auto viewportSize = std::min(args->_viewport.z, args->_viewport.w) >> 1;
|
||||||
batch.setViewportTransform(glm::ivec4(0, 0, viewportSize, viewportSize));
|
batch.setViewportTransform(glm::ivec4(0, 0, viewportSize, viewportSize));
|
||||||
batch.setPipeline(getShowLUTPipeline());
|
batch.setPipeline(getShowLUTPipeline());
|
||||||
batch.setResourceTexture(0, _scatteringTable);
|
batch.setResourceTexture(0, scatteringTable);
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -420,18 +442,15 @@ void diffuseProfile(gpu::TexturePointer& profile) {
|
||||||
profile->assignStoredMip(0, gpu::Element::COLOR_RGBA_32, bytes.size(), bytes.data());
|
profile->assignStoredMip(0, gpu::Element::COLOR_RGBA_32, bytes.size(), bytes.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer SubsurfaceScatteringResource::generatePreIntegratedScattering(RenderArgs* args) {
|
||||||
|
|
||||||
|
|
||||||
gpu::TexturePointer SubsurfaceScattering::generatePreIntegratedScattering(RenderArgs* args) {
|
|
||||||
|
|
||||||
auto profileMap = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, 128, 1, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
auto profileMap = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, 128, 1, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
diffuseProfile(profileMap);
|
diffuseProfile(profileMap);
|
||||||
|
|
||||||
const int WIDTH = 128;
|
const int WIDTH = 128;
|
||||||
const int HEIGHT = 128;
|
const int HEIGHT = 128;
|
||||||
auto scatteringLUT = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, WIDTH, HEIGHT, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
auto scatteringLUT = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, WIDTH, HEIGHT, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
diffuseScatter(scatteringLUT);
|
diffuseScatter(scatteringLUT);
|
||||||
//diffuseScatterGPU(profileMap, scatteringLUT, args);
|
//diffuseScatterGPU(profileMap, scatteringLUT, args);
|
||||||
return scatteringLUT;
|
return scatteringLUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,49 @@
|
||||||
#include "render/DrawTask.h"
|
#include "render/DrawTask.h"
|
||||||
#include "DeferredFrameTransform.h"
|
#include "DeferredFrameTransform.h"
|
||||||
|
|
||||||
|
class SubsurfaceScatteringResource {
|
||||||
|
public:
|
||||||
|
using UniformBufferView = gpu::BufferView;
|
||||||
|
|
||||||
|
SubsurfaceScatteringResource();
|
||||||
|
|
||||||
|
void setBentNormalFactors(const glm::vec4& rgbsBentFactors);
|
||||||
|
glm::vec4 getBentNormalFactors() const;
|
||||||
|
|
||||||
|
void setCurvatureFactors(const glm::vec2& sbCurvatureFactors);
|
||||||
|
glm::vec2 getCurvatureFactors() const;
|
||||||
|
|
||||||
|
UniformBufferView getParametersBuffer() const { return _parametersBuffer; }
|
||||||
|
|
||||||
|
gpu::TexturePointer getScatteringTable() const { return _scatteringTable; }
|
||||||
|
|
||||||
|
void generateScatteringTable(RenderArgs* args);
|
||||||
|
static gpu::TexturePointer generatePreIntegratedScattering(RenderArgs* args);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
// Class describing the uniform buffer with the transform info common to the AO shaders
|
||||||
|
// It s changing every frame
|
||||||
|
class Parameters {
|
||||||
|
public:
|
||||||
|
glm::vec4 normalBentInfo{ 1.5f, 0.8f, 0.3f, 1.5f };
|
||||||
|
glm::vec2 curvatureInfo{ 0.08f, 0.8f };
|
||||||
|
glm::vec2 spare{ 0.0f };
|
||||||
|
|
||||||
|
Parameters() {}
|
||||||
|
};
|
||||||
|
UniformBufferView _parametersBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
gpu::TexturePointer _scatteringTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
using SubsurfaceScatteringResourcePointer = std::shared_ptr<SubsurfaceScatteringResource>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SubsurfaceScatteringConfig : public render::Job::Config {
|
class SubsurfaceScatteringConfig : public render::Job::Config {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(float bentRed MEMBER bentRed NOTIFY dirty)
|
Q_PROPERTY(float bentRed MEMBER bentRed NOTIFY dirty)
|
||||||
|
@ -57,24 +100,8 @@ public:
|
||||||
void configure(const Config& config);
|
void configure(const Config& config);
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, gpu::FramebufferPointer& scatteringFramebuffer);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, gpu::FramebufferPointer& scatteringFramebuffer);
|
||||||
|
|
||||||
static gpu::TexturePointer generatePreIntegratedScattering(RenderArgs* args);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef gpu::BufferView UniformBufferView;
|
SubsurfaceScatteringResourcePointer _scatteringResource;
|
||||||
|
|
||||||
// Class describing the uniform buffer with all the parameters common to the AO shaders
|
|
||||||
class Parameters {
|
|
||||||
public:
|
|
||||||
glm::vec4 normalBentInfo { 0.0f };
|
|
||||||
glm::vec4 curvatureInfo{ 0.0f };
|
|
||||||
|
|
||||||
Parameters() {}
|
|
||||||
};
|
|
||||||
gpu::BufferView _parametersBuffer;
|
|
||||||
|
|
||||||
|
|
||||||
gpu::TexturePointer _scatteringTable;
|
|
||||||
|
|
||||||
|
|
||||||
bool updateScatteringFramebuffer(const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& scatteringFramebuffer);
|
bool updateScatteringFramebuffer(const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& scatteringFramebuffer);
|
||||||
gpu::FramebufferPointer _scatteringFramebuffer;
|
gpu::FramebufferPointer _scatteringFramebuffer;
|
||||||
|
|
45
libraries/render-utils/src/SubsurfaceScattering.slh
Normal file
45
libraries/render-utils/src/SubsurfaceScattering.slh
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 6/8/16.
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
<@func declareSubsurfaceScatteringResource()@>
|
||||||
|
|
||||||
|
uniform sampler2D scatteringLUT;
|
||||||
|
|
||||||
|
vec3 fetchBRDF(float LdotN, float curvature) {
|
||||||
|
return texture(scatteringLUT, vec2( LdotN * 0.5 + 0.5, curvature)).xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {
|
||||||
|
return vec3(
|
||||||
|
fetchBRDF(LdotNSpectrum.r, curvature).r,
|
||||||
|
fetchBRDF(LdotNSpectrum.g, curvature).g,
|
||||||
|
fetchBRDF(LdotNSpectrum.b, curvature).b
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subsurface Scattering parameters
|
||||||
|
struct ScatteringParameters {
|
||||||
|
vec4 normalBendInfo; // R, G, B, factor
|
||||||
|
vec4 curvatureInfo;// Offset, Scale
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform subsurfaceScatteringParametersBuffer {
|
||||||
|
ScatteringParameters parameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec3 getBendFactor() {
|
||||||
|
return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
float unpackCurvature(float packedCurvature) {
|
||||||
|
return abs(packedCurvature * 2 - 1) * 0.5f * parameters.curvatureInfo.y + parameters.curvatureInfo.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
<@endfunc@>
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
<$declareEvalLightmappedColor()$>
|
<$declareEvalLightmappedColor()$>
|
||||||
<$declareEvalSkyboxGlobalColor()$>
|
<$declareEvalSkyboxGlobalColor()$>
|
||||||
|
<$declareEvalSkyboxGlobalColorScattering()$>
|
||||||
|
|
||||||
in vec2 _texCoord0;
|
in vec2 _texCoord0;
|
||||||
out vec4 _fragColor;
|
out vec4 _fragColor;
|
||||||
|
@ -39,6 +40,22 @@ void main(void) {
|
||||||
frag.diffuse,
|
frag.diffuse,
|
||||||
frag.specularVal.xyz);
|
frag.specularVal.xyz);
|
||||||
_fragColor = vec4(color, 1.0);
|
_fragColor = vec4(color, 1.0);
|
||||||
|
} else if (frag.mode == FRAG_MODE_SCATTERING) {
|
||||||
|
|
||||||
|
vec4 blurredCurvature = fetchCurvature(_texCoord0);
|
||||||
|
vec4 diffusedCurvature = fetchDiffusedCurvature(_texCoord0);
|
||||||
|
|
||||||
|
vec3 color = evalSkyboxGlobalColorScattering(
|
||||||
|
getViewInverse(),
|
||||||
|
shadowAttenuation,
|
||||||
|
frag.obscurance,
|
||||||
|
frag.position.xyz,
|
||||||
|
frag.normal,
|
||||||
|
frag.diffuse,
|
||||||
|
blurredCurvature,
|
||||||
|
diffusedCurvature,
|
||||||
|
frag.roughness);
|
||||||
|
_fragColor = vec4(color, 1.0);
|
||||||
} else {
|
} else {
|
||||||
vec3 color = evalSkyboxGlobalColor(
|
vec3 color = evalSkyboxGlobalColor(
|
||||||
getViewInverse(),
|
getViewInverse(),
|
||||||
|
|
|
@ -45,6 +45,8 @@ void main(void) {
|
||||||
vec3 emissive = getMaterialEmissive(mat);
|
vec3 emissive = getMaterialEmissive(mat);
|
||||||
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
|
||||||
|
|
||||||
|
float scattering = getMaterialScattering(mat);
|
||||||
|
|
||||||
packDeferredFragment(
|
packDeferredFragment(
|
||||||
normalize(_normal.xyz),
|
normalize(_normal.xyz),
|
||||||
opacity,
|
opacity,
|
||||||
|
@ -52,5 +54,6 @@ void main(void) {
|
||||||
roughness,
|
roughness,
|
||||||
getMaterialMetallic(mat),
|
getMaterialMetallic(mat),
|
||||||
emissive,
|
emissive,
|
||||||
occlusionTex);
|
occlusionTex,
|
||||||
|
scattering);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ void main(void) {
|
||||||
vec3 viewNormal;
|
vec3 viewNormal;
|
||||||
<$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$>
|
<$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$>
|
||||||
|
|
||||||
|
float scattering = getMaterialScattering(mat);
|
||||||
|
|
||||||
packDeferredFragment(
|
packDeferredFragment(
|
||||||
viewNormal,
|
viewNormal,
|
||||||
opacity,
|
opacity,
|
||||||
|
@ -56,5 +58,6 @@ void main(void) {
|
||||||
roughness,
|
roughness,
|
||||||
getMaterialMetallic(mat),
|
getMaterialMetallic(mat),
|
||||||
emissive,
|
emissive,
|
||||||
occlusionTex);
|
occlusionTex,
|
||||||
|
scattering);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ void main(void) {
|
||||||
float metallic = getMaterialMetallic(mat);
|
float metallic = getMaterialMetallic(mat);
|
||||||
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
||||||
|
|
||||||
|
float scattering = getMaterialScattering(mat);
|
||||||
|
|
||||||
packDeferredFragment(
|
packDeferredFragment(
|
||||||
normalize(viewNormal.xyz),
|
normalize(viewNormal.xyz),
|
||||||
|
@ -60,5 +61,6 @@ void main(void) {
|
||||||
roughness,
|
roughness,
|
||||||
metallic,
|
metallic,
|
||||||
emissive,
|
emissive,
|
||||||
occlusionTex);
|
occlusionTex,
|
||||||
|
scattering);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ void main(void) {
|
||||||
float metallic = getMaterialMetallic(mat);
|
float metallic = getMaterialMetallic(mat);
|
||||||
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
|
||||||
|
|
||||||
|
float scattering = getMaterialScattering(mat);
|
||||||
|
|
||||||
packDeferredFragment(
|
packDeferredFragment(
|
||||||
normalize(_normal),
|
normalize(_normal),
|
||||||
opacity,
|
opacity,
|
||||||
|
@ -56,5 +58,6 @@ void main(void) {
|
||||||
roughness,
|
roughness,
|
||||||
metallic,
|
metallic,
|
||||||
emissive,
|
emissive,
|
||||||
occlusionTex);
|
occlusionTex,
|
||||||
|
scattering);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,6 @@ void main(void) {
|
||||||
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, specular);
|
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, specular);
|
||||||
} else {
|
} else {
|
||||||
packDeferredFragment(
|
packDeferredFragment(
|
||||||
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), length(specular), DEFAULT_EMISSIVE, DEFAULT_OCCLUSION);
|
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), length(specular), DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,5 +36,6 @@ void main(void) {
|
||||||
DEFAULT_ROUGHNESS,
|
DEFAULT_ROUGHNESS,
|
||||||
DEFAULT_METALLIC,
|
DEFAULT_METALLIC,
|
||||||
DEFAULT_EMISSIVE,
|
DEFAULT_EMISSIVE,
|
||||||
DEFAULT_OCCLUSION);
|
DEFAULT_OCCLUSION,
|
||||||
|
DEFAULT_SCATTERING);
|
||||||
}
|
}
|
|
@ -24,5 +24,5 @@ void main(void) {
|
||||||
normalize(_normal.xyz),
|
normalize(_normal.xyz),
|
||||||
1.0,
|
1.0,
|
||||||
_color.rgb,
|
_color.rgb,
|
||||||
DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION);
|
DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue