FIxing the bad brdf and adding better debug tool and better Pipeline architecture

This commit is contained in:
samcake 2016-06-29 18:59:06 -07:00
parent b37df393e2
commit ab21a5a5d5
12 changed files with 434 additions and 429 deletions

View file

@ -609,38 +609,23 @@ void RenderDeferredCleanup::run(const render::SceneContextPointer& sceneContext,
}
}
RenderDeferred::RenderDeferred() :
_subsurfaceScatteringResource(std::make_shared<SubsurfaceScatteringResource>())
{
RenderDeferred::RenderDeferred() {
}
void RenderDeferred::configure(const Config& config) {
glm::vec4 bentInfo(config.bentRed, config.bentGreen, config.bentBlue, config.bentScale);
_subsurfaceScatteringResource->setBentNormalFactors(bentInfo);
glm::vec2 curvatureInfo(config.curvatureOffset, config.curvatureScale);
_subsurfaceScatteringResource->setCurvatureFactors(curvatureInfo);
_subsurfaceScatteringResource->setLevel((float)config.enableScattering);
_subsurfaceScatteringResource->setShowBRDF(config.showScatteringBRDF);
_subsurfaceScatteringResource->setShowCurvature(config.showCurvature);
_subsurfaceScatteringResource->setShowDiffusedNormal(config.showDiffusedNormal);
_enablePointLights = config.enablePointLights;
_enableSpotLights = config.enableSpotLights;
}
void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& inputs) {
if (!_subsurfaceScatteringResource->getScatteringTable()) {
_subsurfaceScatteringResource->generateScatteringTable(renderContext->args);
}
auto deferredTransform = inputs.get0();
auto diffusedCurvature2 = inputs.get2()->getRenderBuffer(0);
setupJob.run(sceneContext, renderContext, deferredTransform, diffusedCurvature2, _subsurfaceScatteringResource);
auto subsurfaceScatteringResource = inputs.get3();
setupJob.run(sceneContext, renderContext, deferredTransform, diffusedCurvature2, subsurfaceScatteringResource);
lightsJob.run(sceneContext, renderContext, deferredTransform, _enablePointLights, _enableSpotLights);

View file

@ -138,39 +138,12 @@ public:
class RenderDeferredConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(float bentRed MEMBER bentRed NOTIFY dirty)
Q_PROPERTY(float bentGreen MEMBER bentGreen NOTIFY dirty)
Q_PROPERTY(float bentBlue MEMBER bentBlue NOTIFY dirty)
Q_PROPERTY(float bentScale MEMBER bentScale NOTIFY dirty)
Q_PROPERTY(bool enablePointLights MEMBER enablePointLights NOTIFY dirty)
Q_PROPERTY(bool enableSpotLights MEMBER enableSpotLights NOTIFY dirty)
Q_PROPERTY(float curvatureOffset MEMBER curvatureOffset NOTIFY dirty)
Q_PROPERTY(float curvatureScale MEMBER curvatureScale NOTIFY dirty)
Q_PROPERTY(bool enableScattering MEMBER enableScattering NOTIFY dirty)
Q_PROPERTY(bool showScatteringBRDF MEMBER showScatteringBRDF NOTIFY dirty)
Q_PROPERTY(bool showCurvature MEMBER showCurvature NOTIFY dirty)
Q_PROPERTY(bool showDiffusedNormal MEMBER showDiffusedNormal NOTIFY dirty)
Q_PROPERTY(bool enablePointLights MEMBER enablePointLights NOTIFY dirty)
Q_PROPERTY(bool enableSpotLights MEMBER enableSpotLights NOTIFY dirty)
public:
RenderDeferredConfig() : render::Job::Config(true) {}
float bentRed{ 1.5f };
float bentGreen{ 0.8f };
float bentBlue{ 0.3f };
float bentScale{ 1.5f };
float curvatureOffset{ 0.08f };
float curvatureScale{ 0.9f };
bool enableScattering{ true };
bool showScatteringBRDF{ false };
bool showCurvature{ false };
bool showDiffusedNormal{ false };
bool enablePointLights{ true };
bool enableSpotLights{ true };
@ -181,7 +154,7 @@ signals:
class RenderDeferred {
public:
using Inputs = render::VaryingSet3 < DeferredFrameTransformPointer, gpu::FramebufferPointer, gpu::FramebufferPointer >;
using Inputs = render::VaryingSet4 < DeferredFrameTransformPointer, gpu::FramebufferPointer, gpu::FramebufferPointer, SubsurfaceScatteringResourcePointer>;
using Config = RenderDeferredConfig;
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
@ -196,7 +169,6 @@ public:
RenderDeferredCleanup cleanupJob;
protected:
SubsurfaceScatteringResourcePointer _subsurfaceScatteringResource;
bool _enablePointLights{ true };
bool _enableSpotLights{ true };

View file

@ -117,13 +117,15 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
const auto diffusedCurvatureFramebuffer = addJob<render::BlurGaussianDepthAware>("DiffuseCurvature2", curvatureFramebufferAndDepth, true);
#endif
const auto scatteringResource = addJob<SubsurfaceScattering>("Scattering");
// AO job
addJob<AmbientOcclusionEffect>("AmbientOcclusion");
// Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now.
addJob<DrawLight>("DrawLight", lights);
const auto deferredLightingInputs = render::Varying(RenderDeferred::Inputs(deferredFrameTransform, curvatureFramebuffer, diffusedCurvatureFramebuffer));
const auto deferredLightingInputs = render::Varying(RenderDeferred::Inputs(deferredFrameTransform, curvatureFramebuffer, diffusedCurvatureFramebuffer, scatteringResource));
// DeferredBuffer is complete, now let's shade it into the LightingBuffer
addJob<RenderDeferred>("RenderDeferred", deferredLightingInputs);
@ -134,8 +136,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
// Render transparent objects forward in LightingBuffer
addJob<DrawDeferred>("DrawTransparentDeferred", transparents, shapePlumber);
const auto scatteringFramebuffer = addJob<SubsurfaceScattering>("Scattering", deferredLightingInputs);
// Lighting Buffer ready for tone mapping
addJob<ToneMappingDeferred>("ToneMapping");
@ -147,6 +148,8 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
// Debugging stages
{
addJob<DebugSubsurfaceScattering>("DebugScattering", deferredLightingInputs);
// Debugging Deferred buffer job
const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(diffusedCurvatureFramebuffer, curvatureFramebuffer));
addJob<DebugDeferredBuffer>("DebugDeferredBuffer", debugFramebuffers);
@ -166,9 +169,6 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
}
}
// FIXME: Hit effect is never used, let's hide it for now, probably a more generic way to add custom post process effects
// addJob<HitEffect>("HitEffect");
// Blit!
addJob<Blit>("Blit");
}

