Demo/DeferredShading: Add tone-mapping (without automatic exposure for now)
This commit is contained in:
parent
0aec863300
commit
f64e16f7d8
|
|
@ -54,7 +54,7 @@ fn main(input: FragIn) -> FragOut
|
||||||
color /= vec3<f32>(1.0, 1.0, 1.0) + color;
|
color /= vec3<f32>(1.0, 1.0, 1.0) + color;
|
||||||
|
|
||||||
let output: FragOut;
|
let output: FragOut;
|
||||||
output.color = vec4<f32>(color, 1.0);
|
output.color = vec4<f32>(max(color, vec3<f32>(0.0, 0.0, 0.0)), 1.0);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
[layout(std140)]
|
||||||
|
struct ViewerData
|
||||||
|
{
|
||||||
|
projectionMatrix: mat4<f32>,
|
||||||
|
invProjectionMatrix: mat4<f32>,
|
||||||
|
viewMatrix: mat4<f32>,
|
||||||
|
invViewMatrix: mat4<f32>,
|
||||||
|
viewProjMatrix: mat4<f32>,
|
||||||
|
invViewProjMatrix: mat4<f32>,
|
||||||
|
renderTargetSize: vec2<f32>,
|
||||||
|
invRenderTargetSize: vec2<f32>,
|
||||||
|
eyePosition: vec3<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
external
|
||||||
|
{
|
||||||
|
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
||||||
|
[set(0), binding(1)] inputTexture: sampler2D<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FragIn
|
||||||
|
{
|
||||||
|
[builtin(fragcoord)] fragcoord: vec4<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FragOut
|
||||||
|
{
|
||||||
|
[location(0)] color: vec4<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VertIn
|
||||||
|
{
|
||||||
|
[location(0)] pos: vec3<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VertOut
|
||||||
|
{
|
||||||
|
[builtin(position)] position: vec4<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
[entry(frag)]
|
||||||
|
fn main(input: FragIn) -> FragOut
|
||||||
|
{
|
||||||
|
let exposure = 0.8;
|
||||||
|
|
||||||
|
let fragcoord = input.fragcoord.xy * viewerData.invRenderTargetSize;
|
||||||
|
|
||||||
|
let hdrColor = inputTexture.Sample(fragcoord).rgb;
|
||||||
|
|
||||||
|
// reinhard tone mapping
|
||||||
|
let mapped = vec3<f32>(1.0, 1.0, 1.0) - exp(-hdrColor * exposure);
|
||||||
|
|
||||||
|
let output: FragOut;
|
||||||
|
output.color = vec4<f32>(mapped, 1.0);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[entry(vert)]
|
||||||
|
fn main(input: VertIn) -> VertOut
|
||||||
|
{
|
||||||
|
let output: VertOut;
|
||||||
|
output.position = vec4<f32>(input.pos, 1.0);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
@ -333,33 +333,45 @@ int main()
|
||||||
|
|
||||||
// Bloom data
|
// Bloom data
|
||||||
|
|
||||||
Nz::RenderPipelineLayoutInfo bloomPipelineLayoutInfo;
|
Nz::RenderPipelineLayoutInfo fullscreenPipelineLayoutInfoViewer;
|
||||||
Nz::Graphics::FillViewerPipelineLayout(bloomPipelineLayoutInfo, 0);
|
Nz::Graphics::FillViewerPipelineLayout(fullscreenPipelineLayoutInfoViewer, 0);
|
||||||
|
|
||||||
bloomPipelineLayoutInfo.bindings.push_back({
|
fullscreenPipelineLayoutInfoViewer.bindings.push_back({
|
||||||
0, 1,
|
0, 1,
|
||||||
Nz::ShaderBindingType::Texture,
|
Nz::ShaderBindingType::Texture,
|
||||||
Nz::ShaderStageType::Fragment,
|
Nz::ShaderStageType::Fragment,
|
||||||
});
|
});
|
||||||
|
|
||||||
Nz::RenderPipelineInfo bloomPipelineInfo;
|
Nz::RenderPipelineInfo fullscreenPipelineInfoViewer;
|
||||||
bloomPipelineInfo.primitiveMode = Nz::PrimitiveMode::TriangleList;
|
fullscreenPipelineInfoViewer.primitiveMode = Nz::PrimitiveMode::TriangleList;
|
||||||
bloomPipelineInfo.pipelineLayout = device->InstantiateRenderPipelineLayout(bloomPipelineLayoutInfo);
|
fullscreenPipelineInfoViewer.pipelineLayout = device->InstantiateRenderPipelineLayout(fullscreenPipelineLayoutInfoViewer);
|
||||||
bloomPipelineInfo.vertexBuffers.push_back({
|
fullscreenPipelineInfoViewer.vertexBuffers.push_back({
|
||||||
0,
|
0,
|
||||||
fullscreenVertexDeclaration
|
fullscreenVertexDeclaration
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomPipelineInfo.shaderModules.push_back(device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, resourceDir / "bloom_bright.nzsl", {}));
|
fullscreenPipelineInfoViewer.shaderModules.push_back(device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, resourceDir / "bloom_bright.nzsl", {}));
|
||||||
|
|
||||||
std::shared_ptr<Nz::ShaderBinding> bloomBrightShaderBinding;
|
std::shared_ptr<Nz::ShaderBinding> bloomBrightShaderBinding;
|
||||||
std::shared_ptr<Nz::ShaderBinding> gaussianBlurShaderBinding;
|
std::shared_ptr<Nz::ShaderBinding> gaussianBlurShaderBinding;
|
||||||
|
|
||||||
std::shared_ptr<Nz::RenderPipeline> bloomBrightPipeline = device->InstantiateRenderPipeline(bloomPipelineInfo);
|
std::shared_ptr<Nz::RenderPipeline> bloomBrightPipeline = device->InstantiateRenderPipeline(fullscreenPipelineInfoViewer);
|
||||||
|
|
||||||
bloomPipelineInfo.shaderModules.clear();
|
// Gaussian Blur
|
||||||
bloomPipelineInfo.shaderModules.push_back(device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, resourceDir / "gaussian_blur.nzsl", {}));
|
fullscreenPipelineInfoViewer.shaderModules.clear();
|
||||||
|
fullscreenPipelineInfoViewer.shaderModules.push_back(device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, resourceDir / "gaussian_blur.nzsl", {}));
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::RenderPipeline> gaussianBlurPipeline = device->InstantiateRenderPipeline(fullscreenPipelineInfoViewer);
|
||||||
|
|
||||||
|
// Tone mapping
|
||||||
|
std::shared_ptr<Nz::ShaderBinding> toneMappingShaderBinding;
|
||||||
|
|
||||||
|
fullscreenPipelineInfoViewer.shaderModules.clear();
|
||||||
|
fullscreenPipelineInfoViewer.shaderModules.push_back(device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, resourceDir / "tone_mapping.nzsl", {}));
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::RenderPipeline> toneMappingPipeline = device->InstantiateRenderPipeline(fullscreenPipelineInfoViewer);
|
||||||
|
|
||||||
|
// Bloom blend
|
||||||
|
|
||||||
Nz::RenderPipelineLayoutInfo bloomBlendPipelineLayoutInfo;
|
Nz::RenderPipelineLayoutInfo bloomBlendPipelineLayoutInfo;
|
||||||
Nz::Graphics::FillViewerPipelineLayout(bloomBlendPipelineLayoutInfo, 0);
|
Nz::Graphics::FillViewerPipelineLayout(bloomBlendPipelineLayoutInfo, 0);
|
||||||
|
|
@ -377,8 +389,6 @@ int main()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<Nz::RenderPipeline> gaussianBlurPipeline = device->InstantiateRenderPipeline(bloomPipelineInfo);
|
|
||||||
|
|
||||||
Nz::RenderPipelineInfo bloomBlendPipelineInfo;
|
Nz::RenderPipelineInfo bloomBlendPipelineInfo;
|
||||||
bloomBlendPipelineInfo.primitiveMode = Nz::PrimitiveMode::TriangleList;
|
bloomBlendPipelineInfo.primitiveMode = Nz::PrimitiveMode::TriangleList;
|
||||||
bloomBlendPipelineInfo.pipelineLayout = device->InstantiateRenderPipelineLayout(bloomBlendPipelineLayoutInfo);
|
bloomBlendPipelineInfo.pipelineLayout = device->InstantiateRenderPipelineLayout(bloomBlendPipelineLayoutInfo);
|
||||||
|
|
@ -548,11 +558,13 @@ int main()
|
||||||
std::size_t positionTexture;
|
std::size_t positionTexture;
|
||||||
std::size_t depthBuffer1;
|
std::size_t depthBuffer1;
|
||||||
std::size_t depthBuffer2;
|
std::size_t depthBuffer2;
|
||||||
std::size_t backbuffer;
|
std::size_t bloomOutput;
|
||||||
std::size_t bloomTextureA;
|
std::size_t bloomTextureA;
|
||||||
std::size_t bloomTextureB;
|
std::size_t bloomTextureB;
|
||||||
std::size_t lightOutput;
|
std::size_t lightOutput;
|
||||||
|
|
||||||
|
std::size_t toneMappingOutput;
|
||||||
|
|
||||||
Nz::SubmeshRenderer submeshRenderer;
|
Nz::SubmeshRenderer submeshRenderer;
|
||||||
std::unique_ptr<Nz::ElementRendererData> submeshRendererData = submeshRenderer.InstanciateData();
|
std::unique_ptr<Nz::ElementRendererData> submeshRendererData = submeshRenderer.InstanciateData();
|
||||||
|
|
||||||
|
|
@ -605,28 +617,35 @@ int main()
|
||||||
|
|
||||||
lightOutput = graph.AddAttachment({
|
lightOutput = graph.AddAttachment({
|
||||||
"Light output",
|
"Light output",
|
||||||
Nz::PixelFormat::RGBA8
|
Nz::PixelFormat::RGBA16F
|
||||||
});
|
});
|
||||||
|
|
||||||
backbuffer = graph.AddAttachment({
|
bloomOutput = graph.AddAttachment({
|
||||||
"Backbuffer",
|
"Backbuffer",
|
||||||
Nz::PixelFormat::RGBA8
|
Nz::PixelFormat::RGBA16F
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomTextureA = graph.AddAttachment({
|
bloomTextureA = graph.AddAttachment({
|
||||||
"Bloom texture A",
|
"Bloom texture A",
|
||||||
Nz::PixelFormat::RGBA8,
|
Nz::PixelFormat::RGBA16F,
|
||||||
10'000,
|
10'000,
|
||||||
10'000
|
10'000
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomTextureB = graph.AddAttachment({
|
bloomTextureB = graph.AddAttachment({
|
||||||
"Bloom texture B",
|
"Bloom texture B",
|
||||||
Nz::PixelFormat::RGBA8,
|
Nz::PixelFormat::RGBA16F,
|
||||||
10'000,
|
10'000,
|
||||||
10'000
|
10'000
|
||||||
});
|
});
|
||||||
|
|
||||||
|
toneMappingOutput = graph.AddAttachment({
|
||||||
|
"Tone mapping",
|
||||||
|
Nz::PixelFormat::RGBA8,
|
||||||
|
100'000,
|
||||||
|
100'000
|
||||||
|
});
|
||||||
|
|
||||||
Nz::FramePass& gbufferPass = graph.AddPass("GBuffer");
|
Nz::FramePass& gbufferPass = graph.AddPass("GBuffer");
|
||||||
|
|
||||||
std::size_t geometryAlbedo = gbufferPass.AddOutput(colorTexture);
|
std::size_t geometryAlbedo = gbufferPass.AddOutput(colorTexture);
|
||||||
|
|
@ -649,9 +668,11 @@ int main()
|
||||||
|
|
||||||
gbufferPass.SetCommandCallback([&](Nz::CommandBufferBuilder& builder, const Nz::Recti& renderArea)
|
gbufferPass.SetCommandCallback([&](Nz::CommandBufferBuilder& builder, const Nz::Recti& renderArea)
|
||||||
{
|
{
|
||||||
builder.SetScissor(renderArea);
|
|
||||||
builder.SetViewport(renderArea);
|
builder.SetViewport(renderArea);
|
||||||
|
|
||||||
|
spaceshipModel.UpdateScissorBox(renderArea);
|
||||||
|
planeModel.UpdateScissorBox(renderArea);
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Nz::RenderElement>> elements;
|
std::vector<std::unique_ptr<Nz::RenderElement>> elements;
|
||||||
spaceshipModel.BuildElement(forwardPassIndex, modelInstance1, elements);
|
spaceshipModel.BuildElement(forwardPassIndex, modelInstance1, elements);
|
||||||
spaceshipModel.BuildElement(forwardPassIndex, modelInstance2, elements);
|
spaceshipModel.BuildElement(forwardPassIndex, modelInstance2, elements);
|
||||||
|
|
@ -781,6 +802,7 @@ int main()
|
||||||
|
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomBlendPass.SetExecutionCallback([&]
|
bloomBlendPass.SetExecutionCallback([&]
|
||||||
{
|
{
|
||||||
return (bloomEnabled) ? Nz::FramePassExecution::Execute : Nz::FramePassExecution::Skip;
|
return (bloomEnabled) ? Nz::FramePassExecution::Execute : Nz::FramePassExecution::Skip;
|
||||||
|
|
@ -788,9 +810,24 @@ int main()
|
||||||
|
|
||||||
bloomBlendPass.AddInput(lightOutput);
|
bloomBlendPass.AddInput(lightOutput);
|
||||||
bloomBlendPass.AddInput(bloomTextureB);
|
bloomBlendPass.AddInput(bloomTextureB);
|
||||||
bloomBlendPass.AddOutput(backbuffer);
|
bloomBlendPass.AddOutput(bloomOutput);
|
||||||
|
|
||||||
graph.AddBackbufferOutput(backbuffer);
|
Nz::FramePass& toneMappingPass = graph.AddPass("Tone mapping");
|
||||||
|
toneMappingPass.AddInput(bloomOutput);
|
||||||
|
toneMappingPass.AddOutput(toneMappingOutput);
|
||||||
|
toneMappingPass.SetCommandCallback([&](Nz::CommandBufferBuilder& builder, const Nz::Recti& renderArea)
|
||||||
|
{
|
||||||
|
builder.SetScissor(renderArea);
|
||||||
|
builder.SetViewport(renderArea);
|
||||||
|
|
||||||
|
builder.BindShaderBinding(0, *toneMappingShaderBinding);
|
||||||
|
builder.BindPipeline(*toneMappingPipeline);
|
||||||
|
builder.BindVertexBuffer(0, *fullscreenVertexBuffer);
|
||||||
|
|
||||||
|
builder.Draw(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
graph.AddBackbufferOutput(toneMappingOutput);
|
||||||
|
|
||||||
return graph.Bake();
|
return graph.Bake();
|
||||||
}();
|
}();
|
||||||
|
|
@ -993,7 +1030,7 @@ int main()
|
||||||
|
|
||||||
frame.PushForRelease(std::move(bloomBrightShaderBinding));
|
frame.PushForRelease(std::move(bloomBrightShaderBinding));
|
||||||
|
|
||||||
bloomBrightShaderBinding = bloomPipelineInfo.pipelineLayout->AllocateShaderBinding(0);
|
bloomBrightShaderBinding = fullscreenPipelineInfoViewer.pipelineLayout->AllocateShaderBinding(0);
|
||||||
bloomBrightShaderBinding->Update({
|
bloomBrightShaderBinding->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
|
|
@ -1013,7 +1050,7 @@ int main()
|
||||||
|
|
||||||
frame.PushForRelease(std::move(gaussianBlurShaderBinding));
|
frame.PushForRelease(std::move(gaussianBlurShaderBinding));
|
||||||
|
|
||||||
gaussianBlurShaderBinding = bloomPipelineInfo.pipelineLayout->AllocateShaderBinding(0);
|
gaussianBlurShaderBinding = fullscreenPipelineInfoViewer.pipelineLayout->AllocateShaderBinding(0);
|
||||||
gaussianBlurShaderBinding->Update({
|
gaussianBlurShaderBinding->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
|
|
@ -1071,6 +1108,26 @@ int main()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frame.PushForRelease(std::move(toneMappingShaderBinding));
|
||||||
|
|
||||||
|
toneMappingShaderBinding = fullscreenPipelineInfoViewer.pipelineLayout->AllocateShaderBinding(0);
|
||||||
|
toneMappingShaderBinding->Update({
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
Nz::ShaderBinding::UniformBufferBinding {
|
||||||
|
viewerInstance.GetViewerBuffer().get(),
|
||||||
|
0, viewerInstance.GetViewerBuffer()->GetSize()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
Nz::ShaderBinding::TextureBinding {
|
||||||
|
bakedGraph.GetAttachmentTexture(bloomOutput).get(),
|
||||||
|
textureSampler.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
frame.PushForRelease(std::move(finalBlitBinding));
|
frame.PushForRelease(std::move(finalBlitBinding));
|
||||||
|
|
||||||
finalBlitBinding = fullscreenPipelineInfo.pipelineLayout->AllocateShaderBinding(0);
|
finalBlitBinding = fullscreenPipelineInfo.pipelineLayout->AllocateShaderBinding(0);
|
||||||
|
|
@ -1078,7 +1135,7 @@ int main()
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::TextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(backbuffer).get(),
|
bakedGraph.GetAttachmentTexture(toneMappingOutput).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1144,7 +1201,7 @@ int main()
|
||||||
{
|
{
|
||||||
Nz::Recti windowRenderRect(0, 0, window.GetSize().x, window.GetSize().y);
|
Nz::Recti windowRenderRect(0, 0, window.GetSize().x, window.GetSize().y);
|
||||||
|
|
||||||
builder.TextureBarrier(Nz::PipelineStage::ColorOutput, Nz::PipelineStage::FragmentShader, Nz::MemoryAccess::ColorWrite, Nz::MemoryAccess::ShaderRead, Nz::TextureLayout::ColorOutput, Nz::TextureLayout::ColorInput, *bakedGraph.GetAttachmentTexture(backbuffer));
|
builder.TextureBarrier(Nz::PipelineStage::ColorOutput, Nz::PipelineStage::FragmentShader, Nz::MemoryAccess::ColorWrite, Nz::MemoryAccess::ShaderRead, Nz::TextureLayout::ColorOutput, Nz::TextureLayout::ColorInput, *bakedGraph.GetAttachmentTexture(toneMappingOutput));
|
||||||
|
|
||||||
builder.BeginRenderPass(windowRT->GetFramebuffer(frame.GetFramebufferIndex()), windowRT->GetRenderPass(), windowRenderRect);
|
builder.BeginRenderPass(windowRT->GetFramebuffer(frame.GetFramebufferIndex()), windowRT->GetRenderPass(), windowRenderRect);
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue