mirror of
https://github.com/overte-org/overte.git
synced 2025-07-24 00:24:00 +02:00
introducing the depth aware blur
This commit is contained in:
parent
938bc77b1f
commit
197d49fc03
12 changed files with 247 additions and 140 deletions
|
@ -159,7 +159,7 @@ static const std::string DEFAULT_CURVATURE_SHADER{
|
||||||
static const std::string DEFAULT_NORMAL_CURVATURE_SHADER{
|
static const std::string DEFAULT_NORMAL_CURVATURE_SHADER{
|
||||||
"vec4 getFragmentColor() {"
|
"vec4 getFragmentColor() {"
|
||||||
//" return vec4(pow(vec3(texture(curvatureMap, uv).a), vec3(1.0 / 2.2)), 1.0);"
|
//" return vec4(pow(vec3(texture(curvatureMap, uv).a), vec3(1.0 / 2.2)), 1.0);"
|
||||||
" return vec4(pow(vec3(texture(curvatureMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);"
|
" return vec4(vec3(texture(curvatureMap, uv).xyz), 1.0);"
|
||||||
//" return vec4(vec3(1.0 - textureLod(pyramidMap, uv, 3).x * 0.01), 1.0);"
|
//" return vec4(vec3(1.0 - textureLod(pyramidMap, uv, 3).x * 0.01), 1.0);"
|
||||||
" }"
|
" }"
|
||||||
};
|
};
|
||||||
|
@ -175,7 +175,7 @@ static const std::string DEFAULT_DIFFUSED_CURVATURE_SHADER{
|
||||||
static const std::string DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER{
|
static const std::string DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER{
|
||||||
"vec4 getFragmentColor() {"
|
"vec4 getFragmentColor() {"
|
||||||
//" return vec4(pow(vec3(texture(curvatureMap, uv).a), vec3(1.0 / 2.2)), 1.0);"
|
//" return vec4(pow(vec3(texture(curvatureMap, uv).a), vec3(1.0 / 2.2)), 1.0);"
|
||||||
" return vec4(pow(vec3(texture(diffusedCurvatureMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);"
|
" return vec4(vec3(texture(diffusedCurvatureMap, uv).xyz), 1.0);"
|
||||||
//" return vec4(vec3(1.0 - textureLod(pyramidMap, uv, 3).x * 0.01), 1.0);"
|
//" return vec4(vec3(1.0 - textureLod(pyramidMap, uv, 3).x * 0.01), 1.0);"
|
||||||
" }"
|
" }"
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,7 +108,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
|
||||||
|
|
||||||
const auto theCurvatureVarying = curvatureFramebufferAndDepth[0];
|
const auto theCurvatureVarying = curvatureFramebufferAndDepth[0];
|
||||||
|
|
||||||
#define SIMPLE_BLUR 1
|
//#define SIMPLE_BLUR 1
|
||||||
#if SIMPLE_BLUR
|
#if SIMPLE_BLUR
|
||||||
const auto curvatureFramebuffer = addJob<render::BlurGaussian>("DiffuseCurvature", curvatureFramebufferAndDepth.get<SurfaceGeometryPass::Outputs>().first);
|
const auto curvatureFramebuffer = addJob<render::BlurGaussian>("DiffuseCurvature", curvatureFramebufferAndDepth.get<SurfaceGeometryPass::Outputs>().first);
|
||||||
const auto diffusedCurvatureFramebuffer = addJob<render::BlurGaussian>("DiffuseCurvature2", curvatureFramebufferAndDepth.get<SurfaceGeometryPass::Outputs>().first, true);
|
const auto diffusedCurvatureFramebuffer = addJob<render::BlurGaussian>("DiffuseCurvature2", curvatureFramebufferAndDepth.get<SurfaceGeometryPass::Outputs>().first, true);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "DeferredLightingEffect.h"
|
#include "DeferredLightingEffect.h"
|
||||||
|
|
||||||
|
#include "subsurfaceScattering_makeProfile_frag.h"
|
||||||
#include "subsurfaceScattering_makeLUT_frag.h"
|
#include "subsurfaceScattering_makeLUT_frag.h"
|
||||||
#include "subsurfaceScattering_drawScattering_frag.h"
|
#include "subsurfaceScattering_drawScattering_frag.h"
|
||||||
|
|
||||||
|
@ -85,8 +86,11 @@ bool SubsurfaceScatteringResource::isShowBRDF() const {
|
||||||
|
|
||||||
|
|
||||||
void SubsurfaceScatteringResource::generateScatteringTable(RenderArgs* args) {
|
void SubsurfaceScatteringResource::generateScatteringTable(RenderArgs* args) {
|
||||||
|
if (!_scatteringProfile) {
|
||||||
|
_scatteringProfile = generateScatteringProfile(args);
|
||||||
|
}
|
||||||
if (!_scatteringTable) {
|
if (!_scatteringTable) {
|
||||||
_scatteringTable = generatePreIntegratedScattering(args);
|
_scatteringTable = generatePreIntegratedScattering(_scatteringProfile, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +106,7 @@ void SubsurfaceScattering::configure(const Config& config) {
|
||||||
glm::vec2 curvatureInfo(config.curvatureOffset, config.curvatureScale);
|
glm::vec2 curvatureInfo(config.curvatureOffset, config.curvatureScale);
|
||||||
_scatteringResource->setCurvatureFactors(curvatureInfo);
|
_scatteringResource->setCurvatureFactors(curvatureInfo);
|
||||||
|
|
||||||
|
_showProfile = config.showProfile;
|
||||||
_showLUT = config.showLUT;
|
_showLUT = config.showLUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +213,7 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext,
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
||||||
_scatteringResource->generateScatteringTable(args);
|
_scatteringResource->generateScatteringTable(args);
|
||||||
|
auto scatteringProfile = _scatteringResource->getScatteringProfile();
|
||||||
auto scatteringTable = _scatteringResource->getScatteringTable();
|
auto scatteringTable = _scatteringResource->getScatteringTable();
|
||||||
|
|
||||||
|
|
||||||
|
@ -227,7 +233,7 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext,
|
||||||
const auto theLight = DependencyManager::get<DeferredLightingEffect>()->getLightStage().lights[0];
|
const auto theLight = DependencyManager::get<DeferredLightingEffect>()->getLightStage().lights[0];
|
||||||
|
|
||||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||||
batch.enableStereo(false);
|
// batch.enableStereo(false);
|
||||||
|
|
||||||
batch.setViewportTransform(args->_viewport);
|
batch.setViewportTransform(args->_viewport);
|
||||||
|
|
||||||
|
@ -252,9 +258,18 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext,
|
||||||
|
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
*/
|
*/
|
||||||
|
auto viewportSize = std::min(args->_viewport.z, args->_viewport.w) >> 1;
|
||||||
|
auto offsetViewport = viewportSize * 0.1;
|
||||||
|
|
||||||
|
if (_showProfile) {
|
||||||
|
batch.setViewportTransform(glm::ivec4(0, 0, viewportSize, offsetViewport));
|
||||||
|
batch.setPipeline(getShowLUTPipeline());
|
||||||
|
batch.setResourceTexture(0, scatteringProfile);
|
||||||
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
}
|
||||||
|
|
||||||
if (_showLUT) {
|
if (_showLUT) {
|
||||||
auto viewportSize = std::min(args->_viewport.z, args->_viewport.w) >> 1;
|
batch.setViewportTransform(glm::ivec4(0, offsetViewport * 1.5, viewportSize, viewportSize));
|
||||||
batch.setViewportTransform(glm::ivec4(0, 0, viewportSize, viewportSize));
|
|
||||||
batch.setPipeline(getShowLUTPipeline());
|
batch.setPipeline(getShowLUTPipeline());
|
||||||
batch.setResourceTexture(0, scatteringTable);
|
batch.setResourceTexture(0, scatteringTable);
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
@ -267,7 +282,6 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext,
|
||||||
|
|
||||||
|
|
||||||
// Reference: http://www.altdevblogaday.com/2011/12/31/skin-shading-in-unity3d/
|
// Reference: http://www.altdevblogaday.com/2011/12/31/skin-shading-in-unity3d/
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -276,7 +290,6 @@ void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext,
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
double gaussian(float v, float r) {
|
double gaussian(float v, float r) {
|
||||||
double g = (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));
|
double g = (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));
|
||||||
return g;
|
return g;
|
||||||
|
@ -385,45 +398,6 @@ void diffuseScatter(gpu::TexturePointer& lut) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void diffuseScatterGPU(gpu::TexturePointer& profileMap, gpu::TexturePointer& lut, RenderArgs* args) {
|
|
||||||
int width = lut->getWidth();
|
|
||||||
int height = lut->getHeight();
|
|
||||||
|
|
||||||
gpu::PipelinePointer makePipeline;
|
|
||||||
{
|
|
||||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
|
||||||
auto ps = gpu::Shader::createPixel(std::string(subsurfaceScattering_makeLUT_frag));
|
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("profileMap"), 0));
|
|
||||||
// slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), BlurTask_SourceSlot));
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
|
||||||
|
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
|
||||||
|
|
||||||
makePipeline = gpu::Pipeline::create(program, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
|
||||||
makeFramebuffer->setRenderBuffer(0, lut);
|
|
||||||
|
|
||||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
|
||||||
batch.enableStereo(false);
|
|
||||||
|
|
||||||
batch.setViewportTransform(glm::ivec4(0, 0, width, height));
|
|
||||||
|
|
||||||
batch.setFramebuffer(makeFramebuffer);
|
|
||||||
batch.setPipeline(makePipeline);
|
|
||||||
batch.setResourceTexture(0, profileMap);
|
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
|
||||||
batch.setResourceTexture(0, nullptr);
|
|
||||||
batch.setPipeline(nullptr);
|
|
||||||
batch.setFramebuffer(nullptr);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void diffuseProfile(gpu::TexturePointer& profile) {
|
void diffuseProfile(gpu::TexturePointer& profile) {
|
||||||
int width = profile->getWidth();
|
int width = profile->getWidth();
|
||||||
int height = profile->getHeight();
|
int height = profile->getHeight();
|
||||||
|
@ -459,15 +433,95 @@ void diffuseProfile(gpu::TexturePointer& profile) {
|
||||||
profile->assignStoredMip(0, gpu::Element::COLOR_RGBA_32, bytes.size(), bytes.data());
|
profile->assignStoredMip(0, gpu::Element::COLOR_RGBA_32, bytes.size(), bytes.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer SubsurfaceScatteringResource::generatePreIntegratedScattering(RenderArgs* args) {
|
void diffuseProfileGPU(gpu::TexturePointer& profileMap, RenderArgs* args) {
|
||||||
|
int width = profileMap->getWidth();
|
||||||
|
int height = profileMap->getHeight();
|
||||||
|
|
||||||
auto profileMap = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, 256, 1, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
gpu::PipelinePointer makePipeline;
|
||||||
diffuseProfile(profileMap);
|
{
|
||||||
|
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||||
|
auto ps = gpu::Shader::createPixel(std::string(subsurfaceScattering_makeProfile_frag));
|
||||||
|
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||||
|
|
||||||
const int WIDTH = 128;
|
gpu::Shader::BindingSet slotBindings;
|
||||||
const int HEIGHT = 128;
|
//slotBindings.insert(gpu::Shader::Binding(std::string("profileMap"), 0));
|
||||||
auto scatteringLUT = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_SRGBA_32, WIDTH, HEIGHT, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
// slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), BlurTask_SourceSlot));
|
||||||
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
|
||||||
|
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||||
|
|
||||||
|
makePipeline = gpu::Pipeline::create(program, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||||
|
makeFramebuffer->setRenderBuffer(0, profileMap);
|
||||||
|
|
||||||
|
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||||
|
batch.enableStereo(false);
|
||||||
|
|
||||||
|
batch.setViewportTransform(glm::ivec4(0, 0, width, height));
|
||||||
|
|
||||||
|
batch.setFramebuffer(makeFramebuffer);
|
||||||
|
batch.setPipeline(makePipeline);
|
||||||
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
batch.setResourceTexture(0, nullptr);
|
||||||
|
batch.setPipeline(nullptr);
|
||||||
|
batch.setFramebuffer(nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void diffuseScatterGPU(const gpu::TexturePointer& profileMap, gpu::TexturePointer& lut, RenderArgs* args) {
|
||||||
|
int width = lut->getWidth();
|
||||||
|
int height = lut->getHeight();
|
||||||
|
|
||||||
|
gpu::PipelinePointer makePipeline;
|
||||||
|
{
|
||||||
|
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||||
|
auto ps = gpu::Shader::createPixel(std::string(subsurfaceScattering_makeLUT_frag));
|
||||||
|
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||||
|
|
||||||
|
gpu::Shader::BindingSet slotBindings;
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringProfile"), 0));
|
||||||
|
// slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), BlurTask_SourceSlot));
|
||||||
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
|
||||||
|
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||||
|
|
||||||
|
makePipeline = gpu::Pipeline::create(program, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||||
|
makeFramebuffer->setRenderBuffer(0, lut);
|
||||||
|
|
||||||
|
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||||
|
batch.enableStereo(false);
|
||||||
|
|
||||||
|
batch.setViewportTransform(glm::ivec4(0, 0, width, height));
|
||||||
|
|
||||||
|
batch.setFramebuffer(makeFramebuffer);
|
||||||
|
batch.setPipeline(makePipeline);
|
||||||
|
batch.setResourceTexture(0, profileMap);
|
||||||
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
batch.setResourceTexture(0, nullptr);
|
||||||
|
batch.setPipeline(nullptr);
|
||||||
|
batch.setFramebuffer(nullptr);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer SubsurfaceScatteringResource::generateScatteringProfile(RenderArgs* args) {
|
||||||
|
const int PROFILE_RESOLUTION = 512;
|
||||||
|
auto profileMap = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_SRGBA_32, PROFILE_RESOLUTION, 1, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
|
diffuseProfileGPU(profileMap, args);
|
||||||
|
return profileMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer SubsurfaceScatteringResource::generatePreIntegratedScattering(const gpu::TexturePointer& profile, RenderArgs* args) {
|
||||||
|
|
||||||
|
const int TABLE_RESOLUTION = 512;
|
||||||
|
auto scatteringLUT = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_SRGBA_32, TABLE_RESOLUTION, TABLE_RESOLUTION, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
//diffuseScatter(scatteringLUT);
|
//diffuseScatter(scatteringLUT);
|
||||||
diffuseScatterGPU(profileMap, scatteringLUT, args);
|
diffuseScatterGPU(profile, scatteringLUT, args);
|
||||||
return scatteringLUT;
|
return scatteringLUT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,12 @@ public:
|
||||||
|
|
||||||
UniformBufferView getParametersBuffer() const { return _parametersBuffer; }
|
UniformBufferView getParametersBuffer() const { return _parametersBuffer; }
|
||||||
|
|
||||||
|
gpu::TexturePointer getScatteringProfile() const { return _scatteringProfile; }
|
||||||
gpu::TexturePointer getScatteringTable() const { return _scatteringTable; }
|
gpu::TexturePointer getScatteringTable() const { return _scatteringTable; }
|
||||||
|
|
||||||
void generateScatteringTable(RenderArgs* args);
|
void generateScatteringTable(RenderArgs* args);
|
||||||
static gpu::TexturePointer generatePreIntegratedScattering(RenderArgs* args);
|
static gpu::TexturePointer generateScatteringProfile(RenderArgs* args);
|
||||||
|
static gpu::TexturePointer generatePreIntegratedScattering(const gpu::TexturePointer& profile, RenderArgs* args);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
gpu::TexturePointer _scatteringProfile;
|
||||||
gpu::TexturePointer _scatteringTable;
|
gpu::TexturePointer _scatteringTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,6 +83,7 @@ class SubsurfaceScatteringConfig : public render::Job::Config {
|
||||||
Q_PROPERTY(float curvatureScale MEMBER curvatureScale NOTIFY dirty)
|
Q_PROPERTY(float curvatureScale MEMBER curvatureScale NOTIFY dirty)
|
||||||
|
|
||||||
|
|
||||||
|
Q_PROPERTY(bool showProfile MEMBER showProfile NOTIFY dirty)
|
||||||
Q_PROPERTY(bool showLUT MEMBER showLUT NOTIFY dirty)
|
Q_PROPERTY(bool showLUT MEMBER showLUT NOTIFY dirty)
|
||||||
public:
|
public:
|
||||||
SubsurfaceScatteringConfig() : render::Job::Config(true) {}
|
SubsurfaceScatteringConfig() : render::Job::Config(true) {}
|
||||||
|
@ -92,6 +96,7 @@ public:
|
||||||
float curvatureOffset{ 0.08f };
|
float curvatureOffset{ 0.08f };
|
||||||
float curvatureScale{ 0.8f };
|
float curvatureScale{ 0.8f };
|
||||||
|
|
||||||
|
bool showProfile{ true };
|
||||||
bool showLUT{ true };
|
bool showLUT{ true };
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -121,6 +126,7 @@ private:
|
||||||
|
|
||||||
gpu::PipelinePointer _showLUTPipeline;
|
gpu::PipelinePointer _showLUTPipeline;
|
||||||
gpu::PipelinePointer getShowLUTPipeline();
|
gpu::PipelinePointer getShowLUTPipeline();
|
||||||
|
bool _showProfile{ false };
|
||||||
bool _showLUT{ false };
|
bool _showLUT{ false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,95 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
<@func declareSubsurfaceScatteringProfileSource()@>
|
||||||
|
|
||||||
|
float gaussian(float v, float r) {
|
||||||
|
const float _PI = 3.14159265358979523846;
|
||||||
|
return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 scatter(float r) {
|
||||||
|
// r is the distance expressed in millimeter
|
||||||
|
// returns the scatter reflectance
|
||||||
|
// Values from GPU Gems 3 "Advanced Skin Rendering".
|
||||||
|
// Originally taken from real life samples.
|
||||||
|
const vec4 profile[6] = vec4[6](
|
||||||
|
vec4(0.0064, 0.233, 0.455, 0.649),
|
||||||
|
vec4(0.0484, 0.100, 0.336, 0.344),
|
||||||
|
vec4(0.1870, 0.118, 0.198, 0.000),
|
||||||
|
vec4(0.5670, 0.113, 0.007, 0.007),
|
||||||
|
vec4(1.9900, 0.358, 0.004, 0.000),
|
||||||
|
vec4(7.4100, 0.078, 0.000, 0.000)
|
||||||
|
);
|
||||||
|
const int profileNum = 6;
|
||||||
|
|
||||||
|
vec3 ret = vec3(0.0);
|
||||||
|
for (int i = 0; i < profileNum; i++) {
|
||||||
|
float v = profile[i].x * 1.414;
|
||||||
|
float g = gaussian(v, r);
|
||||||
|
ret += g * profile[i].yzw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
|
<@func declareSubsurfaceScatteringGenerateProfileMap()@>
|
||||||
|
<$declareSubsurfaceScatteringProfileSource()$>
|
||||||
|
|
||||||
|
vec3 generateProfile(vec2 uv) {
|
||||||
|
return scatter(uv.x * 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
|
<@func declareSubsurfaceScatteringProfileMap()@>
|
||||||
|
|
||||||
|
uniform sampler2D scatteringProfile;
|
||||||
|
|
||||||
|
vec3 scatter(float r) {
|
||||||
|
return texture(scatteringProfile, vec2(r * 0.5, 0.5)).rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
|
<@func declareSubsurfaceScatteringIntegrate(NumIntegrationSteps)@>
|
||||||
|
|
||||||
|
|
||||||
|
vec3 integrate(float cosTheta, float skinRadius) {
|
||||||
|
// Angle from lighting direction.
|
||||||
|
float theta = acos(cosTheta);
|
||||||
|
vec3 totalWeights = vec3(0.0);
|
||||||
|
vec3 totalLight = vec3(0.0);
|
||||||
|
|
||||||
|
const float _PI = 3.14159265358979523846;
|
||||||
|
const float step = 2.0 * _PI / <$NumIntegrationSteps$>;
|
||||||
|
float a = -(_PI);
|
||||||
|
|
||||||
|
|
||||||
|
while (a <= (_PI)) {
|
||||||
|
float sampleAngle = theta + a;
|
||||||
|
float diffuse = clamp(cos(sampleAngle), 0.0, 1.0);
|
||||||
|
//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));
|
||||||
|
|
||||||
|
// Profile Weight.
|
||||||
|
vec3 weights = scatter(sampleDist);
|
||||||
|
|
||||||
|
totalWeights += weights;
|
||||||
|
totalLight += diffuse * weights;
|
||||||
|
a += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 result = (totalLight / totalWeights);
|
||||||
|
return clamp(result, vec3(0.0), vec3(1.0));
|
||||||
|
|
||||||
|
}
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
<@func declareSubsurfaceScatteringResource()@>
|
<@func declareSubsurfaceScatteringResource()@>
|
||||||
|
|
||||||
|
|
|
@ -9,82 +9,9 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
<@include SubsurfaceScattering.slh@>
|
||||||
const float _PI = 3.14159265358979523846;
|
<$declareSubsurfaceScatteringProfileSource()$>
|
||||||
|
<$declareSubsurfaceScatteringIntegrate(2000)$>
|
||||||
|
|
||||||
uniform sampler2D profileMap;
|
|
||||||
/*
|
|
||||||
vec3 scatter(float r) {
|
|
||||||
return texture(profileMap, vec2(2.0 * r, 0.5)).xyz;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
float gaussian(float v, float r) {
|
|
||||||
return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 scatter(float r) {
|
|
||||||
// Values from GPU Gems 3 "Advanced Skin Rendering".
|
|
||||||
// Originally taken from real life samples.
|
|
||||||
vec4 profile[6] = vec4[6](
|
|
||||||
vec4(0.0064, 0.233, 0.455, 0.649),
|
|
||||||
vec4(0.0484, 0.100, 0.336, 0.344),
|
|
||||||
vec4(0.1870, 0.118, 0.198, 0.000),
|
|
||||||
vec4(0.5670, 0.113, 0.007, 0.007),
|
|
||||||
vec4(1.9900, 0.358, 0.004, 0.000),
|
|
||||||
vec4(7.4100, 0.078, 0.000, 0.000)
|
|
||||||
);
|
|
||||||
//const int profileNum = 6;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vec3 ret = vec3(0.0);
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
float v = profile[i].x * 1.414;
|
|
||||||
float g = gaussian(v, r);
|
|
||||||
ret += g * profile[i].yzw;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
vec3 integrate(float cosTheta, float skinRadius) {
|
|
||||||
// Angle from lighting direction.
|
|
||||||
float theta = acos(cosTheta);
|
|
||||||
vec3 totalWeights = vec3(0.0);
|
|
||||||
vec3 totalLight= vec3(0.0);
|
|
||||||
|
|
||||||
float a = -(_PI);
|
|
||||||
|
|
||||||
float inc = 0.1;
|
|
||||||
|
|
||||||
while (a <= (_PI)) {
|
|
||||||
float sampleAngle = theta + a;
|
|
||||||
float diffuse = clamp(cos(sampleAngle), 0.0, 1.0);
|
|
||||||
//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));
|
|
||||||
|
|
||||||
// Profile Weight.
|
|
||||||
vec3 weights = scatter( sampleDist);
|
|
||||||
|
|
||||||
totalWeights += weights;
|
|
||||||
totalLight += diffuse * weights;
|
|
||||||
a += inc;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 result = (totalLight / totalWeights);
|
|
||||||
return clamp(result, vec3(0.0), vec3(1.0));
|
|
||||||
|
|
||||||
return min(sqrt(result), vec3(1.0));
|
|
||||||
|
|
||||||
return scatter(skinRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
in vec2 varTexCoord0;
|
in vec2 varTexCoord0;
|
||||||
out vec4 outFragColor;
|
out vec4 outFragColor;
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 6/27/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 SubsurfaceScattering.slh@>
|
||||||
|
<$declareSubsurfaceScatteringGenerateProfileMap()$>
|
||||||
|
|
||||||
|
in vec2 varTexCoord0;
|
||||||
|
out vec4 outFragColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
outFragColor = vec4(generateProfile(varTexCoord0.xy), 1.0);
|
||||||
|
}
|
|
@ -263,7 +263,7 @@ gpu::PipelinePointer BlurGaussianDepthAware::getBlurVPipeline() {
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||||
|
|
||||||
// Stencil test the curvature pass for objects pixels only, not the background
|
// Stencil test the curvature pass for objects pixels only, not the background
|
||||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
// state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||||
|
|
||||||
_blurVPipeline = gpu::Pipeline::create(program, state);
|
_blurVPipeline = gpu::Pipeline::create(program, state);
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ gpu::PipelinePointer BlurGaussianDepthAware::getBlurHPipeline() {
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||||
|
|
||||||
// Stencil test the curvature pass for objects pixels only, not the background
|
// Stencil test the curvature pass for objects pixels only, not the background
|
||||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
// state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||||
|
|
||||||
_blurHPipeline = gpu::Pipeline::create(program, state);
|
_blurHPipeline = gpu::Pipeline::create(program, state);
|
||||||
}
|
}
|
||||||
|
@ -339,6 +339,10 @@ void BlurGaussianDepthAware::run(const SceneContextPointer& sceneContext, const
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
||||||
batch.setFramebuffer(blurringResources.finalFramebuffer);
|
batch.setFramebuffer(blurringResources.finalFramebuffer);
|
||||||
|
if (_inOutResources._generateOutputFramebuffer) {
|
||||||
|
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0));
|
||||||
|
}
|
||||||
|
|
||||||
batch.setPipeline(blurHPipeline);
|
batch.setPipeline(blurHPipeline);
|
||||||
batch.setResourceTexture(BlurTask_SourceSlot, blurringResources.blurringTexture);
|
batch.setResourceTexture(BlurTask_SourceSlot, blurringResources.blurringTexture);
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
|
@ -116,7 +116,7 @@ class BlurGaussianDepthAwareConfig : public BlurGaussianConfig {
|
||||||
public:
|
public:
|
||||||
BlurGaussianDepthAwareConfig() : BlurGaussianConfig() {}
|
BlurGaussianDepthAwareConfig() : BlurGaussianConfig() {}
|
||||||
|
|
||||||
float depthThreshold{ 2.0f };
|
float depthThreshold{ 1.0f };
|
||||||
signals:
|
signals:
|
||||||
void dirty();
|
void dirty();
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -62,7 +62,7 @@ vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) {
|
||||||
|
|
||||||
vec4 sampleCenter = texture(sourceMap, texcoord);
|
vec4 sampleCenter = texture(sourceMap, texcoord);
|
||||||
|
|
||||||
vec2 finalStep = parameters.filterInfo.x * direction * pixelStep;
|
vec2 finalStep = getFilterScale() * direction * pixelStep;
|
||||||
vec4 srcBlurred = vec4(0.0);
|
vec4 srcBlurred = vec4(0.0);
|
||||||
|
|
||||||
for(int i = 0; i < NUM_TAPS; i++) {
|
for(int i = 0; i < NUM_TAPS; i++) {
|
||||||
|
@ -99,9 +99,10 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep
|
||||||
float filterScale = getFilterScale();
|
float filterScale = getFilterScale();
|
||||||
float scale = distanceToProjectionWindow / sampleDepth;
|
float scale = distanceToProjectionWindow / sampleDepth;
|
||||||
|
|
||||||
vec2 finalStep = filterScale * scale * direction * pixelStep;
|
vec2 finalStep = filterScale * scale * direction * pixelStep; // *1000.0;
|
||||||
|
|
||||||
vec4 srcBlurred = vec4(0.0);
|
// Accumulate the center sample
|
||||||
|
vec4 srcBlurred = gaussianDistributionCurve[0] * sampleCenter;
|
||||||
|
|
||||||
for(int i = 1; i < NUM_TAPS; i++) {
|
for(int i = 1; i < NUM_TAPS; i++) {
|
||||||
// Fetch color and depth for current sample.
|
// Fetch color and depth for current sample.
|
||||||
|
@ -111,7 +112,8 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep
|
||||||
|
|
||||||
|
|
||||||
// If the difference in depth is huge, we lerp color back.
|
// If the difference in depth is huge, we lerp color back.
|
||||||
float s = clamp(depthThreshold * distanceToProjectionWindow /* * filterScale*/ * abs(srcDepth - sampleDepth), 0.0, 1.0);
|
float s = clamp(/*depthThreshold */12.0 * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0);
|
||||||
|
// float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0);
|
||||||
srcSample = mix(srcSample, sampleCenter, s);
|
srcSample = mix(srcSample, sampleCenter, s);
|
||||||
|
|
||||||
// Accumulate.
|
// Accumulate.
|
||||||
|
|
|
@ -57,6 +57,11 @@ Column {
|
||||||
min: 0.0
|
min: 0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: "Scattering Profile"
|
||||||
|
checked: Render.getConfig("Scattering").showProfile
|
||||||
|
onCheckedChanged: { Render.getConfig("Scattering").showProfile = checked }
|
||||||
|
}
|
||||||
CheckBox {
|
CheckBox {
|
||||||
text: "Scattering Table"
|
text: "Scattering Table"
|
||||||
checked: Render.getConfig("Scattering").showLUT
|
checked: Render.getConfig("Scattering").showLUT
|
||||||
|
|
|
@ -38,7 +38,7 @@ Column {
|
||||||
onCheckedChanged: { Render.getConfig("DiffuseCurvature").enabled = checked }
|
onCheckedChanged: { Render.getConfig("DiffuseCurvature").enabled = checked }
|
||||||
}
|
}
|
||||||
Repeater {
|
Repeater {
|
||||||
model: [ "Blur Scale:DiffuseCurvature:filterScale:2.0", "Blur Depth Threshold:DiffuseCurvature:depthThreshold:10.0", "Blur Scale2:DiffuseCurvature2:filterScale:2.0", "Blur Depth Threshold 2:DiffuseCurvature2:depthThreshold:10.0"]
|
model: [ "Blur Scale:DiffuseCurvature:filterScale:2.0", "Blur Depth Threshold:DiffuseCurvature:depthThreshold:1.0", "Blur Scale2:DiffuseCurvature2:filterScale:2.0", "Blur Depth Threshold 2:DiffuseCurvature2:depthThreshold:1.0"]
|
||||||
ConfigSlider {
|
ConfigSlider {
|
||||||
label: qsTr(modelData.split(":")[0])
|
label: qsTr(modelData.split(":")[0])
|
||||||
integral: false
|
integral: false
|
||||||
|
|
Loading…
Reference in a new issue