View file

@ -123,180 +123,26 @@ void SubsurfaceScattering::configure(const Config& config) {
glm::vec2 curvatureInfo(config.curvatureOffset, config.curvatureScale);
_scatteringResource->setCurvatureFactors(curvatureInfo);
_showProfile = config.showProfile;
_showLUT = config.showLUT;
_scatteringResource->setLevel((float)config.enableScattering);
_scatteringResource->setShowBRDF(config.showScatteringBRDF);
_scatteringResource->setShowCurvature(config.showCurvature);
_scatteringResource->setShowDiffusedNormal(config.showDiffusedNormal);
}
gpu::PipelinePointer SubsurfaceScattering::getScatteringPipeline() {
if (!_scatteringPipeline) {
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
// 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("deferredFrameTransformBuffer"), ScatteringTask_FrameTransformSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringParamsBuffer"), ScatteringTask_ParamSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), ScatteringTask_LightSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), ScatteringTask_ScatteringTableSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), ScatteringTask_CurvatureMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("diffusedCurvatureMap"), ScatteringTask_DiffusedCurvatureMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), ScatteringTask_NormalMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("albedoMap"), ScatteringTask_AlbedoMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), ScatteringTask_LinearMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), ScatteringTask_IBLMapSlot));
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
// 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));
_scatteringPipeline = gpu::Pipeline::create(program, state);
}
return _scatteringPipeline;
}
gpu::PipelinePointer _showLUTPipeline;
gpu::PipelinePointer getShowLUTPipeline();
gpu::PipelinePointer SubsurfaceScattering::getShowLUTPipeline() {
if (!_showLUTPipeline) {
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
// slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), SubsurfaceScattering_FrameTransformSlot));
// slotBindings.insert(gpu::Shader::Binding(std::string("sourceMap"), BlurTask_SourceSlot));
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
// 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));
_showLUTPipeline = gpu::Pipeline::create(program, state);
}
return _showLUTPipeline;
}
bool SubsurfaceScattering::updateScatteringFramebuffer(const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& scatteringFramebuffer) {
if (!sourceFramebuffer) {
return false;
}
if (!_scatteringFramebuffer) {
_scatteringFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
// attach depthStencil if present in source
if (sourceFramebuffer->hasDepthStencil()) {
// _scatteringFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat());
}
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT);
auto blurringTarget = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_SRGBA_32, sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), blurringSampler));
_scatteringFramebuffer->setRenderBuffer(0, blurringTarget);
} else {
// it would be easier to just call resize on the bluredFramebuffer and let it work if needed but the source might loose it's depth buffer when doing so
if ((_scatteringFramebuffer->getWidth() != sourceFramebuffer->getWidth()) || (_scatteringFramebuffer->getHeight() != sourceFramebuffer->getHeight())) {
_scatteringFramebuffer->resize(sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), sourceFramebuffer->getNumSamples());
if (sourceFramebuffer->hasDepthStencil()) {
// _scatteringFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat());
}
}
}
if (!scatteringFramebuffer) {
scatteringFramebuffer = _scatteringFramebuffer;
}
return true;
}
void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, gpu::FramebufferPointer& scatteringFramebuffer) {
void SubsurfaceScattering::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, Outputs& outputs) {
assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
_scatteringResource->generateScatteringTable(args);
auto scatteringProfile = _scatteringResource->getScatteringProfile();
auto scatteringTable = _scatteringResource->getScatteringTable();
auto pipeline = getScatteringPipeline();
auto& frameTransform = inputs.get0();
auto& curvatureFramebuffer = inputs.get1();
auto& diffusedFramebuffer = inputs.get2();
auto framebufferCache = DependencyManager::get<FramebufferCache>();
/* if (!updateScatteringFramebuffer(curvatureFramebuffer, scatteringFramebuffer)) {
return;
if (!_scatteringResource->getScatteringTable()) {
_scatteringResource->generateScatteringTable(renderContext->args);
}
*/
const auto theLight = DependencyManager::get<DeferredLightingEffect>()->getLightStage().lights[0];
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
// batch.enableStereo(false);
batch.setViewportTransform(args->_viewport);
/* batch.setFramebuffer(_scatteringFramebuffer);
batch.setPipeline(pipeline);
batch.setUniformBuffer(ScatteringTask_FrameTransformSlot, frameTransform->getFrameTransformBuffer());
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_CurvatureMapSlot, curvatureFramebuffer->getRenderBuffer(0));
batch.setResourceTexture(ScatteringTask_DiffusedCurvatureMapSlot, diffusedFramebuffer->getRenderBuffer(0));
batch.setResourceTexture(ScatteringTask_NormalMapSlot, framebufferCache->getDeferredNormalTexture());
batch.setResourceTexture(ScatteringTask_AlbedoMapSlot, framebufferCache->getDeferredColorTexture());
batch.setResourceTexture(ScatteringTask_LinearMapSlot, framebufferCache->getDepthPyramidTexture());
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) {
batch.setViewportTransform(glm::ivec4(0, offsetViewport * 1.5, viewportSize, viewportSize));
batch.setPipeline(getShowLUTPipeline());
batch.setResourceTexture(0, scatteringTable);
batch.draw(gpu::TRIANGLE_STRIP, 4);
}
});
outputs = _scatteringResource;
}
#ifdef GENERATE_SCATTERING_RESOURCE_ON_CPU
// Reference: http://www.altdevblogaday.com/2011/12/31/skin-shading-in-unity3d/
#include <cstdio>
@ -450,6 +296,8 @@ void diffuseProfile(gpu::TexturePointer& profile) {
profile->assignStoredMip(0, gpu::Element::COLOR_RGBA_32, bytes.size(), bytes.data());
}
#endif
void diffuseProfileGPU(gpu::TexturePointer& profileMap, RenderArgs* args) {
int width = profileMap->getWidth();
int height = profileMap->getHeight();
@ -461,8 +309,6 @@ void diffuseProfileGPU(gpu::TexturePointer& profileMap, RenderArgs* args) {
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());
@ -500,7 +346,6 @@ void diffuseScatterGPU(const gpu::TexturePointer& profileMap, gpu::TexturePointe
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());
@ -529,7 +374,7 @@ void diffuseScatterGPU(const gpu::TexturePointer& profileMap, gpu::TexturePointe
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)));
auto profileMap = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_SRGBA_32, PROFILE_RESOLUTION, 1, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)));
diffuseProfileGPU(profileMap, args);
return profileMap;
}
@ -537,8 +382,153 @@ gpu::TexturePointer SubsurfaceScatteringResource::generateScatteringProfile(Rend
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)));
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, gpu::Sampler::WRAP_CLAMP)));
//diffuseScatter(scatteringLUT);
diffuseScatterGPU(profile, scatteringLUT, args);
return scatteringLUT;
}
DebugSubsurfaceScattering::DebugSubsurfaceScattering() {
}
void DebugSubsurfaceScattering::configure(const Config& config) {
_showProfile = config.showProfile;
_showLUT = config.showLUT;
_showCursorPixel = config.showCursorPixel;
_debugCursorTexcoord = config.debugCursorTexcoord;
}
gpu::PipelinePointer DebugSubsurfaceScattering::getScatteringPipeline() {
if (!_scatteringPipeline) {
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
// auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
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("deferredFrameTransformBuffer"), ScatteringTask_FrameTransformSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringParamsBuffer"), ScatteringTask_ParamSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), ScatteringTask_LightSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), ScatteringTask_ScatteringTableSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), ScatteringTask_CurvatureMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("diffusedCurvatureMap"), ScatteringTask_DiffusedCurvatureMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), ScatteringTask_NormalMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("albedoMap"), ScatteringTask_AlbedoMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), ScatteringTask_LinearMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), ScatteringTask_IBLMapSlot));
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
_scatteringPipeline = gpu::Pipeline::create(program, state);
}
return _scatteringPipeline;
}
gpu::PipelinePointer _showLUTPipeline;
gpu::PipelinePointer getShowLUTPipeline();
gpu::PipelinePointer DebugSubsurfaceScattering::getShowLUTPipeline() {
if (!_showLUTPipeline) {
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
_showLUTPipeline = gpu::Pipeline::create(program, state);
}
return _showLUTPipeline;
}
void DebugSubsurfaceScattering::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs) {
assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
auto& frameTransform = inputs.get0();
auto& curvatureFramebuffer = inputs.get1();
auto& diffusedFramebuffer = inputs.get2();
auto& scatteringResource = inputs.get3();
if (!scatteringResource) {
return;
}
auto scatteringProfile = scatteringResource->getScatteringProfile();
auto scatteringTable = scatteringResource->getScatteringTable();
auto framebufferCache = DependencyManager::get<FramebufferCache>();
const auto theLight = DependencyManager::get<DeferredLightingEffect>()->getLightStage().lights[0];
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
batch.enableStereo(false);
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) {
batch.setViewportTransform(glm::ivec4(0, offsetViewport * 1.5, viewportSize, viewportSize));
batch.setPipeline(getShowLUTPipeline());
batch.setResourceTexture(0, scatteringTable);
batch.draw(gpu::TRIANGLE_STRIP, 4);
if (_showCursorPixel) {
auto debugScatteringPipeline = getScatteringPipeline();
batch.setPipeline(debugScatteringPipeline);
Transform model;
model.setTranslation(glm::vec3(0.0, offsetViewport * 1.5 / args->_viewport.w, 0.0));
model.setScale(glm::vec3(viewportSize / (float)args->_viewport.z, viewportSize / (float)args->_viewport.w, 1.0));
batch.setModelTransform(model);
batch.setUniformBuffer(ScatteringTask_FrameTransformSlot, frameTransform->getFrameTransformBuffer());
batch.setUniformBuffer(ScatteringTask_ParamSlot, scatteringResource->getParametersBuffer());
if (theLight->light) {
batch.setUniformBuffer(ScatteringTask_LightSlot, theLight->light->getSchemaBuffer());
}
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());
batch.setResourceTexture(ScatteringTask_AlbedoMapSlot, framebufferCache->getDeferredColorTexture());
batch.setResourceTexture(ScatteringTask_LinearMapSlot, framebufferCache->getDepthPyramidTexture());
batch._glUniform2f(debugScatteringPipeline->getProgram()->getUniforms().findLocation("uniformCursorTexcoord"), _debugCursorTexcoord.x, _debugCursorTexcoord.y);
batch.draw(gpu::TRIANGLE_STRIP, 4);
}
}
batch.setViewportTransform(args->_viewport);
});
}

View file

@ -90,9 +90,11 @@ class SubsurfaceScatteringConfig : public render::Job::Config {
Q_PROPERTY(float curvatureOffset MEMBER curvatureOffset NOTIFY dirty)
Q_PROPERTY(float curvatureScale MEMBER curvatureScale NOTIFY dirty)
Q_PROPERTY(bool enableScattering MEMBER enableScattering NOTIFY dirty)
Q_PROPERTY(bool showScatteringBRDF MEMBER showScatteringBRDF NOTIFY dirty)
Q_PROPERTY(bool showCurvature MEMBER showCurvature NOTIFY dirty)
Q_PROPERTY(bool showDiffusedNormal MEMBER showDiffusedNormal NOTIFY dirty)
Q_PROPERTY(bool showProfile MEMBER showProfile NOTIFY dirty)
Q_PROPERTY(bool showLUT MEMBER showLUT NOTIFY dirty)
public:
SubsurfaceScatteringConfig() : render::Job::Config(true) {}
@ -102,10 +104,12 @@ public:
float bentScale{ 1.5f };
float curvatureOffset{ 0.08f };
float curvatureScale{ 0.8f };
float curvatureScale{ 0.9f };
bool showProfile{ false };
bool showLUT{ false };
bool enableScattering{ true };
bool showScatteringBRDF{ false };
bool showCurvature{ false };
bool showDiffusedNormal{ false };
signals:
void dirty();
@ -113,22 +117,54 @@ signals:
class SubsurfaceScattering {
public:
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, gpu::FramebufferPointer, gpu::FramebufferPointer>;
//using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, gpu::FramebufferPointer, gpu::FramebufferPointer, SubsurfaceScatteringResourcePointer>;
using Outputs = SubsurfaceScatteringResourcePointer;
using Config = SubsurfaceScatteringConfig;
using JobModel = render::Job::ModelIO<SubsurfaceScattering, Inputs, gpu::FramebufferPointer, Config>;
using JobModel = render::Job::ModelO<SubsurfaceScattering, Outputs, Config>;
SubsurfaceScattering();
void configure(const Config& config);
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, gpu::FramebufferPointer& scatteringFramebuffer);
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, Outputs& outputs);
private:
SubsurfaceScatteringResourcePointer _scatteringResource;
};
bool updateScatteringFramebuffer(const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& scatteringFramebuffer);
gpu::FramebufferPointer _scatteringFramebuffer;
class DebugSubsurfaceScatteringConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(bool showProfile MEMBER showProfile NOTIFY dirty)
Q_PROPERTY(bool showLUT MEMBER showLUT NOTIFY dirty)
Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty)
Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty)
public:
DebugSubsurfaceScatteringConfig() : render::Job::Config(true) {}
bool showProfile{ false };
bool showLUT{ false };
bool showCursorPixel{ false };
glm::vec2 debugCursorTexcoord{ 0.5, 0.5 };
signals:
void dirty();
};
class DebugSubsurfaceScattering {
public:
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, gpu::FramebufferPointer, gpu::FramebufferPointer, SubsurfaceScatteringResourcePointer>;
using Config = DebugSubsurfaceScatteringConfig;
using JobModel = render::Job::ModelI<DebugSubsurfaceScattering, Inputs, Config>;
DebugSubsurfaceScattering();
void configure(const Config& config);
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs);
private:
gpu::PipelinePointer _scatteringPipeline;
gpu::PipelinePointer getScatteringPipeline();
@ -136,6 +172,8 @@ private:
gpu::PipelinePointer getShowLUTPipeline();
bool _showProfile{ false };
bool _showLUT{ false };
bool _showCursorPixel{ false };
glm::vec2 _debugCursorTexcoord;
};
#endif // hifi_SubsurfaceScattering_h

View file

@ -109,8 +109,7 @@ vec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {
return vec3(
fetchBRDF(LdotNSpectrum.r, curvature).r,
fetchBRDF(LdotNSpectrum.g, curvature).g,
fetchBRDF(LdotNSpectrum.b, curvature).b
);
fetchBRDF(LdotNSpectrum.b, curvature).b);
}
// Subsurface Scattering parameters

View file

@ -10,175 +10,112 @@
//
<!<@include DeferredTransform.slh@>
<$declareDeferredFrameTransform()$>
!>
<@include DeferredBufferRead.slh@>
<@include model/Light.slh@>
<@include DeferredGlobalLight.slh@>
<$declareEvalGlobalSpecularIrradiance(0, 1, 0)$>
uniform sampler2D linearDepthMap;
float getZEye(ivec2 pixel) {
return -texelFetch(linearDepthMap, pixel, 0).x;
}
float getZEyeLinear(vec2 texcoord) {
return -texture(linearDepthMap, texcoord).x;
}
vec2 sideToFrameTexcoord(vec2 side, vec2 texcoordPos) {
return vec2((texcoordPos.x + side.x) * side.y, texcoordPos.y);
}
// 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);
}
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
);
}
// Scattering parameters
struct ScatteringParameters {
vec4 normalBendInfo; // R, G, B, factor
vec4 curvatureInfo;// Offset, Scale
};
uniform scatteringParamsBuffer {
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;
}
<$declareDeferredCurvature()$>
<@include SubsurfaceScattering.slh@>
<$declareSubsurfaceScatteringResource()$>
in vec2 varTexCoord0;
out vec4 _fragColor;
uniform vec2 uniformCursorTexcoord = vec2(0.5);
//uniform vec3 uniformLightVector = vec3(1.0);
void main(void) {
DeferredFragment fragment = unpackDeferredFragmentNoPosition(varTexCoord0);
vec3 evalScatteringBRDF(vec2 texcoord) {
DeferredFragment fragment = unpackDeferredFragmentNoPosition(texcoord);
vec3 normal = fragment.normal; // .getWorldNormal(varTexCoord0);
vec4 blurredCurvature = fetchCurvature(varTexCoord0);
vec4 diffusedCurvature = fetchDiffusedCurvature(varTexCoord0);
vec4 blurredCurvature = fetchCurvature(texcoord);
vec4 diffusedCurvature = fetchDiffusedCurvature(texcoord);
// --> Get curvature data
vec3 bentNormalHigh = normalize( (blurredCurvature.xyz - 0.5f) * 2.0f );
vec3 bentNormalLow = normalize( (diffusedCurvature.xyz - 0.5f) * 2.0f );
// Transform directions to worldspace
vec3 fragNormal = vec3((normal));
// Get light
Light light = getLight();
vec3 fresnel = vec3(0.028); // Default Di-electric fresnel value for skin
float metallic = 0.0;
vec3 fragLightDir = -normalize(getLightDirection(light));
vec3 midNormal = normalize((blurredCurvature.xyz - 0.5f) * 2.0f);
vec3 lowNormal = normalize((diffusedCurvature.xyz - 0.5f) * 2.0f);
float curvature = unpackCurvature(diffusedCurvature.w);
if (showDiffusedNormal()) {
return diffusedCurvature.xyz;
return lowNormal * 0.5 + vec3(0.5);
}
if (showCurvature()) {
float curvatureSigned = unpackCurvatureSigned(diffusedCurvature.w);
return (curvatureSigned > 0 ? vec3(curvatureSigned, 0.0, 0.0) : vec3(0.0, 0.0, -curvatureSigned));
}
// _fragColor = vec4(vec3(diffusedCurvature.xyz), 1.0);
vec3 bentNdotL = evalScatteringBentNdotL(fragNormal, midNormal, lowNormal, fragLightDir);
// --> Calculate the light vector.
vec3 brdf = fetchBRDFSpectrum(bentNdotL, curvature);
return brdf;
}
vec3 drawScatteringTableUV(vec2 cursor, vec2 texcoord) {
DeferredFragment fragment = unpackDeferredFragmentNoPosition(cursor);
vec3 normal = fragment.normal; // .getWorldNormal(varTexCoord0);
vec4 blurredCurvature = fetchCurvature(cursor);
vec4 diffusedCurvature = fetchDiffusedCurvature(cursor);
// Get light
Light light = getLight();
vec3 fragLightDir = -getLightDirection(light); //normalize(uniformLightVector); //normalize(lightPos - sourcePos.xyz);
// _fragColor = vec4(fetchBRDF(dot(bentNormalR, fragLightDir), abs(diffusedCurvature.w * 2 - 1)), 1.0);
// _fragColor = vec4(vec3(abs(dot(bentNormalR, fragLightDir))), 1.0);
// _fragColor = vec4(vec3(varTexCoord0, 0.0), 1.0);
// _fragColor = vec4(vec3(bentNormalR * 0.5 + 0.5), 1.0);
vec3 fresnel = vec3(0.028); // Default Di-electric fresnel value for skin
vec3 fragLightDir = -normalize(getLightDirection(light));
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 midNormal = normalize((blurredCurvature.xyz - 0.5f) * 2.0f);
vec3 lowNormal = normalize((diffusedCurvature.xyz - 0.5f) * 2.0f);
float curvature = unpackCurvature(diffusedCurvature.w);
vec3 NdotLSpectrum = vec3(dot(rN, fragLightDir), dot(gN, fragLightDir), dot(bN, fragLightDir));
vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, fragLightDir);
// --> Look up the pre-integrated curvature-dependent BDRF textures
vec3 bdrf = fetchBRDFSpectrum(NdotLSpectrum, curvature);
// return clamp(bentNdotL * 0.5 + 0.5, 0.0, 1.0);
// Pixel being shaded
ivec2 pixelPos;
vec2 texcoordPos;
ivec4 stereoSide;
ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide);
vec2 stereoSideClip = vec2(stereoSide.x, (isStereo() ? 0.5 : 1.0));
vec2 frameTexcoordPos = sideToFrameTexcoord(stereoSideClip, texcoordPos);
// Fetch the z under the pixel (stereo or not)
float Zeye = getZEye(framePixelPos);
vec3 worldNormal = fragment.normal;
// The position of the pixel fragment in Eye space then in world space
vec3 eyePos = evalEyePositionFromZeye(stereoSide.x, Zeye, texcoordPos);
vec3 fragEyeDir = -(frameTransform._viewInverse * vec4(normalize(eyePos), 0.0)).xyz;
vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
if (fragment.metallic > 0.5) {
fresnel = fragment.diffuse;
fragment.metallic = 1.0;
}
vec3 albedo = fragment.diffuse;
vec3 fragNormal = fragment.normal;
vec4 shading;
{ // Key Sun Lighting
// Diffuse Lighting
float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0);
// Specular Lighting
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
vec3 fresnelColor = fresnelSchlick(fresnel, fragLightDir,halfDir);
float power = specularDistribution(fragment.roughness, fragNormal, halfDir);
vec3 specular = power * fresnelColor * diffuse;
shading = vec4(specular, (1.0 - fragment.metallic) * diffuse * (1 - fresnelColor.x));
vec3 distance = vec3(0.0);
for (int c = 0; c < 3; c++) {
vec2 BRDFuv = vec2(clamp(bentNdotL[c] * 0.5 + 0.5, 0.0, 1.0), clamp(2 * curvature, 0.0, 1.0));
vec2 delta = BRDFuv - texcoord;
distance[c] = 1.0 - dot(delta, delta);
}
vec3 color = vec3(albedo * vec3(bdrf.xyz) + shading.rgb) * getLightColor(light) * getLightIntensity(light);
distance *= distance;
float threshold = 0.999;
vec3 color = vec3(0.0);
bool keep = false;
for (int c = 0; c < 3; c++) {
if (distance[c] > threshold) {
keep = true;
color[c] += 1.0;
}
}
// Diffuse from ambient
color += (1 - fragment.metallic) * albedo * evalSphericalLight(getLightAmbientSphere(light), bentNormalHigh).xyz * 1.0 * getLightAmbientIntensity(light);
if (!keep)
discard;
// Specular highlight from ambient
vec3 specularLighting = evalGlobalSpecularIrradiance(light, fragEyeDir, fragNormal, fragment.roughness, fresnel, 1.0);
color += specularLighting;
return color;
}
//_fragColor = vec4(evalSkyboxLight(rS, 0.0).rgb, 1.0);
void main(void) {
// _fragColor = vec4(evalScatteringBRDF(varTexCoord0), 1.0);
// _fragColor = vec4(uniformCursorTexcoord, 0.0, 1.0);
_fragColor = vec4(color, 1.0);
_fragColor = vec4(drawScatteringTableUV(uniformCursorTexcoord, varTexCoord0), 1.0);
}

View file

@ -113,7 +113,7 @@ public:
using Parent = std::tuple<Varying, Varying, Varying>;
VaryingSet3() : Parent(Varying(T0()), Varying(T1()), Varying(T2())) {}
VaryingSet3(const VaryingSet3& trio) : Parent(std::get<0>(trio), std::get<1>(trio), std::get<2>(trio)) {}
VaryingSet3(const VaryingSet3& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src)) {}
VaryingSet3(const Varying& first, const Varying& second, const Varying& third) : Parent(first, second, third) {}
const T0& get0() const { return std::get<0>((*this)).template get<T0>(); }
@ -126,6 +126,28 @@ public:
T2& edit2() { return std::get<2>((*this)).template edit<T2>(); }
};
template <class T0, class T1, class T2, class T3>
class VaryingSet4 : public std::tuple<Varying, Varying, Varying, Varying>{
public:
using Parent = std::tuple<Varying, Varying, Varying, Varying>;
VaryingSet4() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3())) {}
VaryingSet4(const VaryingSet4& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src)) {}
VaryingSet4(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth) : Parent(first, second, third, fourth) {}
const T0& get0() const { return std::get<0>((*this)).template get<T0>(); }
T0& edit0() { return std::get<0>((*this)).template edit<T0>(); }
const T1& get1() const { return std::get<1>((*this)).template get<T1>(); }
T1& edit1() { return std::get<1>((*this)).template edit<T1>(); }
const T2& get2() const { return std::get<2>((*this)).template get<T2>(); }
T2& edit2() { return std::get<2>((*this)).template edit<T2>(); }
const T3& get3() const { return std::get<3>((*this)).template get<T3>(); }
T3& edit3() { return std::get<3>((*this)).template edit<T3>(); }
};
template < class T, int NUM >
class VaryingArray : public std::array<Varying, NUM> {
public:

View file

@ -1,5 +1,5 @@
//
// debugSurfaceGeometryPass.js
// debugDeferredLighting.js
//
// Created by Sam Gateau on 6/6/2016
// Copyright 2016 High Fidelity, Inc.
@ -13,7 +13,7 @@ var qml = Script.resolvePath('deferredLighting.qml');
var window = new OverlayWindow({
title: 'Deferred Lighting Pass',
source: qml,
width: 400, height: 350,
width: 400, height: 100,
});
window.setPosition(250, 800);
window.closed.connect(function() { Script.stop(); });

View file

@ -0,0 +1,37 @@
//
// debugSubsirfaceScattering.js
//
// Created by Sam Gateau on 6/6/2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
// Set up the qml ui
var qml = Script.resolvePath('subsurfaceScattering.qml');
var window = new OverlayWindow({
title: 'Subsurface Scattering',
source: qml,
width: 400, height: 350,
});
window.setPosition(250, 950);
window.closed.connect(function() { Script.stop(); });
var moveDebugCursor = false;
Controller.mousePressEvent.connect(function (e) {
if (e.isMiddleButton) {
moveDebugCursor = true;
setDebugCursor(e.x, e.y);
}
});
Controller.mouseReleaseEvent.connect(function() { moveDebugCursor = false; });
Controller.mouseMoveEvent.connect(function (e) { if (moveDebugCursor) setDebugCursor(e.x, e.y); });
function setDebugCursor(x, y) {
nx = (x / Window.innerWidth);
ny = 1.0 - ((y) / (Window.innerHeight - 32));
Render.getConfig("DebugScattering").debugCursorTexcoord = { x: nx, y: ny };
}

View file

@ -27,56 +27,5 @@ Column {
checked: true
onCheckedChanged: { Render.getConfig("RenderDeferred").enableSpotLights = checked }
}
Column{
CheckBox {
text: "Scattering"
checked: true
onCheckedChanged: { Render.getConfig("RenderDeferred").enableScattering = checked }
}
CheckBox {
text: "Show Scattering BRDF"
checked: Render.getConfig("RenderDeferred").showScatteringBRDF
onCheckedChanged: { Render.getConfig("RenderDeferred").showScatteringBRDF = checked }
}
CheckBox {
text: "Show Curvature"
checked: Render.getConfig("RenderDeferred").showCurvature
onCheckedChanged: { Render.getConfig("RenderDeferred").showCurvature = checked }
}
CheckBox {
text: "Show Diffused Normal"
checked: Render.getConfig("RenderDeferred").showDiffusedNormal
onCheckedChanged: { Render.getConfig("RenderDeferred").showDiffusedNormal = checked }
}
Repeater {
model: [ "Scattering Bent Red:RenderDeferred:bentRed:2.0",
"Scattering Bent Green:RenderDeferred:bentGreen:2.0",
"Scattering Bent Blue:RenderDeferred:bentBlue:2.0",
"Scattering Bent Scale:RenderDeferred:bentScale:5.0",
"Scattering Curvature Offset:RenderDeferred:curvatureOffset:1.0",
"Scattering Curvature Scale:RenderDeferred:curvatureScale:2.0",
]
ConfigSlider {
label: qsTr(modelData.split(":")[0])
integral: false
config: Render.getConfig(modelData.split(":")[1])
property: modelData.split(":")[2]
max: modelData.split(":")[3]
min: 0.0
}
}
CheckBox {
text: "Scattering Profile"
checked: Render.getConfig("Scattering").showProfile
onCheckedChanged: { Render.getConfig("Scattering").showProfile = checked }
}
CheckBox {
text: "Scattering Table"
checked: Render.getConfig("Scattering").showLUT
onCheckedChanged: { Render.getConfig("Scattering").showLUT = checked }
}
}
}
}

View file

@ -0,0 +1,76 @@
//
// subsurfaceScattering.qml
//
// Created by Sam Gateau on 6/6/2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import "configSlider"
Column {
spacing: 8
Column {
id: scattering
spacing: 10
Column{
CheckBox {
text: "Scattering"
checked: Render.getConfig("Scattering").enableScattering
onCheckedChanged: { Render.getConfig("Scattering").enableScattering = checked }
}
CheckBox {
text: "Show Scattering BRDF"
checked: Render.getConfig("Scattering").showScatteringBRDF
onCheckedChanged: { Render.getConfig("Scattering").showScatteringBRDF = checked }
}
CheckBox {
text: "Show Curvature"
checked: Render.getConfig("Scattering").showCurvature
onCheckedChanged: { Render.getConfig("Scattering").showCurvature = checked }
}
CheckBox {
text: "Show Diffused Normal"
checked: Render.getConfig("Scattering").showDiffusedNormal
onCheckedChanged: { Render.getConfig("Scattering").showDiffusedNormal = checked }
}
Repeater {
model: [ "Scattering Bent Red:Scattering:bentRed:2.0",
"Scattering Bent Green:Scattering:bentGreen:2.0",
"Scattering Bent Blue:Scattering:bentBlue:2.0",
"Scattering Bent Scale:Scattering:bentScale:5.0",
"Scattering Curvature Offset:Scattering:curvatureOffset:1.0",
"Scattering Curvature Scale:Scattering:curvatureScale:2.0",
]
ConfigSlider {
label: qsTr(modelData.split(":")[0])
integral: false
config: Render.getConfig(modelData.split(":")[1])
property: modelData.split(":")[2]
max: modelData.split(":")[3]
min: 0.0
}
}
CheckBox {
text: "Scattering Profile"
checked: Render.getConfig("DebugScattering").showProfile
onCheckedChanged: { Render.getConfig("DebugScattering").showProfile = checked }
}
CheckBox {
text: "Scattering Table"
checked: Render.getConfig("DebugScattering").showLUT
onCheckedChanged: { Render.getConfig("DebugScattering").showLUT = checked }
}
CheckBox {
text: "Cursor Pixel"
checked: Render.getConfig("DebugScattering").showCursorPixel
onCheckedChanged: { Render.getConfig("DebugScattering").showCursorPixel = checked }
}
}
}
}