mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 14:42:19 +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);
|
||||
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) {
|
||||
material._material->setOpacity(1.0f);
|
||||
} else {
|
||||
|
|
|
@ -104,6 +104,13 @@ void Material::setMetallic(float 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) {
|
||||
if (textureMap) {
|
||||
_key.setMapChannel(channel, (true));
|
||||
|
|
|
@ -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<Schema>()._roughness; }
|
||||
|
||||
void setScattering(float scattering);
|
||||
float getScattering() const { return _schemaBuffer.get<Schema>()._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
|
||||
|
||||
|
|
|
@ -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@>
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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@>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()@>
|
||||
|
||||
|
|
|
@ -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<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;
|
||||
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>();
|
||||
_subsurfaceScatteringResource->generateScatteringTable(renderContext->args);
|
||||
}
|
||||
|
||||
setupJob.run(sceneContext, renderContext, deferredTransform, _subsurfaceScatteringResource);
|
||||
lightsJob.run(sceneContext, renderContext, deferredTransform);
|
||||
|
||||
cleanupJob.run(sceneContext, renderContext);
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include "LightStage.h"
|
||||
|
||||
#include "SubsurfaceScattering.h"
|
||||
|
||||
class RenderArgs;
|
||||
struct LightLocations;
|
||||
using LightLocationsPtr = std::shared_ptr<LightLocations>;
|
||||
|
@ -111,9 +113,9 @@ public:
|
|||
|
||||
class RenderDeferredSetup {
|
||||
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 {
|
||||
|
@ -140,6 +142,8 @@ public:
|
|||
RenderDeferredSetup setupJob;
|
||||
RenderDeferredLocals lightsJob;
|
||||
RenderDeferredCleanup cleanupJob;
|
||||
|
||||
SubsurfaceScatteringResourcePointer _subsurfaceScatteringResource;
|
||||
};
|
||||
|
||||
#endif // hifi_DeferredLightingEffect_h
|
||||
|
|
|
@ -38,26 +38,49 @@ enum ScatteringShaderMapSlots {
|
|||
|
||||
};
|
||||
|
||||
SubsurfaceScattering::SubsurfaceScattering() {
|
||||
SubsurfaceScatteringResource::SubsurfaceScatteringResource() {
|
||||
Parameters parameters;
|
||||
_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) {
|
||||
auto& params = _parametersBuffer.get<Parameters>();
|
||||
|
||||
glm::vec4 bentInfo(config.bentRed, config.bentGreen, config.bentBlue, config.bentScale);
|
||||
_scatteringResource->setBentNormalFactors(bentInfo);
|
||||
|
||||
if (bentInfo != params.normalBentInfo) {
|
||||
_parametersBuffer.edit<Parameters>().normalBentInfo = bentInfo;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<SubsurfaceScatteringResource>;
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
|
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()$>
|
||||
<$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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,5 +36,6 @@ void main(void) {
|
|||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE,
|
||||
DEFAULT_OCCLUSION);
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue