Examples/DeferredShading: Improve bloom quality
This commit is contained in:
parent
f64e16f7d8
commit
31c71e542e
|
|
@ -20,7 +20,8 @@ external
|
||||||
|
|
||||||
struct FragIn
|
struct FragIn
|
||||||
{
|
{
|
||||||
[builtin(fragcoord)] fragcoord: vec4<f32>
|
[builtin(fragcoord)] fragcoord: vec4<f32>,
|
||||||
|
[location(0)] uv: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FragOut
|
struct FragOut
|
||||||
|
|
@ -30,31 +31,38 @@ struct FragOut
|
||||||
|
|
||||||
struct VertIn
|
struct VertIn
|
||||||
{
|
{
|
||||||
[location(0)] pos: vec3<f32>
|
[location(0)] pos: vec2<f32>,
|
||||||
|
[location(1)] uv: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VertOut
|
struct VertOut
|
||||||
{
|
{
|
||||||
[builtin(position)] position: vec4<f32>
|
[builtin(position)] position: vec4<f32>,
|
||||||
|
[location(0)] uv: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
[entry(frag)]
|
[entry(frag)]
|
||||||
fn main(input: FragIn) -> FragOut
|
fn main(input: FragIn) -> FragOut
|
||||||
{
|
{
|
||||||
let BrightLuminance = 0.8;
|
/*let BrightLuminance = 0.8;
|
||||||
let BrightMiddleGrey = 0.5;
|
let BrightMiddleGrey = 0.5;
|
||||||
let BrightThreshold = 0.7;
|
let BrightThreshold = 0.7;
|
||||||
|
|
||||||
let fragcoord = input.fragcoord.xy * viewerData.invRenderTargetSize * 10.0;
|
let color = colorTexture.Sample(input.uv).rgb;
|
||||||
|
|
||||||
let color = colorTexture.Sample(fragcoord).rgb;
|
|
||||||
color *= BrightMiddleGrey / BrightLuminance;
|
color *= BrightMiddleGrey / BrightLuminance;
|
||||||
color *= vec3<f32>(1.0, 1.0, 1.0) + (color / (BrightThreshold*BrightThreshold));
|
color *= vec3<f32>(1.0, 1.0, 1.0) + (color / (BrightThreshold*BrightThreshold));
|
||||||
color -= vec3<f32>(0.5, 0.5, 0.5);
|
color -= vec3<f32>(0.5, 0.5, 0.5);
|
||||||
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>(max(color, vec3<f32>(0.0, 0.0, 0.0)), 1.0);
|
//output.color = vec4<f32>(max(color, vec3<f32>(0.0, 0.0, 0.0)), 1.0);
|
||||||
|
|
||||||
|
let color = colorTexture.Sample(input.uv).rgb;
|
||||||
|
let brightness = dot(color, vec3<f32>(0.2126, 0.7152, 0.0722));
|
||||||
|
if (brightness > 1.0)
|
||||||
|
output.color = vec4<f32>(color, 1.0);
|
||||||
|
else
|
||||||
|
output.color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +71,8 @@ fn main(input: FragIn) -> FragOut
|
||||||
fn main(input: VertIn) -> VertOut
|
fn main(input: VertIn) -> VertOut
|
||||||
{
|
{
|
||||||
let output: VertOut;
|
let output: VertOut;
|
||||||
output.position = vec4<f32>(input.pos, 1.0);
|
output.position = vec4<f32>(input.pos, 0.0, 1.0);
|
||||||
|
output.uv = input.uv;
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ struct ViewerData
|
||||||
external
|
external
|
||||||
{
|
{
|
||||||
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
||||||
[set(0), binding(1)] colorTexture: sampler2D<f32>,
|
//[set(0), binding(1)] colorTexture: sampler2D<f32>,
|
||||||
[set(0), binding(2)] bloomTexture: sampler2D<f32>,
|
[set(0), binding(2)] bloomTexture: sampler2D<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ struct FragOut
|
||||||
|
|
||||||
struct VertIn
|
struct VertIn
|
||||||
{
|
{
|
||||||
[location(0)] pos: vec3<f32>
|
[location(0)] pos: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VertOut
|
struct VertOut
|
||||||
|
|
@ -45,7 +45,7 @@ fn main(input: FragIn) -> FragOut
|
||||||
let fragcoord = input.fragcoord.xy * viewerData.invRenderTargetSize;
|
let fragcoord = input.fragcoord.xy * viewerData.invRenderTargetSize;
|
||||||
|
|
||||||
let output: FragOut;
|
let output: FragOut;
|
||||||
output.color = colorTexture.Sample(fragcoord) + bloomTexture.Sample(fragcoord);
|
output.color = /*colorTexture.Sample(fragcoord) + */bloomTexture.Sample(fragcoord);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +54,7 @@ fn main(input: FragIn) -> FragOut
|
||||||
fn main(input: VertIn) -> VertOut
|
fn main(input: VertIn) -> VertOut
|
||||||
{
|
{
|
||||||
let output: VertOut;
|
let output: VertOut;
|
||||||
output.position = vec4<f32>(input.pos, 1.0);
|
output.position = vec4<f32>(input.pos, 0.0, 1.0);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ struct FragOut
|
||||||
|
|
||||||
struct VertIn
|
struct VertIn
|
||||||
{
|
{
|
||||||
[location(0)] pos: vec3<f32>,
|
[location(0)] pos: vec2<f32>,
|
||||||
[location(1)] uv: vec2<f32>
|
[location(1)] uv: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ fn main(input: FragIn) -> FragOut
|
||||||
fn main(input: VertIn) -> VertOut
|
fn main(input: VertIn) -> VertOut
|
||||||
{
|
{
|
||||||
let output: VertOut;
|
let output: VertOut;
|
||||||
output.position = vec4<f32>(input.pos, 1.0);
|
output.position = vec4<f32>(input.pos, 0.0, 1.0);
|
||||||
output.vertUV = input.uv;
|
output.vertUV = input.uv;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,18 @@ struct ViewerData
|
||||||
eyePosition: vec3<f32>
|
eyePosition: vec3<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[layout(std140)]
|
||||||
|
struct BlurData
|
||||||
|
{
|
||||||
|
direction: vec2<f32>,
|
||||||
|
sizeFactor: f32
|
||||||
|
}
|
||||||
|
|
||||||
external
|
external
|
||||||
{
|
{
|
||||||
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
||||||
[set(0), binding(1)] colorTexture: sampler2D<f32>,
|
[set(0), binding(1)] colorTexture: sampler2D<f32>,
|
||||||
|
[set(0), binding(2)] blurData: uniform<BlurData>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FragIn
|
struct FragIn
|
||||||
|
|
@ -30,7 +38,7 @@ struct FragOut
|
||||||
|
|
||||||
struct VertIn
|
struct VertIn
|
||||||
{
|
{
|
||||||
[location(0)] pos: vec3<f32>
|
[location(0)] pos: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VertOut
|
struct VertOut
|
||||||
|
|
@ -41,26 +49,16 @@ struct VertOut
|
||||||
[entry(frag)]
|
[entry(frag)]
|
||||||
fn main(input: FragIn) -> FragOut
|
fn main(input: FragIn) -> FragOut
|
||||||
{
|
{
|
||||||
let invTargetSize = viewerData.invRenderTargetSize * 10.0;
|
let invTargetSize = viewerData.invRenderTargetSize * blurData.sizeFactor;
|
||||||
let fragcoord = input.fragcoord.xy * invTargetSize;
|
let fragcoord = input.fragcoord.xy * invTargetSize;
|
||||||
|
|
||||||
let color = colorTexture.Sample(fragcoord).rgb * 0.2270270270;
|
let color = colorTexture.Sample(fragcoord).rgb * 0.2270270270;
|
||||||
|
|
||||||
let filter = vec2<f32>(1.0, 0.0);
|
color += colorTexture.Sample(fragcoord + blurData.direction * 1.3846153846 * invTargetSize).rgb * 0.3162162162;
|
||||||
|
color += colorTexture.Sample(fragcoord - blurData.direction * 1.3846153846 * invTargetSize).rgb * 0.3162162162;
|
||||||
|
|
||||||
color += colorTexture.Sample(fragcoord + filter * 1.3846153846 * invTargetSize).rgb * 0.3162162162;
|
color += colorTexture.Sample(fragcoord + blurData.direction * 3.2307692308 * invTargetSize).rgb * 0.0702702703;
|
||||||
color += colorTexture.Sample(fragcoord - filter * 1.3846153846 * invTargetSize).rgb * 0.3162162162;
|
color += colorTexture.Sample(fragcoord - blurData.direction * 3.2307692308 * invTargetSize).rgb * 0.0702702703;
|
||||||
|
|
||||||
color += colorTexture.Sample(fragcoord + filter * 3.2307692308 * invTargetSize).rgb * 0.0702702703;
|
|
||||||
color += colorTexture.Sample(fragcoord - filter * 3.2307692308 * invTargetSize).rgb * 0.0702702703;
|
|
||||||
|
|
||||||
filter = vec2<f32>(0.0, 1.0);
|
|
||||||
|
|
||||||
color += colorTexture.Sample(fragcoord + filter * 1.3846153846 * invTargetSize).rgb * 0.3162162162;
|
|
||||||
color += colorTexture.Sample(fragcoord - filter * 1.3846153846 * invTargetSize).rgb * 0.3162162162;
|
|
||||||
|
|
||||||
color += colorTexture.Sample(fragcoord + filter * 3.2307692308 * invTargetSize).rgb * 0.0702702703;
|
|
||||||
color += colorTexture.Sample(fragcoord - filter * 3.2307692308 * invTargetSize).rgb * 0.0702702703;
|
|
||||||
|
|
||||||
let output: FragOut;
|
let output: FragOut;
|
||||||
output.color = vec4<f32>(color, 1.0);
|
output.color = vec4<f32>(color, 1.0);
|
||||||
|
|
@ -72,7 +70,7 @@ fn main(input: FragIn) -> FragOut
|
||||||
fn main(input: VertIn) -> VertOut
|
fn main(input: VertIn) -> VertOut
|
||||||
{
|
{
|
||||||
let output: VertOut;
|
let output: VertOut;
|
||||||
output.position = vec4<f32>(input.pos, 1.0);
|
output.position = vec4<f32>(input.pos, 0.0, 1.0);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ struct FragOut
|
||||||
|
|
||||||
struct VertIn
|
struct VertIn
|
||||||
{
|
{
|
||||||
[location(0)] pos: vec3<f32>
|
[location(0)] pos: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VertOut
|
struct VertOut
|
||||||
|
|
@ -60,7 +60,7 @@ fn main(input: FragIn) -> FragOut
|
||||||
fn main(input: VertIn) -> VertOut
|
fn main(input: VertIn) -> VertOut
|
||||||
{
|
{
|
||||||
let output: VertOut;
|
let output: VertOut;
|
||||||
output.position = vec4<f32>(input.pos, 1.0);
|
output.position = vec4<f32>(input.pos, 0.0, 1.0);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
NAZARA_REQUEST_DEDICATED_GPU()
|
NAZARA_REQUEST_DEDICATED_GPU()
|
||||||
|
|
||||||
|
constexpr std::size_t BloomSubdivisionCount = 5;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[layout(std140)]
|
[layout(std140)]
|
||||||
struct PointLight
|
struct PointLight
|
||||||
|
|
@ -325,7 +327,7 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::shared_ptr<const Nz::VertexDeclaration>& fullscreenVertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_UV);
|
const std::shared_ptr<const Nz::VertexDeclaration>& fullscreenVertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XY_UV);
|
||||||
|
|
||||||
|
|
||||||
unsigned int offscreenWidth = windowSize.x;
|
unsigned int offscreenWidth = windowSize.x;
|
||||||
|
|
@ -353,15 +355,60 @@ int main()
|
||||||
fullscreenPipelineInfoViewer.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::RenderPipeline> bloomBrightPipeline = device->InstantiateRenderPipeline(fullscreenPipelineInfoViewer);
|
std::shared_ptr<Nz::RenderPipeline> bloomBrightPipeline = device->InstantiateRenderPipeline(fullscreenPipelineInfoViewer);
|
||||||
|
|
||||||
// Gaussian Blur
|
// Gaussian Blur
|
||||||
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);
|
Nz::RenderPipelineLayoutInfo gaussianBlurPipelineLayoutInfo = fullscreenPipelineLayoutInfoViewer;
|
||||||
|
|
||||||
|
gaussianBlurPipelineLayoutInfo.bindings.push_back({
|
||||||
|
0, 2,
|
||||||
|
Nz::ShaderBindingType::UniformBuffer,
|
||||||
|
Nz::ShaderStageType::Fragment,
|
||||||
|
});
|
||||||
|
|
||||||
|
Nz::RenderPipelineInfo gaussianBlurPipelineInfo = fullscreenPipelineInfoViewer;
|
||||||
|
gaussianBlurPipelineInfo.pipelineLayout = device->InstantiateRenderPipelineLayout(gaussianBlurPipelineLayoutInfo);
|
||||||
|
|
||||||
|
Nz::FieldOffsets gaussianBlurDataOffsets(Nz::StructLayout::Std140);
|
||||||
|
std::size_t gaussianBlurDataDirection = gaussianBlurDataOffsets.AddField(Nz::StructFieldType::Float2);
|
||||||
|
std::size_t gaussianBlurDataSize = gaussianBlurDataOffsets.AddField(Nz::StructFieldType::Float1);
|
||||||
|
|
||||||
|
gaussianBlurPipelineInfo.shaderModules.clear();
|
||||||
|
gaussianBlurPipelineInfo.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(gaussianBlurPipelineInfo);
|
||||||
|
std::vector<std::shared_ptr<Nz::ShaderBinding>> gaussianBlurShaderBinding(BloomSubdivisionCount * 2);
|
||||||
|
|
||||||
|
std::vector<Nz::UInt8> gaussianBlurData(gaussianBlurDataOffsets.GetSize());
|
||||||
|
std::vector<std::shared_ptr<Nz::AbstractBuffer>> gaussianBlurUbos;
|
||||||
|
|
||||||
|
float sizeFactor = 2.f;
|
||||||
|
for (std::size_t i = 0; i < BloomSubdivisionCount; ++i)
|
||||||
|
{
|
||||||
|
Nz::AccessByOffset<Nz::Vector2f&>(gaussianBlurData.data(), gaussianBlurDataDirection) = Nz::Vector2f(1.f, 0.f);
|
||||||
|
Nz::AccessByOffset<float&>(gaussianBlurData.data(), gaussianBlurDataSize) = sizeFactor;
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::AbstractBuffer> horizontalBlurData = device->InstantiateBuffer(Nz::BufferType::Uniform);
|
||||||
|
if (!horizontalBlurData->Initialize(gaussianBlurDataOffsets.GetSize(), Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic))
|
||||||
|
return __LINE__;
|
||||||
|
|
||||||
|
horizontalBlurData->Fill(gaussianBlurData.data(), 0, gaussianBlurDataOffsets.GetSize());
|
||||||
|
|
||||||
|
Nz::AccessByOffset<Nz::Vector2f&>(gaussianBlurData.data(), gaussianBlurDataDirection) = Nz::Vector2f(0.f, 1.f);
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::AbstractBuffer> verticalBlurData = device->InstantiateBuffer(Nz::BufferType::Uniform);
|
||||||
|
if (!verticalBlurData->Initialize(gaussianBlurDataOffsets.GetSize(), Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic))
|
||||||
|
return __LINE__;
|
||||||
|
|
||||||
|
verticalBlurData->Fill(gaussianBlurData.data(), 0, gaussianBlurDataOffsets.GetSize());
|
||||||
|
|
||||||
|
sizeFactor *= 2.f;
|
||||||
|
|
||||||
|
gaussianBlurUbos.push_back(horizontalBlurData);
|
||||||
|
gaussianBlurUbos.push_back(verticalBlurData);
|
||||||
|
}
|
||||||
|
|
||||||
// Tone mapping
|
// Tone mapping
|
||||||
std::shared_ptr<Nz::ShaderBinding> toneMappingShaderBinding;
|
std::shared_ptr<Nz::ShaderBinding> toneMappingShaderBinding;
|
||||||
|
|
@ -373,14 +420,16 @@ int main()
|
||||||
|
|
||||||
// Bloom blend
|
// Bloom blend
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::ShaderBinding> bloomBlitBinding;
|
||||||
|
|
||||||
Nz::RenderPipelineLayoutInfo bloomBlendPipelineLayoutInfo;
|
Nz::RenderPipelineLayoutInfo bloomBlendPipelineLayoutInfo;
|
||||||
Nz::Graphics::FillViewerPipelineLayout(bloomBlendPipelineLayoutInfo, 0);
|
Nz::Graphics::FillViewerPipelineLayout(bloomBlendPipelineLayoutInfo, 0);
|
||||||
|
|
||||||
bloomBlendPipelineLayoutInfo.bindings.push_back({
|
/*bloomBlendPipelineLayoutInfo.bindings.push_back({
|
||||||
0, 1,
|
0, 1,
|
||||||
Nz::ShaderBindingType::Texture,
|
Nz::ShaderBindingType::Texture,
|
||||||
Nz::ShaderStageType::Fragment,
|
Nz::ShaderStageType::Fragment,
|
||||||
});
|
});*/
|
||||||
|
|
||||||
bloomBlendPipelineLayoutInfo.bindings.push_back({
|
bloomBlendPipelineLayoutInfo.bindings.push_back({
|
||||||
0, 2,
|
0, 2,
|
||||||
|
|
@ -390,6 +439,9 @@ int main()
|
||||||
|
|
||||||
|
|
||||||
Nz::RenderPipelineInfo bloomBlendPipelineInfo;
|
Nz::RenderPipelineInfo bloomBlendPipelineInfo;
|
||||||
|
bloomBlendPipelineInfo.blending = true;
|
||||||
|
bloomBlendPipelineInfo.blend.dstColor = Nz::BlendFunc::One;
|
||||||
|
bloomBlendPipelineInfo.blend.srcColor = Nz::BlendFunc::One;
|
||||||
bloomBlendPipelineInfo.primitiveMode = Nz::PrimitiveMode::TriangleList;
|
bloomBlendPipelineInfo.primitiveMode = Nz::PrimitiveMode::TriangleList;
|
||||||
bloomBlendPipelineInfo.pipelineLayout = device->InstantiateRenderPipelineLayout(bloomBlendPipelineLayoutInfo);
|
bloomBlendPipelineInfo.pipelineLayout = device->InstantiateRenderPipelineLayout(bloomBlendPipelineLayoutInfo);
|
||||||
bloomBlendPipelineInfo.vertexBuffers.push_back({
|
bloomBlendPipelineInfo.vertexBuffers.push_back({
|
||||||
|
|
@ -401,7 +453,7 @@ int main()
|
||||||
|
|
||||||
std::shared_ptr<Nz::RenderPipeline> bloomBlendPipeline = device->InstantiateRenderPipeline(bloomBlendPipelineInfo);
|
std::shared_ptr<Nz::RenderPipeline> bloomBlendPipeline = device->InstantiateRenderPipeline(bloomBlendPipelineInfo);
|
||||||
|
|
||||||
std::shared_ptr<Nz::ShaderBinding> bloomBlendShaderBinding;
|
std::vector<std::shared_ptr<Nz::ShaderBinding>> bloomBlendShaderBinding(BloomSubdivisionCount);
|
||||||
|
|
||||||
// Fullscreen data
|
// Fullscreen data
|
||||||
|
|
||||||
|
|
@ -476,18 +528,18 @@ int main()
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Nz::ShaderBinding>> lightingShaderBindings;
|
std::vector<std::shared_ptr<Nz::ShaderBinding>> lightingShaderBindings;
|
||||||
|
|
||||||
std::array<Nz::VertexStruct_XYZ_UV, 3> vertexData = {
|
std::array<Nz::VertexStruct_XY_UV, 3> vertexData = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Nz::Vector3f(-1.f, 1.f, 0.0f),
|
Nz::Vector2f(-1.f, 1.f),
|
||||||
Nz::Vector2f(0.0f, 1.0f),
|
Nz::Vector2f(0.0f, 1.0f),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Nz::Vector3f(-1.f, -3.f, 0.0f),
|
Nz::Vector2f(-1.f, -3.f),
|
||||||
Nz::Vector2f(0.0f, -1.0f),
|
Nz::Vector2f(0.0f, -1.0f),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Nz::Vector3f(3.f, 1.f, 0.0f),
|
Nz::Vector2f(3.f, 1.f),
|
||||||
Nz::Vector2f(2.0f, 1.0f),
|
Nz::Vector2f(2.0f, 1.0f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -558,9 +610,9 @@ 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 bloomBrightOutput;
|
||||||
std::size_t bloomOutput;
|
std::size_t bloomOutput;
|
||||||
std::size_t bloomTextureA;
|
std::vector<std::size_t> bloomTextures(BloomSubdivisionCount * 2);
|
||||||
std::size_t bloomTextureB;
|
|
||||||
std::size_t lightOutput;
|
std::size_t lightOutput;
|
||||||
|
|
||||||
std::size_t toneMappingOutput;
|
std::size_t toneMappingOutput;
|
||||||
|
|
@ -625,19 +677,33 @@ int main()
|
||||||
Nz::PixelFormat::RGBA16F
|
Nz::PixelFormat::RGBA16F
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomTextureA = graph.AddAttachment({
|
unsigned int bloomSize = 50'000;
|
||||||
"Bloom texture A",
|
bloomBrightOutput = graph.AddAttachment({
|
||||||
|
"Bloom bright output",
|
||||||
Nz::PixelFormat::RGBA16F,
|
Nz::PixelFormat::RGBA16F,
|
||||||
10'000,
|
bloomSize,
|
||||||
10'000
|
bloomSize
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomTextureB = graph.AddAttachment({
|
for (std::size_t i = 0; i < BloomSubdivisionCount; ++i)
|
||||||
"Bloom texture B",
|
{
|
||||||
Nz::PixelFormat::RGBA16F,
|
bloomTextures[i * 2 + 0] = graph.AddAttachment({
|
||||||
10'000,
|
"Bloom texture #" + std::to_string(i),
|
||||||
10'000
|
Nz::PixelFormat::RGBA16F,
|
||||||
});
|
bloomSize,
|
||||||
|
bloomSize
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
bloomTextures[i * 2 + 1] = graph.AddAttachment({
|
||||||
|
"Bloom texture #" + std::to_string(i),
|
||||||
|
Nz::PixelFormat::RGBA16F,
|
||||||
|
bloomSize,
|
||||||
|
bloomSize
|
||||||
|
});
|
||||||
|
|
||||||
|
bloomSize /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
toneMappingOutput = graph.AddAttachment({
|
toneMappingOutput = graph.AddAttachment({
|
||||||
"Tone mapping",
|
"Tone mapping",
|
||||||
|
|
@ -768,39 +834,73 @@ int main()
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomBrightPass.AddInput(lightOutput);
|
bloomBrightPass.AddInput(lightOutput);
|
||||||
bloomBrightPass.AddOutput(bloomTextureA);
|
bloomBrightPass.AddOutput(bloomBrightOutput);
|
||||||
|
|
||||||
Nz::FramePass& bloomBlurPass = graph.AddPass("Bloom pass - gaussian blur");
|
std::size_t bloomTextureIndex = 0;
|
||||||
bloomBlurPass.SetCommandCallback([&](Nz::CommandBufferBuilder& builder, const Nz::Recti& renderArea)
|
for (std::size_t i = 0; i < BloomSubdivisionCount; ++i)
|
||||||
{
|
{
|
||||||
builder.SetScissor(renderArea);
|
Nz::FramePass& bloomBlurPassHorizontal = graph.AddPass("Bloom pass - gaussian blur #" + std::to_string(i) + " - horizontal");
|
||||||
builder.SetViewport(renderArea);
|
bloomBlurPassHorizontal.SetCommandCallback([&, i](Nz::CommandBufferBuilder& builder, const Nz::Recti& renderArea)
|
||||||
|
{
|
||||||
|
builder.SetScissor(renderArea);
|
||||||
|
builder.SetViewport(renderArea);
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *gaussianBlurShaderBinding);
|
builder.BindShaderBinding(0, *gaussianBlurShaderBinding[i * 2 + 0]);
|
||||||
builder.BindPipeline(*gaussianBlurPipeline);
|
builder.BindPipeline(*gaussianBlurPipeline);
|
||||||
builder.BindVertexBuffer(0, *fullscreenVertexBuffer);
|
builder.BindVertexBuffer(0, *fullscreenVertexBuffer);
|
||||||
|
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
});
|
});
|
||||||
bloomBlurPass.SetExecutionCallback([&]
|
|
||||||
{
|
|
||||||
return (bloomEnabled) ? Nz::FramePassExecution::Execute : Nz::FramePassExecution::Skip;
|
|
||||||
});
|
|
||||||
|
|
||||||
bloomBlurPass.AddInput(bloomTextureA);
|
bloomBlurPassHorizontal.SetExecutionCallback([&]
|
||||||
bloomBlurPass.AddOutput(bloomTextureB);
|
{
|
||||||
|
return (bloomEnabled) ? Nz::FramePassExecution::Execute : Nz::FramePassExecution::Skip;
|
||||||
|
});
|
||||||
|
|
||||||
|
bloomBlurPassHorizontal.AddInput((i == 0) ? bloomBrightOutput : bloomTextures[bloomTextureIndex++]);
|
||||||
|
bloomBlurPassHorizontal.AddOutput(bloomTextures[bloomTextureIndex]);
|
||||||
|
|
||||||
|
Nz::FramePass& bloomBlurPassVertical = graph.AddPass("Bloom pass - gaussian blur #" + std::to_string(i) + " - vertical");
|
||||||
|
bloomBlurPassVertical.SetCommandCallback([&, i](Nz::CommandBufferBuilder& builder, const Nz::Recti& renderArea)
|
||||||
|
{
|
||||||
|
builder.SetScissor(renderArea);
|
||||||
|
builder.SetViewport(renderArea);
|
||||||
|
|
||||||
|
builder.BindShaderBinding(0, *gaussianBlurShaderBinding[i * 2 + 1]);
|
||||||
|
builder.BindPipeline(*gaussianBlurPipeline);
|
||||||
|
builder.BindVertexBuffer(0, *fullscreenVertexBuffer);
|
||||||
|
|
||||||
|
builder.Draw(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
bloomBlurPassVertical.SetExecutionCallback([&]
|
||||||
|
{
|
||||||
|
return (bloomEnabled) ? Nz::FramePassExecution::Execute : Nz::FramePassExecution::Skip;
|
||||||
|
});
|
||||||
|
|
||||||
|
bloomBlurPassVertical.AddInput(bloomTextures[bloomTextureIndex++]);
|
||||||
|
bloomBlurPassVertical.AddOutput(bloomTextures[bloomTextureIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
Nz::FramePass& bloomBlendPass = graph.AddPass("Bloom pass - blend");
|
Nz::FramePass& bloomBlendPass = graph.AddPass("Bloom pass - blend");
|
||||||
bloomBlendPass.SetCommandCallback([&](Nz::CommandBufferBuilder& builder, const Nz::Recti& renderArea)
|
bloomBlendPass.SetCommandCallback([&](Nz::CommandBufferBuilder& builder, const Nz::Recti& renderArea)
|
||||||
{
|
{
|
||||||
builder.SetScissor(renderArea);
|
builder.SetScissor(renderArea);
|
||||||
builder.SetViewport(renderArea);
|
builder.SetViewport(renderArea);
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *bloomBlendShaderBinding);
|
|
||||||
builder.BindPipeline(*bloomBlendPipeline);
|
|
||||||
builder.BindVertexBuffer(0, *fullscreenVertexBuffer);
|
builder.BindVertexBuffer(0, *fullscreenVertexBuffer);
|
||||||
|
|
||||||
|
// Blit light output
|
||||||
|
builder.BindPipeline(*Nz::Graphics::Instance()->GetBlitPipeline(false));
|
||||||
|
builder.BindShaderBinding(0, *bloomBlitBinding);
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
|
|
||||||
|
// Blend bloom
|
||||||
|
builder.BindPipeline(*bloomBlendPipeline);
|
||||||
|
for (std::size_t i = 0; i < BloomSubdivisionCount; ++i)
|
||||||
|
{
|
||||||
|
builder.BindShaderBinding(0, *bloomBlendShaderBinding[i]);
|
||||||
|
builder.Draw(3);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomBlendPass.SetExecutionCallback([&]
|
bloomBlendPass.SetExecutionCallback([&]
|
||||||
|
|
@ -809,7 +909,9 @@ int main()
|
||||||
});
|
});
|
||||||
|
|
||||||
bloomBlendPass.AddInput(lightOutput);
|
bloomBlendPass.AddInput(lightOutput);
|
||||||
bloomBlendPass.AddInput(bloomTextureB);
|
for (std::size_t i = 0; i < BloomSubdivisionCount; ++i)
|
||||||
|
bloomBlendPass.AddInput(bloomTextures[i * 2 + 1]);
|
||||||
|
|
||||||
bloomBlendPass.AddOutput(bloomOutput);
|
bloomBlendPass.AddOutput(bloomOutput);
|
||||||
|
|
||||||
Nz::FramePass& toneMappingPass = graph.AddPass("Tone mapping");
|
Nz::FramePass& toneMappingPass = graph.AddPass("Tone mapping");
|
||||||
|
|
@ -1048,50 +1150,77 @@ int main()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frame.PushForRelease(std::move(gaussianBlurShaderBinding));
|
std::size_t bloomTextureIndex = 0;
|
||||||
|
for (std::size_t i = 0; i < BloomSubdivisionCount; ++i)
|
||||||
|
{
|
||||||
|
for (std::size_t j = 0; j < 2; ++j)
|
||||||
|
{
|
||||||
|
frame.PushForRelease(std::move(gaussianBlurShaderBinding[i * 2 + j]));
|
||||||
|
|
||||||
gaussianBlurShaderBinding = fullscreenPipelineInfoViewer.pipelineLayout->AllocateShaderBinding(0);
|
gaussianBlurShaderBinding[i * 2 + j] = gaussianBlurPipeline->GetPipelineInfo().pipelineLayout->AllocateShaderBinding(0);
|
||||||
gaussianBlurShaderBinding->Update({
|
gaussianBlurShaderBinding[i * 2 + j]->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
Nz::ShaderBinding::UniformBufferBinding {
|
Nz::ShaderBinding::UniformBufferBinding {
|
||||||
viewerInstance.GetViewerBuffer().get(),
|
viewerInstance.GetViewerBuffer().get(),
|
||||||
0, viewerInstance.GetViewerBuffer()->GetSize()
|
0, viewerInstance.GetViewerBuffer()->GetSize()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
1,
|
1,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::TextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(bloomTextureA).get(),
|
bakedGraph.GetAttachmentTexture((i == 0 && j == 0) ? bloomBrightOutput : bloomTextures[bloomTextureIndex++]).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
2,
|
||||||
|
Nz::ShaderBinding::UniformBufferBinding {
|
||||||
|
gaussianBlurUbos[i * 2 + j].get(),
|
||||||
|
0, gaussianBlurUbos[i * 2 + j]->GetSize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
frame.PushForRelease(std::move(bloomBlendShaderBinding));
|
frame.PushForRelease(std::move(bloomBlendShaderBinding[i]));
|
||||||
|
|
||||||
bloomBlendShaderBinding = bloomBlendPipelineInfo.pipelineLayout->AllocateShaderBinding(0);
|
bloomBlendShaderBinding[i] = bloomBlendPipelineInfo.pipelineLayout->AllocateShaderBinding(0);
|
||||||
bloomBlendShaderBinding->Update({
|
bloomBlendShaderBinding[i]->Update({
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
Nz::ShaderBinding::UniformBufferBinding {
|
||||||
|
viewerInstance.GetViewerBuffer().get(),
|
||||||
|
0, viewerInstance.GetViewerBuffer()->GetSize()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/*{
|
||||||
|
1,
|
||||||
|
Nz::ShaderBinding::TextureBinding {
|
||||||
|
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
||||||
|
textureSampler.get()
|
||||||
|
}
|
||||||
|
},*/
|
||||||
|
{
|
||||||
|
2,
|
||||||
|
Nz::ShaderBinding::TextureBinding {
|
||||||
|
bakedGraph.GetAttachmentTexture(bloomTextures[i * 2 + 1]).get(),
|
||||||
|
textureSampler.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.PushForRelease(std::move(bloomBlitBinding));
|
||||||
|
|
||||||
|
bloomBlitBinding = Nz::Graphics::Instance()->GetBlitPipelineLayout()->AllocateShaderBinding(0);
|
||||||
|
bloomBlitBinding->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
Nz::ShaderBinding::UniformBufferBinding {
|
|
||||||
viewerInstance.GetViewerBuffer().get(),
|
|
||||||
0, viewerInstance.GetViewerBuffer()->GetSize()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
1,
|
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::TextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
2,
|
|
||||||
Nz::ShaderBinding::TextureBinding {
|
|
||||||
bakedGraph.GetAttachmentTexture(bloomTextureB).get(),
|
|
||||||
textureSampler.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue