mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
FIxing the bad brdf and adding better debug tool and better Pipeline architecture
This commit is contained in:
parent
b37df393e2
commit
ab21a5a5d5
12 changed files with 434 additions and 429 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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(); });
|
||||
|
|
|
@ -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 };
|
||||
}
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
76
scripts/developer/utilities/render/subsurfaceScattering.qml
Normal file
76
scripts/developer/utilities/render/subsurfaceScattering.qml
Normal 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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue