From 0c882832bf11827323e7f22a8113d7115b589a84 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 20 Jun 2016 17:58:35 -0700 Subject: [PATCH] Bringing the Scattering type to the pixels and having a different shading during the lighting pass (for global right now) --- libraries/entities-renderer/src/polyvox.slf | 2 +- libraries/fbx/src/FBXReader_Material.cpp | 4 + libraries/model/src/model/Material.cpp | 7 + libraries/model/src/model/Material.h | 27 +++- libraries/model/src/model/Material.slh | 23 +-- .../render-utils/src/DebugDeferredBuffer.cpp | 15 +- .../render-utils/src/DebugDeferredBuffer.h | 3 +- libraries/render-utils/src/DeferredBuffer.slh | 16 +- .../render-utils/src/DeferredBufferRead.slh | 20 +++ .../render-utils/src/DeferredBufferWrite.slh | 5 +- .../render-utils/src/DeferredGlobalLight.slh | 43 ++++++ .../src/DeferredLightingEffect.cpp | 145 +++++++++++------- .../render-utils/src/DeferredLightingEffect.h | 8 +- .../render-utils/src/SubsurfaceScattering.cpp | 65 +++++--- .../render-utils/src/SubsurfaceScattering.h | 61 ++++++-- .../render-utils/src/SubsurfaceScattering.slh | 45 ++++++ .../src/directional_skybox_light.slf | 17 ++ libraries/render-utils/src/model.slf | 5 +- .../render-utils/src/model_normal_map.slf | 5 +- .../src/model_normal_specular_map.slf | 4 +- .../render-utils/src/model_specular_map.slf | 5 +- libraries/render-utils/src/simple.slf | 2 +- .../render-utils/src/simple_textured.slf | 3 +- tests/gpu-test/src/unlit.slf | 2 +- 24 files changed, 405 insertions(+), 127 deletions(-) create mode 100644 libraries/render-utils/src/SubsurfaceScattering.slh diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index a77049b733..b7682913a7 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -41,5 +41,5 @@ void main(void) { vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); 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); } diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index 01878d6ccf..6ad12e4d9a 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -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) { material._material->setOpacity(1.0f); } else { diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index dbe3cabdeb..6e7968a571 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -104,6 +104,13 @@ void Material::setMetallic(float metallic) { _schemaBuffer.edit()._metallic = metallic; } +void Material::setScattering(float scattering) { + scattering = glm::clamp(scattering, 0.0f, 1.0f); + _key.setMetallic(scattering > 0.0f); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); + _schemaBuffer.edit()._scattering = scattering; +} + void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) { if (textureMap) { _key.setMapChannel(channel, (true)); diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index 8dd9dd7960..304ef2e93b 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -35,6 +35,7 @@ public: OPACITY_VAL_BIT, OPACITY_MASK_MAP_BIT, // Opacity Map and Opacity MASK map are mutually exclusive OPACITY_TRANSLUCENT_MAP_BIT, + SCATTERING_VAL_BIT, // THe map bits must be in the same sequence as the enum names for the map channels EMISSIVE_MAP_BIT, @@ -44,6 +45,7 @@ public: NORMAL_MAP_BIT, OCCLUSION_MAP_BIT, LIGHTMAP_MAP_BIT, + SCATTERING_MAP_BIT, NUM_FLAGS, }; @@ -57,6 +59,7 @@ public: NORMAL_MAP, OCCLUSION_MAP, LIGHTMAP_MAP, + SCATTERING_MAP, NUM_MAP_CHANNELS, }; @@ -83,6 +86,8 @@ public: 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& withAlbedoMap() { _flags.set(ALBEDO_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& withOcclusionMap() { _flags.set(OCCLUSION_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 static MaterialKey opaqueAlbedo() { return Builder().withAlbedo().build(); } @@ -135,7 +141,7 @@ public: void setOpacityMaskMap(bool value) { _flags.set(OPACITY_MASK_MAP_BIT, value); } bool isOpacityMaskMap() const { return _flags[OPACITY_MASK_MAP_BIT]; } - + void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); } bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; } @@ -145,6 +151,12 @@ public: void setLightmapMap(bool value) { _flags.set(LIGHTMAP_MAP_BIT, value); } 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); } 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& 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 static MaterialFilter opaqueAlbedo() { return Builder().withAlbedo().withoutTranslucentFactor().build(); } }; @@ -275,6 +294,8 @@ public: void setRoughness(float roughness); float getRoughness() const { return _schemaBuffer.get()._roughness; } + void setScattering(float scattering); + float getScattering() const { return _schemaBuffer.get()._scattering; } // Schema to access the attribute values of the material class Schema { @@ -288,7 +309,9 @@ public: glm::vec3 _fresnel{ 0.03f }; // Fresnel value for a default non 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 diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh index 4a6139c664..2faf2d8569 100644 --- a/libraries/model/src/model/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -15,7 +15,7 @@ struct Material { vec4 _emissiveOpacity; vec4 _albedoRoughness; vec4 _fresnelMetallic; - vec4 _spareKey; + vec4 _scatteringSpare2Key; }; uniform materialBuffer { @@ -37,7 +37,9 @@ float getMaterialMetallic(Material m) { return m._fresnelMetallic.a; } 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 UNLIT_VAL_BIT = 0x00000002; @@ -47,14 +49,17 @@ const int GLOSSY_VAL_BIT = 0x00000010; const int OPACITY_VAL_BIT = 0x00000020; const int OPACITY_MASK_MAP_BIT = 0x00000040; 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 METALLIC_MAP_BIT = 0x00000400; -const int ROUGHNESS_MAP_BIT = 0x00000800; -const int NORMAL_MAP_BIT = 0x00001000; -const int OCCLUSION_MAP_BIT = 0x00002000; -const int LIGHTMAP_MAP_BIT = 0x00004000; + +const int EMISSIVE_MAP_BIT = 0x00000200; +const int ALBEDO_MAP_BIT = 0x00000400; +const int METALLIC_MAP_BIT = 0x00000800; +const int ROUGHNESS_MAP_BIT = 0x00001000; +const int NORMAL_MAP_BIT = 0x00002000; +const int OCCLUSION_MAP_BIT = 0x00004000; +const int LIGHTMAP_MAP_BIT = 0x00008000; +const int SCATTERING_MAP_BIT = 0x00010000; <@endif@> diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 844eaedbb9..0e6697ae4c 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -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 { "vec4 getFragmentColor() {" " 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() {" " return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 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; case LightmapMode: return DEFAULT_LIGHTMAP_SHADER; + case ScatteringMode: + return DEFAULT_SCATTERING_SHADER; case LightingMode: return DEFAULT_LIGHTING_SHADER; case ShadowMode: @@ -253,8 +262,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust return DEFAULT_DIFFUSED_CURVATURE_SHADER; case DiffusedNormalCurvatureMode: return DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER; - case ScatteringMode: - return DEFAULT_SCATTERING_SHADER; + case ScatteringDebugMode: + return DEFAULT_DEBUG_SCATTERING_SHADER; case AmbientOcclusionMode: return DEFAULT_AMBIENT_OCCLUSION_SHADER; case AmbientOcclusionBlurredMode: diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index e1d76e1f71..61ebec8954 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -57,6 +57,7 @@ protected: UnlitMode, OcclusionMode, LightmapMode, + ScatteringMode, LightingMode, ShadowMode, PyramidDepthMode, @@ -64,7 +65,7 @@ protected: NormalCurvatureMode, DiffusedCurvatureMode, DiffusedNormalCurvatureMode, - ScatteringMode, + ScatteringDebugMode, AmbientOcclusionMode, AmbientOcclusionBlurredMode, CustomMode // Needs to stay last diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index b9c65a3bff..5f80354585 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -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_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_SHADED = 1; const int FRAG_MODE_LIGHTMAPPED = 2; +const int FRAG_MODE_SCATTERING = 3; void unpackModeMetallic(float rawValue, out int mode, out float 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); } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) { 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) { mode = FRAG_MODE_UNLIT; metallic = 0.0; @@ -47,6 +55,10 @@ float packLightmappedMetallic(float 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() { return FRAG_PACK_UNLIT; } diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index ffa1cc4771..cabfe001c7 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -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@> diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index e869f32dc6..71236c71ad 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -30,13 +30,14 @@ const float DEFAULT_METALLIC = 0; const vec3 DEFAULT_SPECULAR = vec3(0.1); const vec3 DEFAULT_EMISSIVE = vec3(0.0); const float DEFAULT_OCCLUSION = 1.0; +const float DEFAULT_SCATTERING = 0.0; 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) { 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)); _fragColor2 = vec4(emissive, occlusion); } diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index d29c8bea87..bfab0fafb8 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -152,6 +152,49 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur <@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()@> diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index f70b68b4f0..3e2607413e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -41,13 +41,14 @@ using namespace render; struct LightLocations { - int radius; - int ambientSphere; - int lightBufferUnit; - int sphereParam; - int coneParam; - int deferredFrameTransformBuffer; - int shadowTransformBuffer; + int radius{ -1 }; + int ambientSphere{ -1 }; + int lightBufferUnit{ -1 }; + int sphereParam{ -1 }; + int coneParam{ -1 }; + int deferredFrameTransformBuffer{ -1 }; + int subsurfaceScatteringParametersBuffer{ -1 }; + int shadowTransformBuffer{ -1 }; }; enum DeferredShader_MapSlot { @@ -58,10 +59,14 @@ enum DeferredShader_MapSlot { DEFERRED_BUFFER_OBSCURANCE_UNIT = 4, SHADOW_MAP_UNIT = 5, SKYBOX_MAP_UNIT = 6, + DEFERRED_BUFFER_CURVATURE_UNIT, + DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, + SCATTERING_LUT_UNIT, }; enum DeferredShader_BufferSlot { - DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT = 2, - LIGHT_GPU_SLOT = 3, + DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT = 0, + SCATTERING_PARAMETERS_BUFFER_SLOT, + LIGHT_GPU_SLOT, }; 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("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("subsurfaceScatteringParametersBuffer"), SCATTERING_PARAMETERS_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); 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->deferredFrameTransformBuffer = program->getBuffers().findLocation("deferredFrameTransformBuffer"); + locations->subsurfaceScatteringParametersBuffer = program->getBuffers().findLocation("subsurfaceScatteringParametersBuffer"); locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer"); auto state = std::make_shared(); @@ -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; 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 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()); + // 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 - { - 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); + 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); + + 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_DEPTH_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); }); @@ -582,7 +606,12 @@ void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext, void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const DeferredFrameTransformPointer& deferredTransform) { - setupJob.run(sceneContext, renderContext, deferredTransform); + if (!_subsurfaceScatteringResource) { + _subsurfaceScatteringResource = std::make_shared(); + _subsurfaceScatteringResource->generateScatteringTable(renderContext->args); + } + + setupJob.run(sceneContext, renderContext, deferredTransform, _subsurfaceScatteringResource); lightsJob.run(sceneContext, renderContext, deferredTransform); cleanupJob.run(sceneContext, renderContext); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index c88242bdc5..da59a98e37 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -27,6 +27,8 @@ #include "LightStage.h" +#include "SubsurfaceScattering.h" + class RenderArgs; struct LightLocations; using LightLocationsPtr = std::shared_ptr; @@ -111,9 +113,9 @@ public: class RenderDeferredSetup { public: - using JobModel = render::Job::ModelI; + // using JobModel = render::Job::ModelI; - 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 { @@ -140,6 +142,8 @@ public: RenderDeferredSetup setupJob; RenderDeferredLocals lightsJob; RenderDeferredCleanup cleanupJob; + + SubsurfaceScatteringResourcePointer _subsurfaceScatteringResource; }; #endif // hifi_DeferredLightingEffect_h diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index 2d2769ad0b..25df2c388b 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -38,26 +38,49 @@ enum ScatteringShaderMapSlots { }; -SubsurfaceScattering::SubsurfaceScattering() { +SubsurfaceScatteringResource::SubsurfaceScatteringResource() { Parameters parameters; _parametersBuffer = gpu::BufferView(std::make_shared(sizeof(Parameters), (const gpu::Byte*) ¶meters)); + +} + +void SubsurfaceScatteringResource::setBentNormalFactors(const glm::vec4& rgbsBentFactors) { + if (rgbsBentFactors != getBentNormalFactors()) { + _parametersBuffer.edit().normalBentInfo = rgbsBentFactors; + } +} + +glm::vec4 SubsurfaceScatteringResource::getBentNormalFactors() const { + return _parametersBuffer.get().normalBentInfo; +} + +void SubsurfaceScatteringResource::setCurvatureFactors(const glm::vec2& sbCurvatureFactors) { + if (sbCurvatureFactors != getCurvatureFactors()) { + _parametersBuffer.edit().curvatureInfo = sbCurvatureFactors; + } +} + +glm::vec2 SubsurfaceScatteringResource::getCurvatureFactors() const { + return _parametersBuffer.get().curvatureInfo; +} + +void SubsurfaceScatteringResource::generateScatteringTable(RenderArgs* args) { + if (!_scatteringTable) { + _scatteringTable = generatePreIntegratedScattering(args); + } +} + +SubsurfaceScattering::SubsurfaceScattering() { + _scatteringResource = std::make_shared(); } void SubsurfaceScattering::configure(const Config& config) { - auto& params = _parametersBuffer.get(); glm::vec4 bentInfo(config.bentRed, config.bentGreen, config.bentBlue, config.bentScale); + _scatteringResource->setBentNormalFactors(bentInfo); - if (bentInfo != params.normalBentInfo) { - _parametersBuffer.edit().normalBentInfo = bentInfo; - } - - if (config.curvatureOffset != params.curvatureInfo.x) { - _parametersBuffer.edit().curvatureInfo.x = config.curvatureOffset; - } - if (config.curvatureScale != params.curvatureInfo.y) { - _parametersBuffer.edit().curvatureInfo.y = config.curvatureScale; - } + glm::vec2 curvatureInfo(config.curvatureOffset, config.curvatureScale); + _scatteringResource->setCurvatureFactors(curvatureInfo); _showLUT = config.showLUT; } @@ -164,9 +187,8 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext, RenderArgs* args = renderContext->args; - if (!_scatteringTable) { - _scatteringTable = SubsurfaceScattering::generatePreIntegratedScattering(args); - } + _scatteringResource->generateScatteringTable(args); + auto scatteringTable = _scatteringResource->getScatteringTable(); auto pipeline = getScatteringPipeline(); @@ -194,14 +216,14 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext, batch.setPipeline(pipeline); batch.setUniformBuffer(ScatteringTask_FrameTransformSlot, frameTransform->getFrameTransformBuffer()); - batch.setUniformBuffer(ScatteringTask_ParamSlot, _parametersBuffer); + batch.setUniformBuffer(ScatteringTask_ParamSlot, _scatteringResource->getParametersBuffer()); if (theLight->light) { batch.setUniformBuffer(ScatteringTask_LightSlot, theLight->light->getSchemaBuffer()); if (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_DiffusedCurvatureMapSlot, diffusedFramebuffer->getRenderBuffer(0)); 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; batch.setViewportTransform(glm::ivec4(0, 0, viewportSize, viewportSize)); batch.setPipeline(getShowLUTPipeline()); - batch.setResourceTexture(0, _scatteringTable); + batch.setResourceTexture(0, scatteringTable); 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()); } +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))); diffuseProfile(profileMap); const int WIDTH = 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))); - diffuseScatter(scatteringLUT); + diffuseScatter(scatteringLUT); //diffuseScatterGPU(profileMap, scatteringLUT, args); return scatteringLUT; } - diff --git a/libraries/render-utils/src/SubsurfaceScattering.h b/libraries/render-utils/src/SubsurfaceScattering.h index 4322379e57..c0ce14cc8c 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.h +++ b/libraries/render-utils/src/SubsurfaceScattering.h @@ -17,6 +17,49 @@ #include "render/DrawTask.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; + + + class SubsurfaceScatteringConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(float bentRed MEMBER bentRed NOTIFY dirty) @@ -57,24 +100,8 @@ public: void configure(const Config& config); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, gpu::FramebufferPointer& scatteringFramebuffer); - static gpu::TexturePointer generatePreIntegratedScattering(RenderArgs* args); - private: - typedef gpu::BufferView UniformBufferView; - - // 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; - + SubsurfaceScatteringResourcePointer _scatteringResource; bool updateScatteringFramebuffer(const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& scatteringFramebuffer); gpu::FramebufferPointer _scatteringFramebuffer; diff --git a/libraries/render-utils/src/SubsurfaceScattering.slh b/libraries/render-utils/src/SubsurfaceScattering.slh new file mode 100644 index 0000000000..985d3d5404 --- /dev/null +++ b/libraries/render-utils/src/SubsurfaceScattering.slh @@ -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@> diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index 074ee90fca..544271d20d 100755 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -17,6 +17,7 @@ <$declareEvalLightmappedColor()$> <$declareEvalSkyboxGlobalColor()$> +<$declareEvalSkyboxGlobalColorScattering()$> in vec2 _texCoord0; out vec4 _fragColor; @@ -39,6 +40,22 @@ void main(void) { frag.diffuse, frag.specularVal.xyz); _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 { vec3 color = evalSkyboxGlobalColor( getViewInverse(), diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index c1f5cb1f88..daeead65ec 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -45,6 +45,8 @@ void main(void) { vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + float scattering = getMaterialScattering(mat); + packDeferredFragment( normalize(_normal.xyz), opacity, @@ -52,5 +54,6 @@ void main(void) { roughness, getMaterialMetallic(mat), emissive, - occlusionTex); + occlusionTex, + scattering); } diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index daaa1ed977..e6baac4e04 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -49,6 +49,8 @@ void main(void) { vec3 viewNormal; <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$> + float scattering = getMaterialScattering(mat); + packDeferredFragment( viewNormal, opacity, @@ -56,5 +58,6 @@ void main(void) { roughness, getMaterialMetallic(mat), emissive, - occlusionTex); + occlusionTex, + scattering); } diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf index dd2d3cc951..d5dd607b8f 100755 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ b/libraries/render-utils/src/model_normal_specular_map.slf @@ -52,6 +52,7 @@ void main(void) { float metallic = getMaterialMetallic(mat); <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + float scattering = getMaterialScattering(mat); packDeferredFragment( normalize(viewNormal.xyz), @@ -60,5 +61,6 @@ void main(void) { roughness, metallic, emissive, - occlusionTex); + occlusionTex, + scattering); } diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index f0fe20293c..47b5e3389d 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -49,6 +49,8 @@ void main(void) { float metallic = getMaterialMetallic(mat); <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + float scattering = getMaterialScattering(mat); + packDeferredFragment( normalize(_normal), opacity, @@ -56,5 +58,6 @@ void main(void) { roughness, metallic, emissive, - occlusionTex); + occlusionTex, + scattering); } diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 0f848ee231..4a16c1c46a 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -54,6 +54,6 @@ void main(void) { normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, specular); } else { 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); } } diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 062fb96f7d..f045af2ce5 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -36,5 +36,6 @@ void main(void) { DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION); + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); } \ No newline at end of file diff --git a/tests/gpu-test/src/unlit.slf b/tests/gpu-test/src/unlit.slf index f88fcb510b..71954489af 100644 --- a/tests/gpu-test/src/unlit.slf +++ b/tests/gpu-test/src/unlit.slf @@ -24,5 +24,5 @@ void main(void) { normalize(_normal.xyz), 1.0, _color.rgb, - DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION); + DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING); }