From 6831710efb0dc29947470a6d89edb95691dc339c Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 9 Jun 2016 19:13:28 -0700 Subject: [PATCH] Adding the deawSCattering pass --- .../render-utils/src/SubsurfaceScattering.cpp | 35 +++--- .../subsurfaceScattering_drawScattering.slf | 114 ++++++++++++++++++ .../src/subsurfaceScattering_makeLUT.slf | 17 +-- 3 files changed, 144 insertions(+), 22 deletions(-) create mode 100644 libraries/render-utils/src/subsurfaceScattering_drawScattering.slf diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index b0d0e9a38e..d6543bfc1d 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -16,11 +16,13 @@ #include "FramebufferCache.h" #include "subsurfaceScattering_makeLUT_frag.h" +#include "subsurfaceScattering_drawScattering_frag.h" const int SubsurfaceScattering_FrameTransformSlot = 0; const int SubsurfaceScattering_ParamsSlot = 1; -const int SubsurfaceScattering_DepthMapSlot = 0; +const int SubsurfaceScattering_CurvatureMapSlot = 0; const int SubsurfaceScattering_NormalMapSlot = 1; +const int SubsurfaceScattering_ScatteringTableSlot = 2; SubsurfaceScattering::SubsurfaceScattering() { Parameters parameters; @@ -39,12 +41,17 @@ void SubsurfaceScattering::configure(const Config& config) { gpu::PipelinePointer SubsurfaceScattering::getScatteringPipeline() { if (!_scatteringPipeline) { auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); - auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); + // auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); + auto ps = gpu::Shader::createPixel(std::string(subsurfaceScattering_drawScattering_frag)); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - // slotBindings.insert(gpu::Shader::Binding(std::string("blurParamsBuffer"), BlurTask_ParamsSlot)); - // slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), BlurTask_SourceSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), SubsurfaceScattering_FrameTransformSlot)); + // slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), BlurTask_SourceSlot)); + + slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), SubsurfaceScattering_CurvatureMapSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), SubsurfaceScattering_NormalMapSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), SubsurfaceScattering_ScatteringTableSlot)); gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -71,25 +78,23 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext, auto pipeline = getScatteringPipeline(); + auto framebufferCache = DependencyManager::get(); +// if (curvatureFramebuffer->getRenderBuffer(0)) gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); batch.setViewportTransform(args->_viewport >> 1); - /* batch.setProjectionTransform(glm::mat4()); - batch.setViewTransform(Transform()); - Transform model; - model.setTranslation(glm::vec3(sMin, tMin, 0.0f)); - model.setScale(glm::vec3(sWidth, tHeight, 1.0f)); - batch.setModelTransform(model);*/ + batch.setUniformBuffer(SubsurfaceScattering_FrameTransformSlot, frameTransform->getFrameTransformBuffer()); batch.setPipeline(pipeline); - batch.setResourceTexture(0, _scatteringTable); + batch.setResourceTexture(SubsurfaceScattering_NormalMapSlot, framebufferCache->getDeferredNormalTexture()); + batch.setResourceTexture(SubsurfaceScattering_CurvatureMapSlot, framebufferCache->getCurvatureTexture()); + batch.setResourceTexture(SubsurfaceScattering_ScatteringTableSlot, _scatteringTable); batch.draw(gpu::TRIANGLE_STRIP, 4); }); - } @@ -144,7 +149,7 @@ vec3 integrate(double cosTheta, double skinRadius) { double a = -(_PI); - double inc = 0.1; + double inc = 0.01; while (a <= (_PI)) { double sampleAngle = theta + a; @@ -302,8 +307,8 @@ gpu::TexturePointer SubsurfaceScattering::generatePreIntegratedScattering(Render const int WIDTH = 128; const int HEIGHT = 128; auto scatteringLUT = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, WIDTH, HEIGHT)); - // diffuseScatter(scatteringLUT); - diffuseScatterGPU(profileMap, scatteringLUT, args); + diffuseScatter(scatteringLUT); + //diffuseScatterGPU(profileMap, scatteringLUT, args); return scatteringLUT; } diff --git a/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf b/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf new file mode 100644 index 0000000000..28d7867e51 --- /dev/null +++ b/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf @@ -0,0 +1,114 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// 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 +// + + +<@include DeferredTransform.slh@> +<$declareDeferredFrameTransform()$> + + + + +vec2 signNotZero(vec2 v) { + return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0); +} + +vec3 oct_to_float32x3(in vec2 e) { + vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + if (v.z < 0) { + v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy); + } + return normalize(v); +} + +vec2 unorm8x3_to_snorm12x2(vec3 u) { + u *= 255.0; + u.y *= (1.0 / 16.0); + vec2 s = vec2( u.x * 16.0 + floor(u.y), + fract(u.y) * (16.0 * 256.0) + u.z); + return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0)); +} +vec3 unpackNormal(in vec3 p) { + return oct_to_float32x3(unorm8x3_to_snorm12x2(p)); +} + +vec2 sideToFrameTexcoord(vec2 side, vec2 texcoordPos) { + return vec2((texcoordPos.x + side.x) * side.y, texcoordPos.y); +} + +uniform sampler2D normalMap; + +vec3 getRawNormal(vec2 texcoord) { + return texture(normalMap, texcoord).xyz; +} + +vec3 getWorldNormal(vec2 texcoord) { + vec3 rawNormal = getRawNormal(texcoord); + return unpackNormal(rawNormal); +} + + +// the curvature texture +uniform sampler2D curvatureMap; + +vec4 fetchCurvature(vec2 texcoord) { + return texture(curvatureMap, texcoord); +} + + +uniform sampler2D scatteringLUT; + +vec3 fetchBRDF(float curvature, float LdotN) { + return texture(scatteringLUT, vec2(curvature, LdotN)).xyz; +} + +// Scattering parameters +float normalBendFactor = 1.0f; +float normalBendR = 1.5f; +float normalBendG = 0.8f; +float normalBendB = 0.3f; +float scatterBase = 0.012f; +float scatterCurve = 0.25f; + +in vec2 varTexCoord0; +out vec4 _fragColor; + +void main(void) { + // DeferredTransform deferredTransform = getDeferredTransform(); + // DeferredFragment frag = unpackDeferredFragment(deferredTransform, varTexCoord0); + + vec3 normal = getWorldNormal(varTexCoord0); + vec4 diffusedCurvature = fetchCurvature(varTexCoord0); + + // --> Calculate bent normals. + vec3 bentNormalN = normal; + vec3 bentNormalR = normalize( (diffusedCurvature.xyz - 0.5f) * 2.0f ); + float curvature = abs(diffusedCurvature.w * 2 - 1) * 0.5f * scatterCurve + scatterBase; + + // --> Calculate the light vector. + vec3 lightVector = normalize(vec3(-1.0f, -1.0f, -1.0f)); //normalize(lightPos - sourcePos.xyz); + + + // --> Optimise for skin diffusion profile. + float diffuseBlendedR = dot(normalize(mix( bentNormalN.xyz, bentNormalN, normalBendR * normalBendFactor)), lightVector); + float diffuseBlendedG = dot(normalize(mix(normal.xyz, bentNormalN, normalBendG * normalBendFactor)), lightVector); + float diffuseBlendedB = dot(normalize(mix(normal.xyz, bentNormalN, normalBendB * normalBendFactor)), lightVector); + + + // --> Look up the pre-integrated curvature-dependent BDRF textures + vec3 bdrfR = fetchBRDF(diffuseBlendedR, curvature); + vec3 bdrfG = fetchBRDF(diffuseBlendedG, curvature); + vec3 bdrfB = fetchBRDF(diffuseBlendedB, curvature); + vec3 bdrf = vec3( bdrfR.x, bdrfG.y, bdrfB.z); + bdrf *= bdrf; + _fragColor = vec4(vec3(bdrf.xyz), 1.0); +} + + diff --git a/libraries/render-utils/src/subsurfaceScattering_makeLUT.slf b/libraries/render-utils/src/subsurfaceScattering_makeLUT.slf index e008c52385..90c7bfbf4e 100644 --- a/libraries/render-utils/src/subsurfaceScattering_makeLUT.slf +++ b/libraries/render-utils/src/subsurfaceScattering_makeLUT.slf @@ -10,7 +10,7 @@ // -#define _PI 3.14159265358979523846 +const float _PI = 3.14159265358979523846; uniform sampler2D profileMap; @@ -25,7 +25,6 @@ vec3 integrate(float cosTheta, float skinRadius) { float theta = acos(cosTheta); vec3 totalWeights = vec3(0.0); vec3 totalLight= vec3(0.0); - vec3 skinColour = vec3(1.0); float a = -(_PI); @@ -33,7 +32,9 @@ vec3 integrate(float cosTheta, float skinRadius) { while (a <= (_PI)) { float sampleAngle = theta + a; - float diffuse = clamp(cos(sampleAngle), 0.0, 1.0); + float diffuse = cos(sampleAngle); + if (diffuse < 0.0) diffuse = 0.0; + if (diffuse > 1.0) diffuse = 1.0; // Distance. float sampleDist = abs(2.0 * skinRadius * sin(a * 0.5)); @@ -42,13 +43,15 @@ vec3 integrate(float cosTheta, float skinRadius) { vec3 weights = scatter(sampleDist); totalWeights += weights; - totalLight += diffuse * weights /** (skinColour * skinColour)*/; + totalLight += diffuse * weights; a += inc; } - vec3 result = sqrt(totalLight / totalWeights); + vec3 result = (totalLight / totalWeights); - return min(result, vec3(1.0)); + return min(sqrt(result), vec3(1.0)); + + return scatter(skinRadius); } in vec2 varTexCoord0; @@ -56,6 +59,6 @@ out vec4 outFragColor; void main(void) { - outFragColor = vec4(integrate(varTexCoord0.x * 2.0 - 1, 2.0 * varTexCoord0.y), 1.0); + outFragColor = vec4(integrate(varTexCoord0.x * 2.0 - 1.0, 2.0 / varTexCoord0.y), 1.0); }