diff --git a/EvoEngine_App/DemoApp.cpp b/EvoEngine_App/DemoApp.cpp index f41a8f34..dd0934e8 100644 --- a/EvoEngine_App/DemoApp.cpp +++ b/EvoEngine_App/DemoApp.cpp @@ -280,7 +280,7 @@ void SetupDemoScene(DemoSetup demo_setup, ApplicationInfo& application_info) { application_info.application_name = "Rendering Demo"; application_info.project_path = resource_folder_path / "Example Projects/Rendering/Rendering.eveproj"; ProjectManager::SetActionAfterNewScene([&](const std::shared_ptr& scene) { - scene->environment.ambient_light_intensity = 0.1f; + scene->environment.ambient_light_intensity = 0.4f; #pragma region Set main camera to correct position and rotation const auto main_camera = scene->main_camera.Get(); main_camera->Resize({640, 480}); @@ -311,10 +311,10 @@ void SetupDemoScene(DemoSetup demo_setup, ApplicationInfo& application_info) { const auto point_light_right_material = ProjectManager::CreateTemporaryAsset(); point_light_right_renderer->material.Set(point_light_right_material); point_light_right_material->material_properties.albedo_color = glm::vec3(1.0, 0.8, 0.0); - point_light_right_material->material_properties.emission = 100.0f; + point_light_right_material->material_properties.emission = 10.0f; point_light_right_renderer->mesh = Resources::GetResource("PRIMITIVE_SPHERE"); const auto point_light_right = scene->GetOrSetPrivateComponent(point_light_right_entity).lock(); - point_light_right->diffuse_brightness = 4; + point_light_right->diffuse_brightness = 30; point_light_right->light_size = 0.02f; point_light_right->linear = 0.5f; point_light_right->quadratic = 0.1f; @@ -380,8 +380,6 @@ void SetupDemoScene(DemoSetup demo_setup, ApplicationInfo& application_info) { main_camera_transform.SetPosition(glm::vec3(0, -4, 25)); scene->SetDataComponent(main_camera_entity, main_camera_transform); scene->GetOrSetPrivateComponent(main_camera_entity); - // auto postProcessing = scene->GetOrSetPrivateComponent(mainCameraEntity).lock(); - const auto surface_material = ProjectManager::CreateTemporaryAsset(); const auto border_texture = std::dynamic_pointer_cast(ProjectManager::GetOrCreateAsset("Textures/border.png")); @@ -441,6 +439,7 @@ void SetupDemoScene(DemoSetup demo_setup, ApplicationInfo& application_info) { Entity dle = scene->CreateEntity("Directional Light"); auto dlc = scene->GetOrSetPrivateComponent(dle).lock(); dlc->diffuse = glm::vec3(1.0f); + dlc->diffuse_brightness = 3.f; ltw.SetScale(glm::vec3(0.5f)); Entity ple = scene->CreateEntity("Point Light 1"); diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomCombine.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomCombine.frag deleted file mode 100644 index c83f6fef..00000000 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomCombine.frag +++ /dev/null @@ -1,13 +0,0 @@ -layout (location = 0) out vec4 FragColor; -in VS_OUT { - vec2 TexCoord; -} fs_in; - -uniform sampler2D flatColor; -uniform sampler2D brightColor; -void main() -{ - - vec3 result = texture(flatColor, fs_in.TexCoord).rgb + texture(brightColor, fs_in.TexCoord).rgb; - FragColor = vec4(result, 1.0); -} \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomCopy.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomCopy.frag new file mode 100644 index 00000000..c9dd93ab --- /dev/null +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomCopy.frag @@ -0,0 +1,20 @@ +#extension GL_ARB_shading_language_include : enable + +#include "PerFrame.glsl" + +layout (location = 0) out vec4 outSrcColor; +layout (location = 1) out vec4 outResultColor; + +layout (location = 0) in VS_OUT { + vec2 TexCoord; +} fs_in; + +layout(set = 1, binding = 0) uniform sampler2D inColor; + +void main() +{ + vec2 texCoord = fs_in.TexCoord; + outSrcColor = texture(inColor, texCoord); + + outResultColor = vec4(max(vec3(0.00001f), texture(inColor, texCoord).xyz - vec3(1.0f)), 1.0f); +} \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomDownsampling.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomDownsampling.frag new file mode 100644 index 00000000..b8612886 --- /dev/null +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomDownsampling.frag @@ -0,0 +1,125 @@ + + + +// This shader performs downsampling on a texture, +// as taken from Call Of Duty method, presented at ACM Siggraph 2014. +// This particular method was customly designed to eliminate +// "pulsating artifacts and temporal stability issues". + +// Remember to add bilinear minification filter for this texture! +// Remember to use a floating-point texture format (for HDR)! +// Remember to use edge clamping for this texture! +layout(set = 1, binding = 0) uniform sampler2D srcTexture; + +layout (location = 0) in VS_OUT { + vec2 TexCoord; +} fs_in; + +layout (location = 0) out vec4 downsample; +layout(push_constant) uniform EE_BLOOM_CONSTANTS{ + vec2 srcResolution; + int mipLevel; + int padding; +}; + +vec3 PowVec3(vec3 v, float p) +{ + return vec3(pow(v.x, p), pow(v.y, p), pow(v.z, p)); +} + +const float invGamma = 1.0 / 2.2; +vec3 ToSRGB(vec3 v) { return PowVec3(v, invGamma); } + +float sRGBToLuma(vec3 col) +{ + //return dot(col, vec3(0.2126f, 0.7152f, 0.0722f)); + return dot(col, vec3(0.299f, 0.587f, 0.114f)); +} + +float KarisAverage(vec3 col) +{ + // Formula is 1 / (1 + luma) + float luma = sRGBToLuma(ToSRGB(col)) * 0.25f; + return 1.0f / (1.0f + luma); +} + + +void main() +{ + vec2 texCoord = fs_in.TexCoord; + vec2 srcTexelSize = 1.0f / srcResolution; + float x = srcTexelSize.x; + float y = srcTexelSize.y; + + // Take 13 samples around current texel: + // a - b - c + // - j - k - + // d - e - f + // - l - m - + // g - h - i + // === ('e' is the current texel) === + vec3 a = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y + 2 * y)).rgb; + vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + 2 * y)).rgb; + vec3 c = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y + 2 * y)).rgb; + + vec3 d = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y)).rgb; + vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb; + vec3 f = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y)).rgb; + + vec3 g = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y - 2 * y)).rgb; + vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - 2 * y)).rgb; + vec3 i = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y - 2 * y)).rgb; + + vec3 j = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb; + vec3 k = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb; + vec3 l = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb; + vec3 m = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb; + + // Apply weighted distribution: + // 0.5 + 0.125 + 0.125 + 0.125 + 0.125 = 1 + // a,b,d,e * 0.125 + // b,c,e,f * 0.125 + // d,e,g,h * 0.125 + // e,f,h,i * 0.125 + // j,k,l,m * 0.5 + // This shows 5 square areas that are being sampled. But some of them overlap, + // so to have an energy preserving downsample we need to make some adjustments. + // The weights are the distributed, so that the sum of j,k,l,m (e.g.) + // contribute 0.5 to the final color output. The code below is written + // to effectively yield this sum. We get: + // 0.125*5 + 0.03125*4 + 0.0625*4 = 1 + vec3 result = e * 0.125f; + result += (a + c + g + i) * 0.03125f; + result += (b + d + f + h) * 0.0625f; + result += (j + k + l + m) * 0.125f; + + vec3 groups[5]; + switch (mipLevel) + { + case 0: + // We are writing to mip 0, so we need to apply Karis average to each block + // of 4 samples to prevent fireflies (very bright subpixels, leads to pulsating + // artifacts). + groups[0] = (a + b + d + e) * (0.125f / 4.0f); + groups[1] = (b + c + e + f) * (0.125f / 4.0f); + groups[2] = (d + e + g + h) * (0.125f / 4.0f); + groups[3] = (e + f + h + i) * (0.125f / 4.0f); + groups[4] = (j + k + l + m) * (0.5f / 4.0f); + groups[0] *= KarisAverage(groups[0]); + groups[1] *= KarisAverage(groups[1]); + groups[2] *= KarisAverage(groups[2]); + groups[3] *= KarisAverage(groups[3]); + groups[4] *= KarisAverage(groups[4]); + result = groups[0] + groups[1] + groups[2] + groups[3] + groups[4]; + result = max(result, 0.0001f); + break; + default: + result = e * 0.125f; + result += (a + c + g + i) * 0.03125f; + result += (b + d + f + h) * 0.0625f; + result += (j + k + l + m) * 0.125f; + break; + } + + downsample = vec4(result, 1.0f); +} \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomMix.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomMix.frag new file mode 100644 index 00000000..c05678d8 --- /dev/null +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomMix.frag @@ -0,0 +1,16 @@ +#extension GL_ARB_shading_language_include : enable + +layout (location = 0) out vec4 FragColor; +layout (location = 0) in VS_OUT { + vec2 TexCoord; +} fs_in; + +layout(set = 1, binding = 0) uniform sampler2D originalColor; +layout(set = 1, binding = 1) uniform sampler2D bloomColor; + +void main() +{ + vec2 texCoord = fs_in.TexCoord; + vec4 color = texture(originalColor, texCoord); + FragColor = vec4(clamp(color.xyz, vec3(0.0f), vec3(1.0f)) + texture(bloomColor, texCoord).xyz, color.w); +} \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomSeparator.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomSeparator.frag deleted file mode 100644 index f38240ce..00000000 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomSeparator.frag +++ /dev/null @@ -1,18 +0,0 @@ -layout (location = 0) out vec4 FragColor; -layout (location = 1) out vec4 BrightColor; -in VS_OUT { - vec2 TexCoord; -} fs_in; -uniform float threshold; -uniform sampler2D image; -void main() -{ - vec3 result = texture(image, fs_in.TexCoord).rgb; - // check whether result is higher than some threshold, if so, output as bloom threshold color - float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722)); - if(brightness > threshold) - BrightColor = vec4(result, 1.0); - else - BrightColor = vec4(0.0, 0.0, 0.0, 1.0); - FragColor = vec4(result, 1.0); -} \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomUpsampling.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomUpsampling.frag new file mode 100644 index 00000000..df31b2f2 --- /dev/null +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/BloomUpsampling.frag @@ -0,0 +1,55 @@ + + + +// This shader performs downsampling on a texture, +// as taken from Call Of Duty method, presented at ACM Siggraph 2014. +// This particular method was customly designed to eliminate +// "pulsating artifacts and temporal stability issues". + +// Remember to add bilinear minification filter for this texture! +// Remember to use a floating-point texture format (for HDR)! +// Remember to use edge clamping for this texture! +layout(set = 1, binding = 0) uniform sampler2D srcTexture; + +layout (location = 0) in VS_OUT { + vec2 TexCoord; +} fs_in; + +layout (location = 0) out vec4 upsample; +layout(push_constant) uniform EE_BLOOM_CONSTANTS{ + float filterRadius; +}; +void main() +{ + vec2 texCoord = fs_in.TexCoord; + // The filter kernel is applied with a radius, specified in texture + // coordinates, so that the radius will vary across mip resolutions. + float x = filterRadius; + float y = filterRadius; + + // Take 9 samples around current texel: + // a - b - c + // d - e - f + // g - h - i + // === ('e' is the current texel) === + vec4 a = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgba; + vec4 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + y)).rgba; + vec4 c = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgba; + + vec4 d = texture(srcTexture, vec2(texCoord.x - x, texCoord.y)).rgba; + vec4 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgba; + vec4 f = texture(srcTexture, vec2(texCoord.x + x, texCoord.y)).rgba; + + vec4 g = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgba; + vec4 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - y)).rgba; + vec4 i = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgba; + + // Apply weighted distribution, by using a 3x3 tent filter: + // 1 | 1 2 1 | + // -- * | 2 4 2 | + // 16 | 1 2 1 | + upsample = e * 4.0f; + upsample += (b + d + f + h)* 2.0f; + upsample += (a + c + g + i); + upsample *= 1.0f / 16.0f; +} \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRBlur.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/Blur.frag similarity index 91% rename from EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRBlur.frag rename to EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/Blur.frag index d9b95105..b85ee8a1 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRBlur.frag +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/Blur.frag @@ -1,9 +1,5 @@ #extension GL_ARB_shading_language_include : enable -#include "SSRConstants.glsl" - -precision highp float; - layout (location = 0) out vec4 FragColor; layout (location = 0) in VS_OUT { @@ -12,6 +8,12 @@ layout (location = 0) in VS_OUT { layout(set = 0, binding = 0) uniform sampler2D image; + +layout(push_constant) uniform BLUR_CONSTANTS{ + int horizontal; + float weight[5]; +}; + void main() { vec2 tex_offset = 1.0 / textureSize(image, 0); // gets size of single texel diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOBlur.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOBlur.frag new file mode 100644 index 00000000..57f582ed --- /dev/null +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOBlur.frag @@ -0,0 +1,73 @@ +#extension GL_ARB_shading_language_include : enable + +layout (location = 0) out vec4 FragColor; + +layout (location = 0) in VS_OUT { + vec2 TexCoord; +} fs_in; + +layout(set = 1, binding = 17) uniform sampler2D inDepth; +layout(set = 1, binding = 18) uniform sampler2D inNormal; +layout(set = 1, binding = 19) uniform sampler2D inMaterial; + +layout(set = 0, binding = 0) uniform sampler2D image; + + +layout(push_constant) uniform BLUR_CONSTANTS{ + int horizontal; + float camera_near; + float camera_far; + float avoid_distance; + float weight[5]; + +}; + +float linearize_depth(float ndcDepth) { + return camera_near * camera_far / (camera_far - ndcDepth * (camera_far - camera_near)); +} + +void main() +{ + vec2 tex_offset = 1.0 / textureSize(image, 0); // gets size of single texel + vec4 current = texture(image, fs_in.TexCoord).rgba; + + vec4 result = current * weight[0]; // current fragment's contribution + + float depth = linearize_depth(texture(inDepth, fs_in.TexCoord).x); + + float max_depth_diff = avoid_distance; + + if(horizontal != 0) + { + for(int i = 1; i < 5; ++i) + { + vec2 coord1 = fs_in.TexCoord + vec2(tex_offset.x * i, 0.0); + float depth1 = linearize_depth(texture(inDepth, coord1).x); + + if(abs(depth1 - depth) < max_depth_diff) result += texture(image, coord1).rgba * weight[i]; + else result += current * weight[i]; + + vec2 coord2 = fs_in.TexCoord - vec2(tex_offset.x * i, 0.0); + float depth2 = linearize_depth(texture(inDepth, coord2).x); + + if(abs(depth2 - depth) < max_depth_diff) result += texture(image, coord2).rgba * weight[i]; + else result += current * weight[i]; + } + } + else + { + for(int i = 1; i < 5; ++i) + { + vec2 coord1 = fs_in.TexCoord + vec2(0.0, tex_offset.y * i); + float depth1 = linearize_depth(texture(inDepth, coord1).x); + if(abs(depth1 - depth) < max_depth_diff) result += texture(image, coord1).rgba * weight[i]; + else result += current * weight[i]; + + vec2 coord2 = fs_in.TexCoord - vec2(0.0, tex_offset.y * i); + float depth2 = linearize_depth(texture(inDepth, coord2).x); + if(abs(depth2 - depth) < max_depth_diff) result += texture(image, coord2).rgba * weight[i]; + else result += current * weight[i]; + } + } + FragColor = result; +} \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOCombine.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOCombine.frag index 5b2d617e..18577f14 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOCombine.frag +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOCombine.frag @@ -1,12 +1,17 @@ +#extension GL_ARB_shading_language_include : enable + layout (location = 0) out vec4 FragColor; -in VS_OUT { - vec2 TexCoord; +layout (location = 0) in VS_OUT { + vec2 TexCoord; } fs_in; -uniform sampler2D originalColor; -uniform sampler2D ao; +layout(set = 0, binding = 0) uniform sampler2D originalColor; +layout(set = 0, binding = 1) uniform sampler2D ambientOcclusion; + void main() { - vec3 result = texture(originalColor, fs_in.TexCoord).rgb * (1.0 - texture(ao, fs_in.TexCoord).r); - FragColor = vec4(result, 1.0); + vec2 texCoord = fs_in.TexCoord; + vec4 color = texture(originalColor, texCoord); + vec3 result = color.rgb * (texture(ambientOcclusion, texCoord).r); + FragColor = vec4(result, color.a); } \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOGeometry.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOGeometry.frag index 581bc799..413e5d0b 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOGeometry.frag +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSAOGeometry.frag @@ -1,62 +1,86 @@ -layout (location = 0) out vec3 originalColor; -layout (location = 1) out float proximity; +#extension GL_ARB_shading_language_include : enable -in VS_OUT { +#include "PerFrame.glsl" +#include "VogelDisk.glsl" + +layout (location = 0) out vec4 outSrcColor; +layout (location = 1) out vec4 proximity; + +layout (location = 0) in VS_OUT { vec2 TexCoord; } fs_in; -uniform sampler2D color; -uniform sampler2D gNormal; -uniform sampler2D gDepth; +layout(set = 1, binding = 17) uniform sampler2D inDepth; +layout(set = 1, binding = 18) uniform sampler2D inNormal; +layout(set = 1, binding = 19) uniform sampler2D inMaterial; +layout(set = 2, binding = 0) uniform sampler2D inColor; + +layout(push_constant) uniform EE_SSAO_CONSTANTS{ + int EE_CAMERA_INDEX; + int kernelSize; + float radius; + float bias; + float factor; + float intensity; +}; -// parameters (you'd probably want to use them as uniforms to more easily tweak the effect) -uniform int kernelSize; -uniform float radius; -uniform float bias; -uniform float factor; -// tile noise texture over screen based on screen dimensions divided by noise size -uniform vec2 noiseScale; +vec3 GetNormal(in vec2 texCoord){ + return texture(inNormal, texCoord).rgb; +} + +vec3 GetViewNormal(in vec2 texCoord){ + return normalize((EE_CAMERAS[EE_CAMERA_INDEX].view * vec4(GetNormal(texCoord), 0.0f)).xyz); +} + +bool GetViewPosition(in vec2 texCoord, out vec3 position){ + float ndcDepth = texture(inDepth, texCoord).x; + if(ndcDepth == 1.0f) return false; + position = EE_DEPTH_TO_VIEW_POS(EE_CAMERA_INDEX, texCoord, ndcDepth); + return true; +} void main() { - // get input for SSAO algorithm - float ndcDepth = texture(gDepth, fs_in.TexCoord).r; - vec3 viewPos = EE_DEPTH_TO_VIEW_POS(EE_CAMERA_INDEX, fs_in.TexCoord, ndcDepth); - vec3 normal = texture(gNormal, fs_in.TexCoord).rgb; - originalColor = texture(color, fs_in.TexCoord).rgb; - if(normal == vec3(0.0)) return; - normal = normalize(mat3(view) * normal); - vec3 randomVec = EE_UNIFORM_KERNEL[int(InterleavedGradientNoise(viewPos) * MAX_KERNEL_AMOUNT) % MAX_KERNEL_AMOUNT].xyz; - // create TBN change-of-basis matrix: from tangent-space to view-space - vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); - vec3 bitangent = cross(normal, tangent); - mat3 TBN = mat3(tangent, bitangent, normal); - // iterate over the sample kernel and calculate occlusion factor - float occlusion = 0.0; - int validAmount = 0; - for(int i = 0; i < kernelSize; ++i) - { - vec3 point = EE_UNIFORM_KERNEL[i].xyz; - point.z = abs(point.z); - // get sample position - vec3 samplePos = TBN * point; // from tangent to view-space - samplePos = viewPos + samplePos * radius; - // project sample position (to sample texture) (to get position on screen/texture) - vec4 offset = vec4(samplePos, 1.0); - offset = projection * offset; // from view to clip-space - offset.xyz /= offset.w; // perspective divide - offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0 - validAmount = validAmount + 1; - // get sample depth - float sampleDepth = EE_DEPTH_TO_VIEW_POS(EE_CAMERA_INDEX, offset.xy, texture(gDepth, offset.xy).r).z; - // range check & accumulate - float rangeCheck = smoothstep(0.0, 1.0, radius / abs(viewPos.z - sampleDepth)); - occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck; - } - if(validAmount == 0){ - proximity = 0.0; - }else{ - proximity = occlusion / validAmount; - } + vec2 texSize = textureSize(inColor, 0).xy; + vec2 texCoord = fs_in.TexCoord; + outSrcColor = texture(inColor, texCoord); + vec2 uv = vec2(0.0f); + vec3 viewPos; + + if(!GetViewPosition(texCoord, viewPos)){ + proximity = vec4(1, 1, 1, 1); + return; + } + vec3 normal = GetViewNormal(texCoord); + + vec3 randomVec = EE_UNIFORM_KERNEL[int(EE_INTERLEAVED_GRADIENT_NOISE(viewPos * 3141) * MAX_KERNEL_AMOUNT) % MAX_KERNEL_AMOUNT].xyz; + + mat4 projection = EE_CAMERAS[EE_CAMERA_INDEX].projection; + // create TBN change-of-basis matrix: from tangent-space to view-space + vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 TBN = mat3(tangent, bitangent, normal); + // iterate over the sample kernel and calculate occlusion factor + float occlusion = 0.0f; + for(int i = 0; i < kernelSize; ++i) + { + vec3 point = EE_UNIFORM_KERNEL[i].xyz; + point.z = abs(point.z); + // get sample position + vec3 samplePos = TBN * point; // from tangent to view-space + samplePos = viewPos + samplePos * radius; + // project sample position (to sample texture) (to get position on screen/texture) + vec4 offset = vec4(samplePos, 1.0f); + offset = projection * offset; // from view to clip-space + offset.xyz /= offset.w; // perspective divide + offset.xyz = offset.xyz * 0.5f + 0.5f; // transform to range 0.0 - 1.0 + // get sample depth + vec3 sampleViewPos = EE_DEPTH_TO_VIEW_POS(EE_CAMERA_INDEX, offset.xy, texture(inDepth, offset.xy).r); + float sampleDepth = sampleViewPos.z; + // range check & accumulate + float rangeCheck = smoothstep(0.0f, 1.0f, pow((radius - distance(viewPos, sampleViewPos)) / radius, factor)); + occlusion += (sampleDepth >= samplePos.z + bias ? 1.0f : 0.0f) * rangeCheck; + } + proximity = vec4(max(0.0f, 1.0f - occlusion / kernelSize * intensity)); } \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRCombine.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRCombine.frag index eb6975f7..3e872338 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRCombine.frag +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRCombine.frag @@ -1,5 +1,8 @@ #extension GL_ARB_shading_language_include : enable +#define EE_MATERIALS_BLOCK_SET 0 +#define EE_MATERIALS_BLOCK_BINDING 3 +#include "Materials.glsl" #include "SSRConstants.glsl" layout (location = 0) out vec4 FragColor; @@ -7,13 +10,29 @@ layout (location = 0) in VS_OUT { vec2 TexCoord; } fs_in; -layout(set = 0, binding = 0) uniform sampler2D originalColor; -layout(set = 0, binding = 1) uniform sampler2D reflectedColorVisibility; +layout(set = 1, binding = 0) uniform sampler2D originalColor; +layout(set = 1, binding = 1) uniform sampler2D reflectedColorVisibility; + +layout(set = 2, binding = 17) uniform sampler2D inDepth; +layout(set = 2, binding = 18) uniform sampler2D inNormal; +layout(set = 2, binding = 19) uniform sampler2D inMaterial; void main() { - vec3 color = texture(originalColor, fs_in.TexCoord).rgb; - vec4 reflected = texture(reflectedColorVisibility, fs_in.TexCoord); - vec3 result = color * (1.0 - reflected.a) + reflected.rgb * reflected.a; - FragColor = vec4(result, 1.0); + vec2 texCoord = fs_in.TexCoord; + + int material_index = int(round(texture(inMaterial, texCoord).w)); + vec2 materialTexCoord = texture(inMaterial, texCoord).xy; + MaterialProperties materialProperties = EE_MATERIAL_PROPERTIES[material_index]; + + float roughness = materialProperties.roughness; + float metallic = materialProperties.metallic; + + vec4 color = texture(originalColor, texCoord); + vec4 reflected = texture(reflectedColorVisibility, texCoord); + + float factor = clamp(reflected.a * metallic * (1.f - roughness), 0.0f, 1.0f); + + vec3 result = color.xyz * (1.0f - factor) + reflected.rgb * factor; + FragColor = vec4(result.xyz, color.w); } \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRReflect.frag b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRReflect.frag index 790e14f6..8a51e68a 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRReflect.frag +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Graphics/Fragment/PostProcessing/SSRReflect.frag @@ -1,9 +1,8 @@ #extension GL_ARB_shading_language_include : enable #include "SSRConstants.glsl" -#include "Basic.glsl" +#include "PerFrame.glsl" -precision highp float; layout (location = 0) out vec4 outSrcColor; layout (location = 1) out vec4 outDstColorVisibility; @@ -15,16 +14,7 @@ layout (location = 0) in VS_OUT { layout(set = 1, binding = 17) uniform sampler2D inDepth; layout(set = 1, binding = 18) uniform sampler2D inNormal; layout(set = 1, binding = 19) uniform sampler2D inMaterial; -layout(set = 1, binding = 20) uniform sampler2D inColor; - - -vec3 EE_FUNC_FRESNEL_SCHLICK_ROUGHNESS(float cosTheta, vec3 F0, float roughness) -{ - return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0); -} - - - +layout(set = 2, binding = 0) uniform sampler2D inColor; vec3 GetNormal(in vec2 texCoord){ return texture(inNormal, texCoord).rgb; @@ -34,13 +24,6 @@ vec3 GetViewNormal(in vec2 texCoord){ return normalize((EE_CAMERAS[EE_CAMERA_INDEX].view * vec4(GetNormal(texCoord), 0.0f)).xyz); } -bool GetPosition(in vec2 texCoord, out vec3 position){ - float ndcDepth = texture(inDepth, texCoord).x; - if(ndcDepth == 1.0f) return false; - position = EE_DEPTH_TO_WORLD_POS(EE_CAMERA_INDEX, texCoord, ndcDepth); - return true; -} - bool GetViewPosition(in vec2 texCoord, out vec3 position){ float ndcDepth = texture(inDepth, texCoord).x; if(ndcDepth == 1.0f) return false; @@ -48,28 +31,6 @@ bool GetViewPosition(in vec2 texCoord, out vec3 position){ return true; } -vec3 GetPosition(in vec2 texCoord){ - float ndcDepth = texture(inDepth, texCoord).x; - return EE_DEPTH_TO_WORLD_POS(EE_CAMERA_INDEX, texCoord, ndcDepth); -} - -vec3 GetViewPosition(in vec2 texCoord){ - float ndcDepth = texture(inDepth, texCoord).x; - return EE_DEPTH_TO_VIEW_POS(EE_CAMERA_INDEX, texCoord, ndcDepth); -} - -vec3 GetScreenPosition(in vec2 texCoord){ - float ndcDepth = texture(inDepth, texCoord).x; - return EE_DEPTH_TO_CLIP_POS(texCoord, ndcDepth); -} - -bool GetScreenPosition(in vec2 texCoord, out vec3 position){ - float ndcDepth = texture(inDepth, texCoord).x; - if(ndcDepth == 1.0f) return false; - position = EE_DEPTH_TO_CLIP_POS(texCoord, ndcDepth); - return true; -} - void main() { vec2 texSize = textureSize(inColor, 0).xy; @@ -107,11 +68,10 @@ void main() vec2 frag = startFrag; uv = frag / texSize; - outSrcColor = vec4(endFrag / texSize, 0, 1); float deltaX = endFrag.x - startFrag.x; float deltaY = endFrag.y - startFrag.y; float useX = abs(deltaX) >= abs(deltaY) ? 1.0 : 0.0; - float delta = mix(abs(deltaY), abs(deltaX), useX) * clamp(resolution, 0.0, 1.0); + float delta = min(maxIterationCount, mix(abs(deltaY), abs(deltaX), useX) * resolution); vec2 increment = vec2(deltaX, deltaY) / max(delta, 0.001); float search0 = 0; @@ -120,7 +80,7 @@ void main() int hit0 = 0; int hit1 = 0; - float viewDistance = startView.y; + float viewDistance = startView.z; float depth = thickness; float i = 0; @@ -136,10 +96,10 @@ void main() search1 = clamp(search1, 0.0, 1.0); - viewDistance = (startView.y * endView.y) / mix(endView.y, startView.y, search1); - depth = viewDistance - positionTo.y; + viewDistance = (startView.z * endView.z) / mix(endView.z, startView.z, search1); + depth = positionTo.z - viewDistance; - if (valid && depth > 0 && depth < thickness) { + if (depth > 0 && depth < thickness) { hit0 = 1; break; } else { @@ -156,10 +116,10 @@ void main() uv.xy = frag / texSize; bool valid = GetViewPosition(uv, positionTo); - viewDistance = (startView.y * endView.y) / mix(endView.y, startView.y, search1); - depth = viewDistance - positionTo.y; + viewDistance = (startView.z * endView.z) / mix(endView.z, startView.z, search1); + depth = positionTo.z - viewDistance; - if (valid && depth > 0 && depth < thickness) { + if (depth > 0 && depth < thickness) { hit1 = 1; search1 = search0 + ((search1 - search0) / 2); } else { @@ -186,13 +146,12 @@ void main() * (uv.x < 0 || uv.x > 1 ? 0 : 1) * (uv.y < 0 || uv.y > 1 ? 0 : 1); + visibility = clamp(visibility, 0, 1); - + if(visibility != 0){ - outDstColorVisibility = clamp(vec4(texture(inColor, uv).rgb, visibility), vec4(0, 0, 0, 0), vec4(1, 1, 1, 1)); + outDstColorVisibility = max(vec4(texture(inColor, uv).rgb, visibility), vec4(0.0f)); }else{ outDstColorVisibility = vec4(0, 0, 0, 0); } - - } \ No newline at end of file diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Kernel.glsl b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Kernel.glsl index e68d4f08..900af303 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Kernel.glsl +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Kernel.glsl @@ -4,3 +4,4 @@ layout(set = EE_KERNEL_BLOCK_SET, binding = EE_KERNEL_BLOCK_BINDING) uniform EE_ vec4 EE_UNIFORM_KERNEL[MAX_KERNEL_AMOUNT]; vec4 EE_GAUSS_KERNEL[MAX_KERNEL_AMOUNT]; }; + diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Lighting.glsl b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Lighting.glsl index 5fd4e75b..beb2cb28 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Lighting.glsl +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Lighting.glsl @@ -1,3 +1,7 @@ + + +#include "VogelDisk.glsl" + layout(set = EE_PER_GROUP_SET, binding = 14) uniform sampler2DArray EE_DIRECTIONAL_LIGHT_SM; layout(set = EE_PER_GROUP_SET, binding = 15) uniform sampler2DArray EE_POINT_LIGHT_SM; layout(set = EE_PER_GROUP_SET, binding = 16) uniform sampler2D EE_SPOT_LIGHT_SM; @@ -221,18 +225,7 @@ vec3 EE_FUNC_SPOT_LIGHT(vec3 albedo, float specular, int i, vec3 normal, vec3 fr return (kD * albedo / PI + spec) * radiance * NdotL; } -vec2 VogelDiskSample(int sampleIndex, int sampleCount, float phi) -{ - float goldenAngle = 2.4; - float r = sqrt(float(sampleIndex + 0.5)) / sqrt(float(sampleCount)); - float theta = goldenAngle * sampleIndex + phi; - return r * vec2(cos(theta), sin(theta)); -} -float InterleavedGradientNoise(vec3 fragCoords) { - vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189); - return fract(dot(fragCoords, magic)); -} float EE_FUNC_DIRECTIONAL_LIGHT_SHADOW(int i, int splitIndex, vec3 fragPos, vec3 normal, float cameraFragDistance) { @@ -288,7 +281,7 @@ float EE_FUNC_DIRECTIONAL_LIGHT_SHADOW(int i, int splitIndex, vec3 fragPos, vec3 sampleAmount = int(EE_RENDER_INFO.shadow_sample_size * distanceFactor * distanceFactor); for (int i = 0; i < sampleAmount; i++) { - vec2 tex_coord = projCoords.xy + VogelDiskSample(i, sampleAmount, InterleavedGradientNoise(fragPos * 3141)) * (texelSize + 0.001); + vec2 tex_coord = projCoords.xy + EE_VOGEL_DISK_SAMPLE(i, sampleAmount, fragPos * 3141) * (texelSize + 0.001); float closestDepth = texture(EE_DIRECTIONAL_LIGHT_SM, vec3(tex_coord * texScale + texBase, splitIndex)).r; if (closestDepth == 0.0) continue; shadow += projCoords.z < closestDepth ? 1.0 : 0.0; @@ -334,7 +327,7 @@ float EE_FUNC_SPOT_LIGHT_SHADOW(int i, vec3 fragPos, float cameraFragDistance) { float shadow = 0.0; for (int i = 0; i < sampleAmount; i++) { - vec2 tex_coord = projCoords.xy + VogelDiskSample(i, sampleAmount, InterleavedGradientNoise(fragPos * 3141)) * (penumbraWidth + 0.001); + vec2 tex_coord = projCoords.xy + EE_VOGEL_DISK_SAMPLE(i, sampleAmount, fragPos * 3141) * (penumbraWidth + 0.001); float closestDepth = texture(EE_SPOT_LIGHT_SM, vec2(tex_coord * texScale + texBase)).r; if (closestDepth == 0.0) continue; shadow += projCoords.z < closestDepth ? 1.0 : 0.0; @@ -412,7 +405,7 @@ float EE_FUNC_POINT_LIGHT_SHADOW(int i, vec3 fragPos, float cameraFragDistance) sampleAmount = int(EE_RENDER_INFO.shadow_sample_size * distanceFactor * distanceFactor); for (int i = 0; i < sampleAmount; i++) { - vec2 tex_coord = projCoords.xy + VogelDiskSample(i, sampleAmount, InterleavedGradientNoise(fragPos * 3141)) * (penumbraWidth + 0.001); + vec2 tex_coord = projCoords.xy + EE_VOGEL_DISK_SAMPLE(i, sampleAmount, fragPos * 3141) * (penumbraWidth + 0.001); tex_coord.x = clamp(tex_coord.x, 1.0 / float(light.viewport_x_size), 1.0 - 1.0 / float(light.viewport_x_size)); tex_coord.y = clamp(tex_coord.y, 1.0 / float(light.viewport_x_size), 1.0 - 1.0 / float(light.viewport_x_size)); float closestDepth = texture(EE_POINT_LIGHT_SM, vec3(tex_coord * texScale + texBase, slice)).r; diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Math.glsl b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Math.glsl index b48b3cf3..c1ece24c 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Math.glsl +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/Math.glsl @@ -134,4 +134,5 @@ vec3 rotate_vec3(in vec4 q, in vec3 v) { vec3 q_vec = q.xyz; vec3 t = cross(q_vec, v) * 2.0; return v + t * q.w + cross(q_vec, t); -} \ No newline at end of file +} + diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/SSRConstants.glsl b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/SSRConstants.glsl index c2a9d1fa..7041bce4 100644 --- a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/SSRConstants.glsl +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/SSRConstants.glsl @@ -3,8 +3,7 @@ layout(push_constant) uniform EE_SSR_CONSTANTS{ int EE_CAMERA_INDEX; float maxDistance; float resolution; + int maxIterationCount; int initial_steps; float thickness; - int horizontal; - float weight[5]; }; diff --git a/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/VogelDisk.glsl b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/VogelDisk.glsl new file mode 100644 index 00000000..07b018fd --- /dev/null +++ b/EvoEngine_SDK/Internals/DefaultResources/Shaders/Includes/VogelDisk.glsl @@ -0,0 +1,17 @@ + +float EE_INTERLEAVED_GRADIENT_NOISE(vec3 position) { + vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189); + return fract(dot(position, magic)); +} + +vec2 EE_VOGEL_DISK_SAMPLE(int sampleIndex, int sampleCount, float phi) { + float goldenAngle = 2.4; + float r = sqrt(float(sampleIndex + 0.5)) / sqrt(float(sampleCount)); + float theta = goldenAngle * sampleIndex + phi; + return r * vec2(cos(theta), sin(theta)); +} + +vec2 EE_VOGEL_DISK_SAMPLE(int sampleIndex, int sampleCount, vec3 position) { + float phi = EE_INTERLEAVED_GRADIENT_NOISE(position); + return EE_VOGEL_DISK_SAMPLE(sampleIndex, sampleCount, phi); +} diff --git a/EvoEngine_SDK/include/Rendering/Camera.hpp b/EvoEngine_SDK/include/Rendering/Camera.hpp index c7f0fe13..41c215c7 100644 --- a/EvoEngine_SDK/include/Rendering/Camera.hpp +++ b/EvoEngine_SDK/include/Rendering/Camera.hpp @@ -70,15 +70,13 @@ class Camera final : public IPrivateComponent { bool OnInspect(const std::shared_ptr& editor_layer) override; void CollectAssetRef(std::vector& list) override; + const std::shared_ptr& GetGBufferDescriptorSet() const; + private: friend class Platform; friend class RenderLayer; friend class EditorLayer; friend struct CameraInfoBlock; - friend class PostProcessingStack; - friend class ScreenSpaceReflection; - friend class Bloom; - friend class Ssao; std::shared_ptr render_texture_; // Deferred shading GBuffer std::shared_ptr g_buffer_normal_ = {}; diff --git a/EvoEngine_SDK/include/Rendering/PBR/Lights.hpp b/EvoEngine_SDK/include/Rendering/PBR/Lights.hpp index 99fbdfc3..4f2a630b 100644 --- a/EvoEngine_SDK/include/Rendering/PBR/Lights.hpp +++ b/EvoEngine_SDK/include/Rendering/PBR/Lights.hpp @@ -19,7 +19,7 @@ class DirectionalLight : public IPrivateComponent { public: bool cast_shadow = true; glm::vec3 diffuse = glm::vec3(1.0f); - float diffuse_brightness = 1.f; + float diffuse_brightness = 3.f; float bias = 0.1f; float normal_offset = 0.05f; float light_size = 0.01f; @@ -49,7 +49,7 @@ class PointLight : public IPrivateComponent { float quadratic = 0.0015f; float bias = 0.05f; glm::vec3 diffuse = glm::vec3(1.0f); - float diffuse_brightness = 0.8f; + float diffuse_brightness = 3.f; float light_size = 0.01f; bool OnInspect(const std::shared_ptr& editor_layer) override; void OnCreate() override; @@ -80,7 +80,7 @@ class SpotLight : public IPrivateComponent { float quadratic = 0.0015f; float bias = 0.001f; glm::vec3 diffuse = glm::vec3(1.0f); - float diffuse_brightness = 0.8f; + float diffuse_brightness = 3.f; float light_size = 0.01f; bool OnInspect(const std::shared_ptr& editor_layer) override; void OnCreate() override; diff --git a/EvoEngine_SDK/include/Rendering/PostProcessing/PostProcessingStack.hpp b/EvoEngine_SDK/include/Rendering/PostProcessing/PostProcessingStack.hpp index 3cc4f37e..eade73f7 100644 --- a/EvoEngine_SDK/include/Rendering/PostProcessing/PostProcessingStack.hpp +++ b/EvoEngine_SDK/include/Rendering/PostProcessing/PostProcessingStack.hpp @@ -3,76 +3,149 @@ #include "IAsset.hpp" #include "RenderTexture.hpp" namespace evo_engine { +class ScreenSpaceReflection; +class Bloom; +class ScreenSpaceAmbientOcclusion; class Camera; -struct SsaoSettings {}; +class PostProcessingStack : public IAsset { + friend class Camera; + + void Resize(const glm::uvec2& size) const; + + inline static std::shared_ptr blur_layout; + inline static std::shared_ptr blur_pipeline; + + std::shared_ptr blur_horizontal_descriptor_set; // RENDER_TEXTURE_PRESENT_LAYOUT: 0 + std::shared_ptr blur_vertical_descriptor_set; // RENDER_TEXTURE_PRESENT_LAYOUT: 0 + public: + std::shared_ptr source_color_texture; + std::shared_ptr result_texture; + std::shared_ptr swap_texture; + + void OnCreate() override; + bool OnInspect(const std::shared_ptr& editor_layer) override; + void Process(const std::shared_ptr& target_camera) const; + std::shared_ptr screen_space_ambient_occlusion{}; + std::shared_ptr bloom{}; + std::shared_ptr screen_space_reflection{}; -struct BloomSettings {}; + void GaussianBlur(const glm::uvec2& size) const; + + bool enable_screen_space_ambient_occlusion = true; + bool enable_bloom = true; + bool enable_screen_space_reflection = true; +}; class IPostProcessing { public: - virtual void Process(const std::shared_ptr& render_texture0, - const std::shared_ptr& render_texture1, - const std::shared_ptr& render_texture2, - const std::shared_ptr& target_camera) const = 0; + virtual void Process(const PostProcessingStack& post_processing_stack, + const std::shared_ptr& target_camera) = 0; virtual bool OnInspect(const std::shared_ptr& editor_layer) { return false; + } + + virtual void BuildPipelines() = 0; +}; + +class ScreenSpaceAmbientOcclusion : public IPostProcessing { + public: + inline static std::shared_ptr blur_layout; + inline static std::shared_ptr blur_pipeline; + + std::shared_ptr blur_horizontal_descriptor_set; // RENDER_TEXTURE_PRESENT_LAYOUT: 0 + std::shared_ptr blur_vertical_descriptor_set; // RENDER_TEXTURE_PRESENT_LAYOUT: 0 + struct BlurPushConstant { + int horizontal = false; + float camera_near; + float camera_far; + float avoid_distance; + float weight[5] = {0.227027f, 0.1945946f, 0.1216216f, 0.054054f, 0.016216f}; + }; + float avoid_distance = 1.f; + inline static std::shared_ptr combine_layout; + std::shared_ptr combine_descriptor_set; + inline static std::shared_ptr geometry_pipeline; + inline static std::shared_ptr combine_pipeline; + /** + * \brief Parameters (you'd probably want to use them as uniforms to more easily tweak the effect) + */ + int kernel_size = 32; + float radius = 0.5f; + float bias = 0.01f; + float factor = 1.0f; + float intensity = 3.0f; + struct PushConstant { + int camera_index; + // parameters (you'd probably want to use them as uniforms to more easily tweak the effect) + int kernel_size; + float radius; + float bias; + float factor; + float intensity; }; + + bool OnInspect(const std::shared_ptr& editor_layer) override; + void Process(const PostProcessingStack& post_processing_stack, const std::shared_ptr& target_camera) override; + void BuildPipelines() override; }; class ScreenSpaceReflection : public IPostProcessing { public: - float max_distance = 0.5f; - float resolution = 0.3f; - int initial_steps = 5; - float thickness = 0.5f; + float max_distance = 10.f; + float resolution = 16.f; + int max_iteration_count = 64; + int initial_steps = 8; + float thickness = 0.3f; + bool blur = true; + struct PushConstant { int32_t camera_index = 0; float max_distance; float resolution; + int max_iteration_count = 5; int initial_steps; float thickness; - int horizontal = false; - float weight[5] = {0.227027f, 0.1945946f, 0.1216216f, 0.054054f, 0.016216f}; }; - inline static std::shared_ptr ssr_reflect_layout; - inline static std::shared_ptr ssr_blur_layout; - inline static std::shared_ptr ssr_combine_layout; - inline static std::shared_ptr ssr_reflect_pipeline; - inline static std::shared_ptr ssr_blur_pipeline; - inline static std::shared_ptr ssr_combine_pipeline; - - inline static std::shared_ptr ssr_reflect_descriptor_set; // SSR_REFLECT_LAYOUT: 0, 1, 2, 3 - inline static std::shared_ptr ssr_blur_horizontal_descriptor_set; // RENDER_TEXTURE_PRESENT_LAYOUT: 0 - inline static std::shared_ptr ssr_blur_vertical_descriptor_set; // RENDER_TEXTURE_PRESENT_LAYOUT: 0 - inline static std::shared_ptr ssr_combine_descriptor_set; // SSR_COMBINE: 0, 1 + inline static std::shared_ptr combine_layout; + inline static std::shared_ptr reflect_pipeline; + inline static std::shared_ptr combine_pipeline; + std::shared_ptr combine_descriptor_set; // SSR_COMBINE: 0, 1 bool OnInspect(const std::shared_ptr& editor_layer) override; - void Process(const std::shared_ptr& render_texture0, - const std::shared_ptr& render_texture1, - const std::shared_ptr& render_texture2, - const std::shared_ptr& target_camera) const override; - static void BuildPipelines(); + void Process(const PostProcessingStack& post_processing_stack, const std::shared_ptr& target_camera) override; + void BuildPipelines() override; }; -class PostProcessingStack : public IAsset { - friend class Camera; - std::shared_ptr render_texture0; - std::shared_ptr render_texture1; - std::shared_ptr render_texture2; - void Resize(const glm::uvec2& size) const; - +class Bloom : public IPostProcessing { public: - void OnCreate() override; - bool OnInspect(const std::shared_ptr& editor_layer) override; - void Process(const std::shared_ptr& target_camera) const; - SsaoSettings ssao_settings{}; - BloomSettings bloom_settings{}; - ScreenSpaceReflection screen_space_reflection{}; + inline static std::shared_ptr mix_layout; + std::shared_ptr mix_descriptor_set; + + inline static std::shared_ptr sampling_layout; + inline static std::shared_ptr downsampling_pipeline; + inline static std::shared_ptr upsampling_pipeline; + + struct DownsamplingPushConstant { + glm::vec2 source_resolution; + int mip_level; + int padding; + }; + + struct UpsamplingPushConstant { + float filter_radius; + }; - bool enable_screen_space_ambient_occlusion = false; - bool enable_bloom = false; - bool enable_screen_space_reflection = false; + float filter_radius = 0.001f; + int bloom_chain_length = 2; + std::vector> downsampling_descriptor_set; + std::vector> upsampling_descriptor_set; + inline static std::shared_ptr copy_pipeline; + inline static std::shared_ptr mix_pipeline; + bool OnInspect(const std::shared_ptr& editor_layer) override; + void Process(const PostProcessingStack& post_processing_stack, const std::shared_ptr& target_camera) override; + void BuildPipelines() override; }; + } // namespace evo_engine diff --git a/EvoEngine_SDK/include/Rendering/Texture/RenderTexture.hpp b/EvoEngine_SDK/include/Rendering/Texture/RenderTexture.hpp index 1168961e..675c016d 100644 --- a/EvoEngine_SDK/include/Rendering/Texture/RenderTexture.hpp +++ b/EvoEngine_SDK/include/Rendering/Texture/RenderTexture.hpp @@ -14,20 +14,20 @@ class RenderTexture { friend class Platform; friend class RenderLayer; std::shared_ptr color_image_ = {}; - std::shared_ptr color_image_view_ = {}; + std::vector> color_image_views_ = {}; std::shared_ptr depth_image_ = {}; - std::shared_ptr depth_image_view_ = {}; + std::vector> depth_image_views_ = {}; VkExtent3D extent_; VkImageViewType image_view_type_; std::shared_ptr color_sampler_ = {}; std::shared_ptr depth_sampler_ = {}; - ImTextureID color_im_texture_id_ = nullptr; + std::vector color_im_texture_ids_{}; bool color_ = true; bool depth_ = true; - void Initialize(const RenderTextureCreateInfo& render_texture_create_info); + void Initialize(const RenderTextureCreateInfo& render_texture_create_info, uint32_t mip_levels = 1); std::shared_ptr present_descriptor_set_; std::shared_ptr storage_descriptor_set_; @@ -37,27 +37,31 @@ class RenderTexture { void Clear(VkCommandBuffer vk_command_buffer) const; explicit RenderTexture(const RenderTextureCreateInfo& render_texture_create_info); - void Resize(VkExtent3D extent); + void Resize(VkExtent3D extent, uint32_t mip_level = 1); void AppendColorAttachmentInfos(std::vector& attachment_infos, VkAttachmentLoadOp load_op, - VkAttachmentStoreOp store_op) const; + VkAttachmentStoreOp store_op, uint32_t mip_level = 0) const; [[nodiscard]] VkRenderingAttachmentInfo GetDepthAttachmentInfo(VkAttachmentLoadOp load_op, - VkAttachmentStoreOp store_op) const; + VkAttachmentStoreOp store_op, + uint32_t mip_level = 0) const; [[nodiscard]] VkExtent3D GetExtent() const; [[nodiscard]] VkImageViewType GetImageViewType() const; - + [[nodiscard]] uint32_t GetMipLevels() const; [[nodiscard]] const std::shared_ptr& GetColorSampler() const; [[nodiscard]] const std::shared_ptr& GetDepthSampler() const; [[nodiscard]] const std::shared_ptr& GetColorImage(); [[nodiscard]] const std::shared_ptr& GetDepthImage(); - [[nodiscard]] const std::shared_ptr& GetColorImageView(); - [[nodiscard]] const std::shared_ptr& GetDepthImageView(); + [[nodiscard]] const std::shared_ptr& GetColorImageView(uint32_t mip_index = 0); + [[nodiscard]] const std::shared_ptr& GetDepthImageView(uint32_t mip_index = 0); void Render(VkCommandBuffer vk_command_buffer, VkAttachmentLoadOp load_op, VkAttachmentStoreOp store_op, - const std::function& func) const; - [[nodiscard]] ImTextureID GetColorImTextureId() const; + const std::function& func, uint32_t mip_level = 0) const; + [[nodiscard]] ImTextureID GetColorImTextureId(uint32_t mip_index = 0) const; void ApplyGraphicsPipelineStates(GraphicsPipelineStates& global_pipeline_state) const; [[maybe_unused]] bool Save(const std::filesystem::path& path) const; void StoreToPng(const std::string& path, int resize_x = -1, int resize_y = -1, unsigned compression_level = 8) const; void StoreToJpg(const std::string& path, int resize_x = -1, int resize_y = -1, unsigned quality = 100) const; void StoreToHdr(const std::string& path, int resize_x = -1, int resize_y = -1, unsigned quality = 100) const; + + const std::shared_ptr& GetPresentDescriptorSet() const; + const std::shared_ptr& GetStorageDescriptorSet() const; }; } // namespace evo_engine diff --git a/EvoEngine_SDK/src/Camera.cpp b/EvoEngine_SDK/src/Camera.cpp index afc95e70..8b923757 100644 --- a/EvoEngine_SDK/src/Camera.cpp +++ b/EvoEngine_SDK/src/Camera.cpp @@ -541,3 +541,7 @@ void Camera::CollectAssetRef(std::vector& list) { list.push_back(skybox); list.push_back(post_processing_stack_ref); } + +const std::shared_ptr& Camera::GetGBufferDescriptorSet() const { + return g_buffer_descriptor_set_; +} diff --git a/EvoEngine_SDK/src/EditorLayer.cpp b/EvoEngine_SDK/src/EditorLayer.cpp index 582aa028..f902901f 100644 --- a/EvoEngine_SDK/src/EditorLayer.cpp +++ b/EvoEngine_SDK/src/EditorLayer.cpp @@ -7,6 +7,7 @@ #include "Mesh.hpp" #include "MeshRenderer.hpp" #include "Platform.hpp" +#include "PostProcessingStack.hpp" #include "Prefab.hpp" #include "ProjectManager.hpp" #include "RenderLayer.hpp" @@ -116,6 +117,7 @@ void EditorLayer::OnCreate() { scene_camera->clear_color = glm::vec3(59.0f / 255.0f, 85 / 255.0f, 143 / 255.f); scene_camera->use_clear_color = false; scene_camera->OnCreate(); + scene_camera->post_processing_stack_ref = ProjectManager::CreateTemporaryAsset(); RegisterEditorCamera(scene_camera); scene_camera_handle_ = scene_camera->GetHandle(); } diff --git a/EvoEngine_SDK/src/PostProcessingStack.cpp b/EvoEngine_SDK/src/PostProcessingStack.cpp index d521e827..76a2da0a 100644 --- a/EvoEngine_SDK/src/PostProcessingStack.cpp +++ b/EvoEngine_SDK/src/PostProcessingStack.cpp @@ -12,84 +12,232 @@ #include "Shader.hpp" using namespace evo_engine; -bool ScreenSpaceReflection::OnInspect(const std::shared_ptr& editor_layer) { +bool Bloom::OnInspect(const std::shared_ptr& editor_layer) { bool changed = false; - if (ImGui::DragFloat("Max distance", &max_distance, 0.01f, 0.01f, 1.0f)) - changed = false; - if (ImGui::DragFloat("Resolution", &resolution, 0.01f, 0.0f, 1.0f)) - changed = false; - if (ImGui::DragInt("Steps", &initial_steps, 1, 1, 16)) - changed = false; - if (ImGui::DragFloat("Thickness", &thickness, 0.01f, 0.0f, 1.0f)) - changed = false; - + if (ImGui::DragFloat("Filter radius", &filter_radius, 0.0001f, 0.0001f, .1f)) { + changed = true; + } + if (ImGui::DragInt("Chain length", &bloom_chain_length, 1, 0, 10)) { + changed = true; + } if (ImGui::Button("Rebuild pipelines")) { BuildPipelines(); } - return changed; } -void ScreenSpaceReflection::Process(const std::shared_ptr& render_texture0, - const std::shared_ptr& render_texture1, - const std::shared_ptr& render_texture2, - const std::shared_ptr& target_camera) const { - if (!ssr_reflect_pipeline || !ssr_blur_pipeline || !ssr_combine_pipeline || !ssr_reflect_pipeline->Initialized() || - !ssr_blur_pipeline->Initialized() || !ssr_combine_pipeline->Initialized()) +void Bloom::Process(const PostProcessingStack& post_processing_stack, const std::shared_ptr& target_camera) { + if (!copy_pipeline || !copy_pipeline->Initialized() || !downsampling_pipeline || + !downsampling_pipeline->Initialized() || !upsampling_pipeline || !upsampling_pipeline->Initialized() || + !mix_pipeline || !mix_pipeline->Initialized()) return; + const auto render_layer = Application::GetLayer(); - if (!ssr_reflect_descriptor_set) { - ssr_reflect_descriptor_set = std::make_shared(ssr_reflect_layout); - } - if (!ssr_blur_horizontal_descriptor_set) { - ssr_blur_horizontal_descriptor_set = std::make_shared(ssr_blur_layout); - } - if (!ssr_blur_vertical_descriptor_set) { - ssr_blur_vertical_descriptor_set = std::make_shared(ssr_blur_layout); - } - if (!ssr_combine_descriptor_set) { - ssr_combine_descriptor_set = std::make_shared(ssr_combine_layout); - } - { - VkDescriptorImageInfo image_info; - image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - image_info.imageView = target_camera->GetRenderTexture()->GetDepthImageView()->GetVkImageView(); - image_info.sampler = target_camera->GetRenderTexture()->GetDepthSampler()->GetVkSampler(); - ssr_reflect_descriptor_set->UpdateImageDescriptorBinding(17, image_info); - image_info.imageView = target_camera->g_buffer_normal_view_->GetVkImageView(); - image_info.sampler = target_camera->g_buffer_normal_sampler_->GetVkSampler(); - ssr_reflect_descriptor_set->UpdateImageDescriptorBinding(18, image_info); - image_info.imageView = target_camera->g_buffer_material_view_->GetVkImageView(); - image_info.sampler = target_camera->g_buffer_material_sampler_->GetVkSampler(); - ssr_reflect_descriptor_set->UpdateImageDescriptorBinding(19, image_info); - - image_info.imageView = target_camera->GetRenderTexture()->GetColorImageView()->GetVkImageView(); - image_info.sampler = target_camera->GetRenderTexture()->GetColorSampler()->GetVkSampler(); - ssr_reflect_descriptor_set->UpdateImageDescriptorBinding(20, image_info); - } - { - VkDescriptorImageInfo image_info; - image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - image_info.imageView = render_texture1->GetColorImageView()->GetVkImageView(); - image_info.sampler = render_texture1->GetColorSampler()->GetVkSampler(); - ssr_blur_horizontal_descriptor_set->UpdateImageDescriptorBinding(0, image_info); - } - { - VkDescriptorImageInfo image_info; - image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - image_info.imageView = render_texture2->GetColorImageView()->GetVkImageView(); - image_info.sampler = render_texture2->GetColorSampler()->GetVkSampler(); - ssr_blur_vertical_descriptor_set->UpdateImageDescriptorBinding(0, image_info); - } + const auto mip_levels = post_processing_stack.result_texture->GetMipLevels(); + const auto base_extent = post_processing_stack.result_texture->GetColorImage()->GetExtent(); + const auto mesh = Resources::GetResource("PRIMITIVE_TEX_PASS_THROUGH"); + + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { +#pragma region Viewport and scissor + VkRect2D render_area; + render_area.offset = {0, 0}; + render_area.extent.width = target_camera->GetSize().x; + render_area.extent.height = target_camera->GetSize().y; + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = target_camera->GetSize().x; + viewport.height = target_camera->GetSize().y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = target_camera->GetSize().x; + scissor.extent.height = target_camera->GetSize().y; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + + std::vector color_attachment_infos; + VkRenderingInfo render_info2{}; + render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + render_info2.renderArea = render_area; + render_info2.layerCount = 1; + render_info2.pDepthAttachment = VK_NULL_HANDLE; + + // Input texture + target_camera->GetRenderTexture()->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + // Attachments + post_processing_stack.source_color_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.source_color_texture->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + post_processing_stack.result_texture->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + + vkCmdBeginRendering(vk_command_buffer, &render_info2); + copy_pipeline->states.depth_test = false; + copy_pipeline->states.color_blend_attachment_states.clear(); + copy_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : copy_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + copy_pipeline->Bind(vk_command_buffer); + copy_pipeline->BindDescriptorSet(vk_command_buffer, 0, + render_layer->GetPerFrameDescriptorSet()->GetVkDescriptorSet()); + copy_pipeline->BindDescriptorSet( + vk_command_buffer, 1, target_camera->GetRenderTexture()->GetPresentDescriptorSet()->GetVkDescriptorSet()); + copy_pipeline->states.view_port = viewport; + copy_pipeline->states.scissor = scissor; + mesh->DrawIndexed(vk_command_buffer, copy_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + }); + + downsampling_descriptor_set.clear(); + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + for (int target_mip_level = 1; target_mip_level < glm::min(static_cast(mip_levels), bloom_chain_length + 1); + ++target_mip_level) { + const auto current_descriptor_set = + downsampling_descriptor_set.emplace_back(std::make_shared(sampling_layout)); + + VkDescriptorImageInfo descriptor_image_info; + descriptor_image_info.imageView = + post_processing_stack.result_texture->GetColorImageView(target_mip_level - 1)->GetVkImageView(); + descriptor_image_info.imageLayout = post_processing_stack.result_texture->GetColorImage()->GetLayout(); + descriptor_image_info.sampler = post_processing_stack.result_texture->GetColorSampler()->GetVkSampler(); + current_descriptor_set->UpdateImageDescriptorBinding(0, descriptor_image_info); + const float mip_width = static_cast(base_extent.width) * glm::pow(0.5f, target_mip_level); + const float mip_height = static_cast(base_extent.height) * glm::pow(0.5f, target_mip_level); + if (mip_width < 1.f || mip_height < 1.f) + continue; +#pragma region Viewport and scissor + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = mip_width; + viewport.height = mip_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = mip_width; + scissor.extent.height = mip_height; + downsampling_pipeline->states.view_port = viewport; + downsampling_pipeline->states.scissor = scissor; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + post_processing_stack.result_texture->Render( + vk_command_buffer, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, + [&]() { + downsampling_pipeline->states.cull_mode = VK_CULL_MODE_NONE; + downsampling_pipeline->states.color_blend_attachment_states.clear(); + downsampling_pipeline->states.color_blend_attachment_states.resize(1); + for (auto& i : downsampling_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + downsampling_pipeline->Bind(vk_command_buffer); + downsampling_pipeline->BindDescriptorSet(vk_command_buffer, 0, + render_layer->GetPerFrameDescriptorSet()->GetVkDescriptorSet()); + downsampling_pipeline->BindDescriptorSet(vk_command_buffer, 1, + current_descriptor_set->GetVkDescriptorSet()); + DownsamplingPushConstant push_constant; + push_constant.mip_level = target_mip_level - 1; + push_constant.source_resolution = {mip_width, mip_height}; + downsampling_pipeline->PushConstant(vk_command_buffer, 0, push_constant); + mesh->DrawIndexed(vk_command_buffer, downsampling_pipeline->states, 1); + }, + target_mip_level); + Platform::EverythingBarrier(vk_command_buffer); + } + }); + + upsampling_descriptor_set.clear(); + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + for (int src_mip_level = glm::min(static_cast(mip_levels), bloom_chain_length + 1) - 1; src_mip_level > 0; + --src_mip_level) { + const auto current_descriptor_set = + upsampling_descriptor_set.emplace_back(std::make_shared(sampling_layout)); + + VkDescriptorImageInfo descriptor_image_info; + descriptor_image_info.imageView = + post_processing_stack.result_texture->GetColorImageView(src_mip_level)->GetVkImageView(); + descriptor_image_info.imageLayout = post_processing_stack.result_texture->GetColorImage()->GetLayout(); + descriptor_image_info.sampler = post_processing_stack.result_texture->GetColorSampler()->GetVkSampler(); + current_descriptor_set->UpdateImageDescriptorBinding(0, descriptor_image_info); + + const float prev_mip_width = static_cast(base_extent.width) * glm::pow(0.5f, src_mip_level); + const float prev_mip_height = static_cast(base_extent.height) * glm::pow(0.5f, src_mip_level); + if (prev_mip_width < 1.f || prev_mip_height < 1.f) + continue; + + const float mip_width = static_cast(base_extent.width) * glm::pow(0.5f, src_mip_level - 1); + const float mip_height = static_cast(base_extent.height) * glm::pow(0.5f, src_mip_level - 1); + +#pragma region Viewport and scissor + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = mip_width; + viewport.height = mip_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = mip_width; + scissor.extent.height = mip_height; + upsampling_pipeline->states.view_port = viewport; + upsampling_pipeline->states.scissor = scissor; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + post_processing_stack.result_texture->Render( + vk_command_buffer, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, + [&]() { + upsampling_pipeline->states.cull_mode = VK_CULL_MODE_NONE; + upsampling_pipeline->states.color_blend_attachment_states.clear(); + upsampling_pipeline->states.color_blend_attachment_states.resize(1); + for (auto& i : upsampling_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + upsampling_pipeline->Bind(vk_command_buffer); + upsampling_pipeline->BindDescriptorSet(vk_command_buffer, 0, + render_layer->GetPerFrameDescriptorSet()->GetVkDescriptorSet()); + upsampling_pipeline->BindDescriptorSet(vk_command_buffer, 1, current_descriptor_set->GetVkDescriptorSet()); + + UpsamplingPushConstant push_constant; + push_constant.filter_radius = filter_radius; + upsampling_pipeline->PushConstant(vk_command_buffer, 0, push_constant); + mesh->DrawIndexed(vk_command_buffer, upsampling_pipeline->states, 1); + }, + src_mip_level - 1); + Platform::EverythingBarrier(vk_command_buffer); + } + }); + { VkDescriptorImageInfo image_info; image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - image_info.imageView = render_texture0->GetColorImageView()->GetVkImageView(); - image_info.sampler = render_texture0->GetColorSampler()->GetVkSampler(); - ssr_combine_descriptor_set->UpdateImageDescriptorBinding(0, image_info); - image_info.imageView = render_texture1->GetColorImageView()->GetVkImageView(); - image_info.sampler = render_texture1->GetColorSampler()->GetVkSampler(); - ssr_combine_descriptor_set->UpdateImageDescriptorBinding(1, image_info); + image_info.imageView = post_processing_stack.source_color_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = post_processing_stack.source_color_texture->GetColorSampler()->GetVkSampler(); + mix_descriptor_set->UpdateImageDescriptorBinding(0, image_info); + image_info.imageView = post_processing_stack.result_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = post_processing_stack.result_texture->GetColorSampler()->GetVkSampler(); + mix_descriptor_set->UpdateImageDescriptorBinding(1, image_info); } Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { @@ -112,220 +260,124 @@ void ScreenSpaceReflection::Process(const std::shared_ptr& render scissor.extent.height = target_camera->GetSize().y; #pragma endregion GeometryStorage::BindVertices(vk_command_buffer); - { - PushConstant push_constant{}; - push_constant.max_distance = max_distance; - push_constant.resolution = resolution; - push_constant.initial_steps = initial_steps; - push_constant.thickness = thickness; - push_constant.camera_index = - render_layer->GetCurrentRenderInstanceStorage()->GetCameraIndex(target_camera->GetHandle()); - const auto mesh = Resources::GetResource("PRIMITIVE_TEX_PASS_THROUGH"); - std::vector color_attachment_infos; - VkRenderingInfo render_info2{}; - render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; - render_info2.renderArea = render_area; - render_info2.layerCount = 1; - render_info2.pDepthAttachment = VK_NULL_HANDLE; - - // Input texture - target_camera->TransitGBufferImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - target_camera->render_texture_->GetDepthImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - target_camera->render_texture_->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - // Attachments - render_texture0->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - render_texture1->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - render_texture0->AppendColorAttachmentInfos(color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE); - render_texture1->AppendColorAttachmentInfos(color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE); - render_info2.colorAttachmentCount = color_attachment_infos.size(); - render_info2.pColorAttachments = color_attachment_infos.data(); - - { - vkCmdBeginRendering(vk_command_buffer, &render_info2); - ssr_reflect_pipeline->states.depth_test = false; - ssr_reflect_pipeline->states.color_blend_attachment_states.clear(); - ssr_reflect_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); - for (auto& i : ssr_reflect_pipeline->states.color_blend_attachment_states) { - i.colorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - i.blendEnable = VK_FALSE; - } - ssr_reflect_pipeline->Bind(vk_command_buffer); - ssr_reflect_pipeline->BindDescriptorSet(vk_command_buffer, 0, - render_layer->GetPerFrameDescriptorSet()->GetVkDescriptorSet()); - ssr_reflect_pipeline->BindDescriptorSet(vk_command_buffer, 1, ssr_reflect_descriptor_set->GetVkDescriptorSet()); - ssr_reflect_pipeline->states.view_port = viewport; - ssr_reflect_pipeline->states.scissor = scissor; - - ssr_reflect_pipeline->PushConstant(vk_command_buffer, 0, push_constant); - mesh->DrawIndexed(vk_command_buffer, ssr_reflect_pipeline->states, 1); - vkCmdEndRendering(vk_command_buffer); - } - // Input texture - render_texture1->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - // Attachments - color_attachment_infos.clear(); - render_texture2->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - render_texture2->AppendColorAttachmentInfos(color_attachment_infos, VK_ATTACHMENT_LOAD_OP_CLEAR, - VK_ATTACHMENT_STORE_OP_STORE); - render_info2.colorAttachmentCount = color_attachment_infos.size(); - render_info2.pColorAttachments = color_attachment_infos.data(); - { - vkCmdBeginRendering(vk_command_buffer, &render_info2); - ssr_blur_pipeline->states.depth_test = false; - ssr_blur_pipeline->states.color_blend_attachment_states.clear(); - ssr_blur_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); - for (auto& i : ssr_blur_pipeline->states.color_blend_attachment_states) { - i.colorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - i.blendEnable = VK_FALSE; - } - ssr_blur_pipeline->Bind(vk_command_buffer); - ssr_blur_pipeline->BindDescriptorSet(vk_command_buffer, 0, - ssr_blur_horizontal_descriptor_set->GetVkDescriptorSet()); - ssr_blur_pipeline->states.view_port = viewport; - ssr_blur_pipeline->states.scissor = scissor; - push_constant.horizontal = true; - ssr_blur_pipeline->PushConstant(vk_command_buffer, 0, push_constant); - mesh->DrawIndexed(vk_command_buffer, ssr_blur_pipeline->states, 1); - vkCmdEndRendering(vk_command_buffer); - } - // Input texture - render_texture2->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - // Attachments - color_attachment_infos.clear(); - render_texture1->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - render_texture1->AppendColorAttachmentInfos(color_attachment_infos, VK_ATTACHMENT_LOAD_OP_CLEAR, - VK_ATTACHMENT_STORE_OP_STORE); - render_info2.colorAttachmentCount = color_attachment_infos.size(); - render_info2.pColorAttachments = color_attachment_infos.data(); - { - vkCmdBeginRendering(vk_command_buffer, &render_info2); - ssr_blur_pipeline->states.depth_test = false; - ssr_blur_pipeline->states.color_blend_attachment_states.clear(); - ssr_blur_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); - for (auto& i : ssr_blur_pipeline->states.color_blend_attachment_states) { - i.colorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - i.blendEnable = VK_FALSE; - } - ssr_blur_pipeline->Bind(vk_command_buffer); - ssr_blur_pipeline->BindDescriptorSet(vk_command_buffer, 0, - ssr_blur_vertical_descriptor_set->GetVkDescriptorSet()); - ssr_blur_pipeline->states.view_port = viewport; - ssr_blur_pipeline->states.scissor = scissor; - push_constant.horizontal = false; - ssr_blur_pipeline->PushConstant(vk_command_buffer, 0, push_constant); - mesh->DrawIndexed(vk_command_buffer, ssr_blur_pipeline->states, 1); - vkCmdEndRendering(vk_command_buffer); - } - // Input texture - render_texture0->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - render_texture1->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); - // Attachments - color_attachment_infos.clear(); - target_camera->GetRenderTexture()->GetColorImage()->TransitImageLayout(vk_command_buffer, - VK_IMAGE_LAYOUT_GENERAL); - target_camera->GetRenderTexture()->AppendColorAttachmentInfos( - color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); - render_info2.colorAttachmentCount = color_attachment_infos.size(); - render_info2.pColorAttachments = color_attachment_infos.data(); - { - vkCmdBeginRendering(vk_command_buffer, &render_info2); - ssr_combine_pipeline->states.depth_test = false; - ssr_combine_pipeline->states.color_blend_attachment_states.clear(); - ssr_combine_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); - for (auto& i : ssr_combine_pipeline->states.color_blend_attachment_states) { - i.colorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - i.blendEnable = VK_FALSE; - } - ssr_combine_pipeline->Bind(vk_command_buffer); - ssr_combine_pipeline->BindDescriptorSet(vk_command_buffer, 0, ssr_combine_descriptor_set->GetVkDescriptorSet()); - ssr_combine_pipeline->states.view_port = viewport; - ssr_combine_pipeline->states.scissor = scissor; - ssr_combine_pipeline->PushConstant(vk_command_buffer, 0, push_constant); - mesh->DrawIndexed(vk_command_buffer, ssr_combine_pipeline->states, 1); - vkCmdEndRendering(vk_command_buffer); + std::vector color_attachment_infos{}; + VkRenderingInfo render_info2{}; + render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + render_info2.renderArea = render_area; + render_info2.layerCount = 1; + render_info2.pDepthAttachment = VK_NULL_HANDLE; + + // Input texture + + target_camera->GetRenderTexture()->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + // Attachments + post_processing_stack.source_color_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + + target_camera->GetRenderTexture()->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + { + vkCmdBeginRendering(vk_command_buffer, &render_info2); + mix_pipeline->states.depth_test = false; + mix_pipeline->states.color_blend_attachment_states.clear(); + mix_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : mix_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; } + mix_pipeline->Bind(vk_command_buffer); + mix_pipeline->BindDescriptorSet(vk_command_buffer, 0, + render_layer->GetPerFrameDescriptorSet()->GetVkDescriptorSet()); + mix_pipeline->BindDescriptorSet(vk_command_buffer, 1, mix_descriptor_set->GetVkDescriptorSet()); + mix_pipeline->states.view_port = viewport; + mix_pipeline->states.scissor = scissor; + mesh->DrawIndexed(vk_command_buffer, mix_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); } }); } -void ScreenSpaceReflection::BuildPipelines() { - ssr_reflect_layout = std::make_shared(); - ssr_reflect_layout->PushDescriptorBinding(17, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, - 0); - ssr_reflect_layout->PushDescriptorBinding(18, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, - 0); - ssr_reflect_layout->PushDescriptorBinding(19, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, - 0); - ssr_reflect_layout->PushDescriptorBinding(20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, - 0); - ssr_reflect_layout->Initialize(); - - ssr_blur_layout = std::make_shared(); - ssr_blur_layout->PushDescriptorBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); - ssr_blur_layout->Initialize(); - - ssr_combine_layout = std::make_shared(); - ssr_combine_layout->PushDescriptorBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, - 0); - ssr_combine_layout->PushDescriptorBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, - 0); - ssr_combine_layout->Initialize(); - - ssr_reflect_pipeline = std::make_shared(); - ssr_reflect_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); - ssr_reflect_pipeline->fragment_shader = Shader::CreateTemporary( +void Bloom::BuildPipelines() { + mix_layout = std::make_shared(); + mix_layout->PushDescriptorBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + mix_layout->PushDescriptorBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + mix_layout->Initialize(); + + if (!mix_descriptor_set) { + mix_descriptor_set = std::make_shared(mix_layout); + } + + sampling_layout = std::make_shared(); + sampling_layout->PushDescriptorBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + sampling_layout->Initialize(); + + downsampling_pipeline = std::make_shared(); + downsampling_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + downsampling_pipeline->fragment_shader = Shader::CreateTemporary( ShaderType::Fragment, Platform::Constants::shader_global_defines, - std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/SSRReflect.frag"); - ssr_reflect_pipeline->geometry_type = GeometryType::Mesh; - ssr_reflect_pipeline->descriptor_set_layouts.emplace_back(RenderLayer::per_frame_layout); - ssr_reflect_pipeline->descriptor_set_layouts.emplace_back(ssr_reflect_layout); - ssr_reflect_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; - ssr_reflect_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; - ssr_reflect_pipeline->color_attachment_formats = {2, Platform::Constants::render_texture_color}; - auto& ssr_reflect_pipeline_push_constant_range = ssr_reflect_pipeline->push_constant_ranges.emplace_back(); - ssr_reflect_pipeline_push_constant_range.size = sizeof(PushConstant); - ssr_reflect_pipeline_push_constant_range.offset = 0; - ssr_reflect_pipeline_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; - ssr_reflect_pipeline->Initialize(); - - ssr_blur_pipeline = std::make_shared(); - ssr_blur_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); - ssr_blur_pipeline->fragment_shader = - Shader::CreateTemporary(ShaderType::Fragment, std::filesystem::path("./DefaultResources") / - "Shaders/Graphics/Fragment/PostProcessing/SSRBlur.frag"); - ssr_blur_pipeline->geometry_type = GeometryType::Mesh; - ssr_blur_pipeline->descriptor_set_layouts.emplace_back(ssr_blur_layout); - ssr_blur_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; - ssr_blur_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; - ssr_blur_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; - auto& ssr_blur_pipeline_push_constant_range = ssr_blur_pipeline->push_constant_ranges.emplace_back(); - ssr_blur_pipeline_push_constant_range.size = sizeof(PushConstant); - ssr_blur_pipeline_push_constant_range.offset = 0; - ssr_blur_pipeline_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; - ssr_blur_pipeline->Initialize(); - - ssr_combine_pipeline = std::make_shared(); - ssr_combine_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); - ssr_combine_pipeline->fragment_shader = - Shader::CreateTemporary(ShaderType::Fragment, std::filesystem::path("./DefaultResources") / - "Shaders/Graphics/Fragment/PostProcessing/SSRCombine.frag"); - ssr_combine_pipeline->geometry_type = GeometryType::Mesh; - ssr_combine_pipeline->descriptor_set_layouts.emplace_back(ssr_combine_layout); - ssr_combine_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; - ssr_combine_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; - ssr_combine_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; - auto& ssr_combine_pipeline_push_constant_range = ssr_combine_pipeline->push_constant_ranges.emplace_back(); - ssr_combine_pipeline_push_constant_range.size = sizeof(PushConstant); - ssr_combine_pipeline_push_constant_range.offset = 0; - ssr_combine_pipeline_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; - ssr_combine_pipeline->Initialize(); + std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/BloomDownsampling.frag"); + + downsampling_pipeline->geometry_type = GeometryType::Mesh; + downsampling_pipeline->descriptor_set_layouts.emplace_back(RenderLayer::per_frame_layout); + downsampling_pipeline->descriptor_set_layouts.emplace_back(sampling_layout); + downsampling_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + downsampling_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + downsampling_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; + auto& downsampling_push_constant_range = downsampling_pipeline->push_constant_ranges.emplace_back(); + downsampling_push_constant_range.size = sizeof(DownsamplingPushConstant); + downsampling_push_constant_range.offset = 0; + downsampling_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; + downsampling_pipeline->Initialize(); + + upsampling_pipeline = std::make_shared(); + upsampling_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + upsampling_pipeline->fragment_shader = Shader::CreateTemporary( + ShaderType::Fragment, Platform::Constants::shader_global_defines, + std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/BloomUpsampling.frag"); + + upsampling_pipeline->geometry_type = GeometryType::Mesh; + upsampling_pipeline->descriptor_set_layouts.emplace_back(RenderLayer::per_frame_layout); + upsampling_pipeline->descriptor_set_layouts.emplace_back(sampling_layout); + upsampling_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + upsampling_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + upsampling_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; + auto& upsampling_push_constant_range = upsampling_pipeline->push_constant_ranges.emplace_back(); + upsampling_push_constant_range.size = sizeof(UpsamplingPushConstant); + upsampling_push_constant_range.offset = 0; + upsampling_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; + upsampling_pipeline->Initialize(); + + copy_pipeline = std::make_shared(); + copy_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + copy_pipeline->fragment_shader = Shader::CreateTemporary( + ShaderType::Fragment, Platform::Constants::shader_global_defines, + std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/BloomCopy.frag"); + copy_pipeline->geometry_type = GeometryType::Mesh; + copy_pipeline->descriptor_set_layouts.emplace_back(RenderLayer::per_frame_layout); + copy_pipeline->descriptor_set_layouts.emplace_back(RenderTexture::render_texture_present_layout); + copy_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + copy_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + copy_pipeline->color_attachment_formats = {2, Platform::Constants::render_texture_color}; + copy_pipeline->Initialize(); + + mix_pipeline = std::make_shared(); + mix_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + mix_pipeline->fragment_shader = Shader::CreateTemporary( + ShaderType::Fragment, Platform::Constants::shader_global_defines, + std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/BloomMix.frag"); + mix_pipeline->geometry_type = GeometryType::Mesh; + mix_pipeline->descriptor_set_layouts.emplace_back(RenderLayer::per_frame_layout); + mix_pipeline->descriptor_set_layouts.emplace_back(mix_layout); + mix_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + mix_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + mix_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; + mix_pipeline->Initialize(); } void PostProcessingStack::Resize(const glm::uvec2& size) const { @@ -333,29 +385,64 @@ void PostProcessingStack::Resize(const glm::uvec2& size) const { return; if (size.x > 16384 || size.y >= 16384) return; - render_texture0->Resize({size.x, size.y, 1}); - render_texture1->Resize({size.x, size.y, 1}); - render_texture2->Resize({size.x, size.y, 1}); + const uint32_t mip_levels = static_cast(std::floor(std::log2(std::max(size.x, size.y)))) + 1; + source_color_texture->Resize({size.x, size.y, 1}); + result_texture->Resize({size.x, size.y, 1}, mip_levels); + swap_texture->Resize({size.x, size.y, 1}); } void PostProcessingStack::OnCreate() { + if (!blur_layout) { + blur_layout = std::make_shared(); + blur_layout->PushDescriptorBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + blur_layout->Initialize(); + } + + if (!blur_horizontal_descriptor_set) { + blur_horizontal_descriptor_set = std::make_shared(blur_layout); + } + if (!blur_vertical_descriptor_set) { + blur_vertical_descriptor_set = std::make_shared(blur_layout); + } + RenderTextureCreateInfo render_texture_create_info{}; render_texture_create_info.depth = false; - render_texture0 = std::make_unique(render_texture_create_info); - render_texture1 = std::make_unique(render_texture_create_info); - render_texture2 = std::make_unique(render_texture_create_info); + source_color_texture = std::make_unique(render_texture_create_info); + result_texture = std::make_unique(render_texture_create_info); + swap_texture = std::make_unique(render_texture_create_info); + screen_space_ambient_occlusion = std::make_shared(); + bloom = std::make_shared(); + screen_space_reflection = std::make_shared(); - screen_space_reflection.BuildPipelines(); + screen_space_ambient_occlusion->BuildPipelines(); + bloom->BuildPipelines(); + screen_space_reflection->BuildPipelines(); } bool PostProcessingStack::OnInspect(const std::shared_ptr& editor_layer) { bool changed = false; + if (ImGui::Checkbox("SSAO", &enable_screen_space_ambient_occlusion)) + changed = true; + + if (enable_screen_space_ambient_occlusion && ImGui::TreeNodeEx("SSAO", ImGuiTreeNodeFlags_DefaultOpen)) { + if (screen_space_ambient_occlusion->OnInspect(editor_layer)) + changed = true; + ImGui::TreePop(); + } + if (ImGui::Checkbox("Bloom", &enable_bloom)) + changed = true; + + if (enable_bloom && ImGui::TreeNodeEx("Bloom", ImGuiTreeNodeFlags_DefaultOpen)) { + if (bloom->OnInspect(editor_layer)) + changed = true; + ImGui::TreePop(); + } if (ImGui::Checkbox("SSR", &enable_screen_space_reflection)) changed = true; if (enable_screen_space_reflection && ImGui::TreeNodeEx("SSR", ImGuiTreeNodeFlags_DefaultOpen)) { - if (screen_space_reflection.OnInspect(editor_layer)) + if (screen_space_reflection->OnInspect(editor_layer)) changed = true; ImGui::TreePop(); } @@ -364,24 +451,31 @@ bool PostProcessingStack::OnInspect(const std::shared_ptr& editor_l static float debug_scale = 0.25f; ImGui::DragFloat("Scale", &debug_scale, 0.01f, 0.1f, 1.0f); debug_scale = glm::clamp(debug_scale, 0.1f, 1.0f); - if (ImGui::TreeNode("Render Texture 0")) { - ImGui::Image( - render_texture0->GetColorImTextureId(), - ImVec2(render_texture0->GetExtent().width * debug_scale, render_texture0->GetExtent().height * debug_scale), - ImVec2(0, 1), ImVec2(1, 0)); + auto initial_size = ImVec2(source_color_texture->GetExtent().width * debug_scale, + source_color_texture->GetExtent().height * debug_scale); + if (ImGui::TreeNode("Source")) { + ImGui::Image(source_color_texture->GetColorImTextureId(), initial_size, ImVec2(0, 1), ImVec2(1, 0)); ImGui::TreePop(); } - if (ImGui::TreeNode("Render Texture 1")) { + if (ImGui::TreeNode("Result")) { ImGui::Image( - render_texture1->GetColorImTextureId(), - ImVec2(render_texture1->GetExtent().width * debug_scale, render_texture1->GetExtent().height * debug_scale), + result_texture->GetColorImTextureId(), + ImVec2(result_texture->GetExtent().width * debug_scale, result_texture->GetExtent().height * debug_scale), ImVec2(0, 1), ImVec2(1, 0)); ImGui::TreePop(); } - if (ImGui::TreeNode("Render Texture 2")) { + if (ImGui::TreeNode("Mipmaps")) { + const auto mip_levels = result_texture->GetMipLevels(); + for (uint32_t mip_level = 1; mip_level < mip_levels; mip_level++) { + initial_size /= 2.f; + ImGui::Image(result_texture->GetColorImTextureId(mip_level), initial_size, ImVec2(0, 1), ImVec2(1, 0)); + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Swap")) { ImGui::Image( - render_texture2->GetColorImTextureId(), - ImVec2(render_texture2->GetExtent().width * debug_scale, render_texture2->GetExtent().height * debug_scale), + swap_texture->GetColorImTextureId(), + ImVec2(swap_texture->GetExtent().width * debug_scale, swap_texture->GetExtent().height * debug_scale), ImVec2(0, 1), ImVec2(1, 0)); ImGui::TreePop(); } @@ -392,11 +486,138 @@ bool PostProcessingStack::OnInspect(const std::shared_ptr& editor_l void PostProcessingStack::Process(const std::shared_ptr& target_camera) const { const auto render_layer = Application::GetLayer(); + + { + VkDescriptorImageInfo image_info; + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + image_info.imageView = result_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = result_texture->GetColorSampler()->GetVkSampler(); + blur_horizontal_descriptor_set->UpdateImageDescriptorBinding(0, image_info); + } + { + VkDescriptorImageInfo image_info; + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + image_info.imageView = swap_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = swap_texture->GetColorSampler()->GetVkSampler(); + blur_vertical_descriptor_set->UpdateImageDescriptorBinding(0, image_info); + } + if (enable_screen_space_ambient_occlusion) { + screen_space_ambient_occlusion->Process(*this, target_camera); + } + if (enable_bloom) { + bloom->Process(*this, target_camera); } if (enable_screen_space_reflection) { - screen_space_reflection.Process(render_texture0, render_texture1, render_texture2, target_camera); + screen_space_reflection->Process(*this, target_camera); } - if (enable_bloom) { +} + +void PostProcessingStack::GaussianBlur(const glm::uvec2& size) const { + struct PushConstant { + int horizontal = false; + float weight[5] = {0.227027f, 0.1945946f, 0.1216216f, 0.054054f, 0.016216f}; + }; + if (!blur_pipeline) { + blur_pipeline = std::make_shared(); + blur_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + blur_pipeline->fragment_shader = + Shader::CreateTemporary(ShaderType::Fragment, std::filesystem::path("./DefaultResources") / + "Shaders/Graphics/Fragment/PostProcessing/Blur.frag"); + blur_pipeline->geometry_type = GeometryType::Mesh; + blur_pipeline->descriptor_set_layouts.emplace_back(blur_layout); + blur_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + blur_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + blur_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; + auto& ssr_blur_pipeline_push_constant_range = blur_pipeline->push_constant_ranges.emplace_back(); + ssr_blur_pipeline_push_constant_range.size = sizeof(PushConstant); + ssr_blur_pipeline_push_constant_range.offset = 0; + ssr_blur_pipeline_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; + blur_pipeline->Initialize(); } + + const auto mesh = Resources::GetResource("PRIMITIVE_TEX_PASS_THROUGH"); + + PushConstant push_constant{}; + + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { +#pragma region Viewport and scissor + VkRect2D render_area; + render_area.offset = {0, 0}; + render_area.extent.width = size.x; + render_area.extent.height = size.y; + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = size.x; + viewport.height = size.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = size.x; + scissor.extent.height = size.y; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + std::vector color_attachment_infos; + color_attachment_infos.clear(); + VkRenderingInfo render_info2{}; + render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + render_info2.renderArea = render_area; + render_info2.layerCount = 1; + render_info2.pDepthAttachment = VK_NULL_HANDLE; + result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + swap_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + + swap_texture->AppendColorAttachmentInfos(color_attachment_infos, VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + + { + vkCmdBeginRendering(vk_command_buffer, &render_info2); + blur_pipeline->states.depth_test = false; + blur_pipeline->states.color_blend_attachment_states.clear(); + blur_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : blur_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + blur_pipeline->Bind(vk_command_buffer); + blur_pipeline->BindDescriptorSet(vk_command_buffer, 0, blur_horizontal_descriptor_set->GetVkDescriptorSet()); + blur_pipeline->states.view_port = viewport; + blur_pipeline->states.scissor = scissor; + push_constant.horizontal = true; + blur_pipeline->PushConstant(vk_command_buffer, 0, push_constant); + mesh->DrawIndexed(vk_command_buffer, blur_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + } + + color_attachment_infos.clear(); + result_texture->AppendColorAttachmentInfos(color_attachment_infos, VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + { + vkCmdBeginRendering(vk_command_buffer, &render_info2); + blur_pipeline->states.depth_test = false; + blur_pipeline->states.color_blend_attachment_states.clear(); + blur_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : blur_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + blur_pipeline->Bind(vk_command_buffer); + blur_pipeline->BindDescriptorSet(vk_command_buffer, 0, blur_vertical_descriptor_set->GetVkDescriptorSet()); + blur_pipeline->states.view_port = viewport; + blur_pipeline->states.scissor = scissor; + push_constant.horizontal = false; + blur_pipeline->PushConstant(vk_command_buffer, 0, push_constant); + mesh->DrawIndexed(vk_command_buffer, blur_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + } + }); } diff --git a/EvoEngine_SDK/src/RenderLayer.cpp b/EvoEngine_SDK/src/RenderLayer.cpp index 7e9727f4..e2af9939 100644 --- a/EvoEngine_SDK/src/RenderLayer.cpp +++ b/EvoEngine_SDK/src/RenderLayer.cpp @@ -41,7 +41,6 @@ void RenderLayer::ForwardRenderingAllCameras( } void RenderLayer::OnCreate() { - #pragma region Graphics Pipelines if (!point_light_shadow_pipeline_normal) { point_light_shadow_pipeline_normal = std::make_shared(); @@ -1604,7 +1603,7 @@ void RenderLayer::RenderToCamera(const GlobalTransform& camera_global_transform, const auto& directional_light_shadow_pipeline = use_mesh_shader ? directional_light_shadow_pipeline_mesh_shader : directional_light_shadow_pipeline_normal; auto& platform = Platform::GetInstance(); - Platform::RecordCommandsMainQueue([&](VkCommandBuffer vk_command_buffer) { + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { #pragma region Viewport and scissor VkRect2D render_area; render_area.offset = {0, 0}; diff --git a/EvoEngine_SDK/src/RenderTexture.cpp b/EvoEngine_SDK/src/RenderTexture.cpp index bcc5097c..f97538fe 100644 --- a/EvoEngine_SDK/src/RenderTexture.cpp +++ b/EvoEngine_SDK/src/RenderTexture.cpp @@ -6,13 +6,14 @@ using namespace evo_engine; -void RenderTexture::Initialize(const RenderTextureCreateInfo& render_texture_create_info) { - color_image_view_.reset(); +void RenderTexture::Initialize(const RenderTextureCreateInfo& render_texture_create_info, uint32_t mip_levels) { + color_image_views_.clear(); color_image_.reset(); color_sampler_.reset(); - depth_image_view_.reset(); + depth_image_views_.clear(); depth_image_.reset(); depth_sampler_.reset(); + color_im_texture_ids_.clear(); int layer_count = render_texture_create_info.image_view_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : 1; depth_ = render_texture_create_info.depth; color_ = render_texture_create_info.color; @@ -46,7 +47,7 @@ void RenderTexture::Initialize(const RenderTextureCreateInfo& render_texture_cre } if (color_) { image_info.extent = render_texture_create_info.extent; - image_info.mipLevels = 1; + image_info.mipLevels = mip_levels; image_info.arrayLayers = layer_count; image_info.format = Platform::Constants::render_texture_color; image_info.tiling = VK_IMAGE_TILING_OPTIMAL; @@ -58,29 +59,34 @@ void RenderTexture::Initialize(const RenderTextureCreateInfo& render_texture_cre color_image_ = std::make_shared(image_info); Platform::ImmediateSubmit([&](const VkCommandBuffer vk_command_buffer) { + if (mip_levels > 1) { + color_image_->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + color_image_->GenerateMipmaps(vk_command_buffer); + } color_image_->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); }); - VkImageViewCreateInfo view_info{}; - view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view_info.image = color_image_->GetVkImage(); - view_info.viewType = render_texture_create_info.image_view_type; - view_info.format = Platform::Constants::render_texture_color; - view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view_info.subresourceRange.baseMipLevel = 0; - view_info.subresourceRange.levelCount = 1; - view_info.subresourceRange.baseArrayLayer = 0; - view_info.subresourceRange.layerCount = layer_count; - - color_image_view_ = std::make_shared(view_info); + for (unsigned int mip = 0; mip < mip_levels; ++mip) { + VkImageViewCreateInfo view_info{}; + view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_info.image = color_image_->GetVkImage(); + view_info.viewType = render_texture_create_info.image_view_type; + view_info.format = Platform::Constants::render_texture_color; + view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_info.subresourceRange.baseMipLevel = mip; + view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.baseArrayLayer = 0; + view_info.subresourceRange.layerCount = layer_count; + color_image_views_.emplace_back(std::make_shared(view_info)); + } VkSamplerCreateInfo sampler_info{}; sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; sampler_info.magFilter = VK_FILTER_LINEAR; sampler_info.minFilter = VK_FILTER_LINEAR; - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; sampler_info.anisotropyEnable = VK_TRUE; sampler_info.maxAnisotropy = Platform::GetSelectedPhysicalDevice()->properties.limits.maxSamplerAnisotropy; sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; @@ -90,9 +96,11 @@ void RenderTexture::Initialize(const RenderTextureCreateInfo& render_texture_cre sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; color_sampler_ = std::make_shared(sampler_info); - - EditorLayer::UpdateTextureId(color_im_texture_id_, color_sampler_->GetVkSampler(), - color_image_view_->GetVkImageView(), color_image_->GetLayout()); + color_im_texture_ids_.resize(mip_levels); + for (unsigned int mip = 0; mip < mip_levels; ++mip) { + EditorLayer::UpdateTextureId(color_im_texture_ids_[mip], color_sampler_->GetVkSampler(), + color_image_views_[mip]->GetVkImageView(), color_image_->GetLayout()); + } } if (depth_) { @@ -115,26 +123,27 @@ void RenderTexture::Initialize(const RenderTextureCreateInfo& render_texture_cre depth_image_->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); }); - VkImageViewCreateInfo depth_view_info{}; - depth_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - depth_view_info.image = depth_image_->GetVkImage(); - depth_view_info.viewType = render_texture_create_info.image_view_type; - depth_view_info.format = Platform::Constants::render_texture_depth; - depth_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - depth_view_info.subresourceRange.baseMipLevel = 0; - depth_view_info.subresourceRange.levelCount = 1; - depth_view_info.subresourceRange.baseArrayLayer = 0; - depth_view_info.subresourceRange.layerCount = layer_count; - - depth_image_view_ = std::make_shared(depth_view_info); + for (unsigned int mip = 0; mip < mip_levels; ++mip) { + VkImageViewCreateInfo depth_view_info{}; + depth_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + depth_view_info.image = depth_image_->GetVkImage(); + depth_view_info.viewType = render_texture_create_info.image_view_type; + depth_view_info.format = Platform::Constants::render_texture_depth; + depth_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + depth_view_info.subresourceRange.baseMipLevel = mip; + depth_view_info.subresourceRange.levelCount = 1; + depth_view_info.subresourceRange.baseArrayLayer = 0; + depth_view_info.subresourceRange.layerCount = layer_count; + depth_image_views_.emplace_back(std::make_shared(depth_view_info)); + } VkSamplerCreateInfo depth_sampler_info{}; depth_sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; depth_sampler_info.magFilter = VK_FILTER_LINEAR; depth_sampler_info.minFilter = VK_FILTER_LINEAR; - depth_sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; - depth_sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; - depth_sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + depth_sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + depth_sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + depth_sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; depth_sampler_info.anisotropyEnable = VK_TRUE; depth_sampler_info.maxAnisotropy = Platform::GetSelectedPhysicalDevice()->properties.limits.maxSamplerAnisotropy; depth_sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; @@ -151,15 +160,15 @@ void RenderTexture::Initialize(const RenderTextureCreateInfo& render_texture_cre if (color_) { present_descriptor_set_ = std::make_shared(render_texture_present_layout); VkDescriptorImageInfo present_info; - present_info.imageLayout = color_image_->GetLayout(); - present_info.imageView = color_image_view_->GetVkImageView(); + present_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + present_info.imageView = color_image_views_[0]->GetVkImageView(); present_info.sampler = color_sampler_->GetVkSampler(); present_descriptor_set_->UpdateImageDescriptorBinding(0, present_info); storage_descriptor_set_ = std::make_shared(render_texture_storage_layout); VkDescriptorImageInfo storage_info; - storage_info.imageLayout = color_image_->GetLayout(); - storage_info.imageView = color_image_view_->GetVkImageView(); + storage_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + storage_info.imageView = color_image_views_[0]->GetVkImageView(); storage_info.sampler = color_sampler_->GetVkSampler(); storage_descriptor_set_->UpdateImageDescriptorBinding(0, storage_info); } @@ -201,7 +210,7 @@ void RenderTexture::Clear(VkCommandBuffer vk_command_buffer) const { RenderTexture::RenderTexture(const RenderTextureCreateInfo& render_texture_create_info) { Initialize(render_texture_create_info); } -void RenderTexture::Resize(const VkExtent3D extent) { +void RenderTexture::Resize(const VkExtent3D extent, const uint32_t mip_level) { if (extent.width == extent_.width && extent.height == extent_.height && extent.depth == extent_.depth) return; RenderTextureCreateInfo render_texture_create_info; @@ -209,12 +218,12 @@ void RenderTexture::Resize(const VkExtent3D extent) { render_texture_create_info.color = color_; render_texture_create_info.depth = depth_; render_texture_create_info.image_view_type = image_view_type_; - Initialize(render_texture_create_info); + Initialize(render_texture_create_info, mip_level); } void RenderTexture::AppendColorAttachmentInfos(std::vector& attachment_infos, - const VkAttachmentLoadOp load_op, - const VkAttachmentStoreOp store_op) const { + const VkAttachmentLoadOp load_op, const VkAttachmentStoreOp store_op, + const uint32_t mip_level) const { assert(color_); VkRenderingAttachmentInfo attachment{}; attachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; @@ -224,12 +233,13 @@ void RenderTexture::AppendColorAttachmentInfos(std::vectorGetVkImageView(); + attachment.imageView = color_image_views_[mip_level]->GetVkImageView(); attachment_infos.push_back(attachment); } VkRenderingAttachmentInfo RenderTexture::GetDepthAttachmentInfo(const VkAttachmentLoadOp load_op, - const VkAttachmentStoreOp store_op) const { + const VkAttachmentStoreOp store_op, + const uint32_t mip_level) const { assert(depth_); VkRenderingAttachmentInfo attachment{}; attachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; @@ -239,7 +249,7 @@ VkRenderingAttachmentInfo RenderTexture::GetDepthAttachmentInfo(const VkAttachme attachment.storeOp = store_op; attachment.clearValue.depthStencil = {1, 0}; - attachment.imageView = depth_image_view_->GetVkImageView(); + attachment.imageView = depth_image_views_[mip_level]->GetVkImageView(); return attachment; } @@ -251,6 +261,10 @@ VkImageViewType RenderTexture::GetImageViewType() const { return image_view_type_; } +uint32_t RenderTexture::GetMipLevels() const { + return color_image_views_.size(); +} + const std::shared_ptr& RenderTexture::GetColorSampler() const { assert(color_); return color_sampler_; @@ -271,37 +285,38 @@ const std::shared_ptr& RenderTexture::GetDepthImage() { return depth_image_; } -const std::shared_ptr& RenderTexture::GetColorImageView() { +const std::shared_ptr& RenderTexture::GetColorImageView(const uint32_t mip_index) { assert(color_); - return color_image_view_; + return color_image_views_[mip_index]; } -const std::shared_ptr& RenderTexture::GetDepthImageView() { +const std::shared_ptr& RenderTexture::GetDepthImageView(const uint32_t mip_index) { assert(depth_); - return depth_image_view_; + return depth_image_views_[mip_index]; } void RenderTexture::Render(const VkCommandBuffer vk_command_buffer, const VkAttachmentLoadOp load_op, - const VkAttachmentStoreOp store_op, const std::function& func) const { + const VkAttachmentStoreOp store_op, const std::function& func, + const uint32_t mip_level) const { if (depth_) depth_image_->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL); if (color_) color_image_->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); VkRect2D render_area; render_area.offset = {0, 0}; - render_area.extent.width = extent_.width; - render_area.extent.height = extent_.height; + render_area.extent.width = glm::max(1., static_cast(extent_.width) * glm::pow(0.5f, mip_level)); + render_area.extent.height = glm::max(1., static_cast(extent_.height) * glm::pow(0.5f, mip_level)); VkRenderingInfo render_info{}; VkRenderingAttachmentInfo depth_attachment; if (depth_) { - depth_attachment = GetDepthAttachmentInfo(load_op, store_op); + depth_attachment = GetDepthAttachmentInfo(load_op, store_op, mip_level); render_info.pDepthAttachment = &depth_attachment; } else { render_info.pDepthAttachment = nullptr; } std::vector color_attachment_infos; if (color_) { - AppendColorAttachmentInfos(color_attachment_infos, load_op, store_op); + AppendColorAttachmentInfos(color_attachment_infos, load_op, store_op, mip_level); render_info.colorAttachmentCount = color_attachment_infos.size(); render_info.pColorAttachments = color_attachment_infos.data(); } else { @@ -316,8 +331,8 @@ void RenderTexture::Render(const VkCommandBuffer vk_command_buffer, const VkAtta vkCmdEndRendering(vk_command_buffer); } -ImTextureID RenderTexture::GetColorImTextureId() const { - return color_im_texture_id_; +ImTextureID RenderTexture::GetColorImTextureId(const uint32_t mip_index) const { + return color_im_texture_ids_[glm::clamp(mip_index, 0u, static_cast(color_im_texture_ids_.size()) - 1)]; } void RenderTexture::ApplyGraphicsPipelineStates(GraphicsPipelineStates& global_pipeline_state) const { @@ -463,3 +478,11 @@ void RenderTexture::StoreToHdr(const std::string& path, int resize_x, int resize stbi_write_hdr(path.c_str(), resolution_x, resolution_y, channels, dst.data()); } } + +const std::shared_ptr& RenderTexture::GetPresentDescriptorSet() const { + return present_descriptor_set_; +} + +const std::shared_ptr& RenderTexture::GetStorageDescriptorSet() const { + return storage_descriptor_set_; +} diff --git a/EvoEngine_SDK/src/ScreenSpaceAmbientOcclusion.cpp b/EvoEngine_SDK/src/ScreenSpaceAmbientOcclusion.cpp new file mode 100644 index 00000000..d96907e8 --- /dev/null +++ b/EvoEngine_SDK/src/ScreenSpaceAmbientOcclusion.cpp @@ -0,0 +1,367 @@ +#include "PostProcessingStack.hpp" + +#include "Application.hpp" +#include "Camera.hpp" +#include "EditorLayer.hpp" +#include "GeometryStorage.hpp" +#include "GraphicsPipeline.hpp" +#include "Mesh.hpp" +#include "Platform.hpp" +#include "RenderLayer.hpp" +#include "Resources.hpp" +#include "Shader.hpp" +using namespace evo_engine; + +bool ScreenSpaceAmbientOcclusion::OnInspect(const std::shared_ptr& editor_layer) { + bool changed = false; + + if (ImGui::DragInt("Kernel size", &kernel_size, 1, 1, 64)) { + changed = true; + } + if (ImGui::DragFloat("Disk radius", &radius, 0.001f, 0.0f, 10.f)) { + changed = true; + } + if (ImGui::DragFloat("Bias", &bias, 0.001f, 0.0f, 1.f)) { + changed = true; + } + if (ImGui::DragFloat("Factor", &factor, 0.01f, 0.0f, 5.f)) { + changed = true; + } + if (ImGui::DragFloat("Intensity", &intensity, 0.01f, 0.0f, 5.f)) { + changed = true; + } + if (ImGui::DragFloat("Avoid distance", &avoid_distance, 0.1f, 0.0f, 100.f)) { + changed = true; + } + if (ImGui::Button("Rebuild pipelines")) { + BuildPipelines(); + } + return changed; +} + +void ScreenSpaceAmbientOcclusion::Process(const PostProcessingStack& post_processing_stack, + const std::shared_ptr& target_camera) { + if (!geometry_pipeline || !geometry_pipeline->Initialized() || !combine_pipeline || !combine_pipeline->Initialized()) + return; + const auto render_layer = Application::GetLayer(); + { + VkDescriptorImageInfo image_info; + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + image_info.imageView = post_processing_stack.source_color_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = post_processing_stack.source_color_texture->GetColorSampler()->GetVkSampler(); + combine_descriptor_set->UpdateImageDescriptorBinding(0, image_info); + image_info.imageView = post_processing_stack.result_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = post_processing_stack.result_texture->GetColorSampler()->GetVkSampler(); + combine_descriptor_set->UpdateImageDescriptorBinding(1, image_info); + } + { + VkDescriptorImageInfo image_info; + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + image_info.imageView = post_processing_stack.result_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = post_processing_stack.result_texture->GetColorSampler()->GetVkSampler(); + blur_horizontal_descriptor_set->UpdateImageDescriptorBinding(0, image_info); + } + { + VkDescriptorImageInfo image_info; + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + image_info.imageView = post_processing_stack.swap_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = post_processing_stack.swap_texture->GetColorSampler()->GetVkSampler(); + blur_vertical_descriptor_set->UpdateImageDescriptorBinding(0, image_info); + } + const auto size = target_camera->GetSize(); + PushConstant push_constant; + push_constant.kernel_size = kernel_size; + push_constant.radius = radius; + push_constant.bias = bias; + push_constant.factor = factor; + push_constant.intensity = intensity; + push_constant.camera_index = + render_layer->GetCurrentRenderInstanceStorage()->GetCameraIndex(target_camera->GetHandle()); + const auto mesh = Resources::GetResource("PRIMITIVE_TEX_PASS_THROUGH"); + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { +#pragma region Viewport and scissor + VkRect2D render_area; + render_area.offset = {0, 0}; + render_area.extent.width = size.x; + render_area.extent.height = size.y; + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = size.x; + viewport.height = size.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = size.x; + scissor.extent.height = size.y; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + + std::vector color_attachment_infos; + VkRenderingInfo render_info2{}; + render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + render_info2.renderArea = render_area; + render_info2.layerCount = 1; + render_info2.pDepthAttachment = VK_NULL_HANDLE; + + // Input texture + target_camera->TransitGBufferImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + target_camera->GetRenderTexture()->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + // Attachments + post_processing_stack.source_color_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.source_color_texture->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + post_processing_stack.result_texture->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + + vkCmdBeginRendering(vk_command_buffer, &render_info2); + geometry_pipeline->states.depth_test = false; + geometry_pipeline->states.color_blend_attachment_states.clear(); + geometry_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : geometry_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + geometry_pipeline->Bind(vk_command_buffer); + geometry_pipeline->BindDescriptorSet(vk_command_buffer, 0, + render_layer->GetPerFrameDescriptorSet()->GetVkDescriptorSet()); + geometry_pipeline->BindDescriptorSet(vk_command_buffer, 1, + target_camera->GetGBufferDescriptorSet()->GetVkDescriptorSet()); + geometry_pipeline->BindDescriptorSet( + vk_command_buffer, 2, target_camera->GetRenderTexture()->GetPresentDescriptorSet()->GetVkDescriptorSet()); + geometry_pipeline->states.view_port = viewport; + geometry_pipeline->states.scissor = scissor; + + geometry_pipeline->PushConstant(vk_command_buffer, 0, push_constant); + mesh->DrawIndexed(vk_command_buffer, geometry_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + }); + BlurPushConstant blur_push_constant{}; + blur_push_constant.avoid_distance = avoid_distance; + blur_push_constant.camera_near = target_camera->near_distance; + blur_push_constant.camera_far = target_camera->far_distance; + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { +#pragma region Viewport and scissor + VkRect2D render_area; + render_area.offset = {0, 0}; + render_area.extent.width = size.x; + render_area.extent.height = size.y; + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = size.x; + viewport.height = size.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = size.x; + scissor.extent.height = size.y; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + std::vector color_attachment_infos; + color_attachment_infos.clear(); + VkRenderingInfo render_info2{}; + render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + render_info2.renderArea = render_area; + render_info2.layerCount = 1; + render_info2.pDepthAttachment = VK_NULL_HANDLE; + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.swap_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + + post_processing_stack.swap_texture->AppendColorAttachmentInfos(color_attachment_infos, VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + + { + vkCmdBeginRendering(vk_command_buffer, &render_info2); + blur_pipeline->states.depth_test = false; + blur_pipeline->states.color_blend_attachment_states.clear(); + blur_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : blur_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + blur_pipeline->Bind(vk_command_buffer); + blur_pipeline->BindDescriptorSet(vk_command_buffer, 0, blur_horizontal_descriptor_set->GetVkDescriptorSet()); + blur_pipeline->BindDescriptorSet(vk_command_buffer, 1, + target_camera->GetGBufferDescriptorSet()->GetVkDescriptorSet()); + blur_pipeline->states.view_port = viewport; + blur_pipeline->states.scissor = scissor; + blur_push_constant.horizontal = true; + blur_pipeline->PushConstant(vk_command_buffer, 0, blur_push_constant); + mesh->DrawIndexed(vk_command_buffer, blur_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + } + + color_attachment_infos.clear(); + post_processing_stack.result_texture->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + { + vkCmdBeginRendering(vk_command_buffer, &render_info2); + blur_pipeline->states.depth_test = false; + blur_pipeline->states.color_blend_attachment_states.clear(); + blur_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : blur_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + blur_pipeline->Bind(vk_command_buffer); + blur_pipeline->BindDescriptorSet(vk_command_buffer, 0, blur_vertical_descriptor_set->GetVkDescriptorSet()); + blur_pipeline->BindDescriptorSet(vk_command_buffer, 1, + target_camera->GetGBufferDescriptorSet()->GetVkDescriptorSet()); + blur_pipeline->states.view_port = viewport; + blur_pipeline->states.scissor = scissor; + blur_push_constant.horizontal = false; + blur_pipeline->PushConstant(vk_command_buffer, 0, blur_push_constant); + mesh->DrawIndexed(vk_command_buffer, blur_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + } + }); + + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { +#pragma region Viewport and scissor + VkRect2D render_area; + render_area.offset = {0, 0}; + render_area.extent.width = size.x; + render_area.extent.height = size.y; + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = size.x; + viewport.height = size.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = size.x; + scissor.extent.height = size.y; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + + std::vector color_attachment_infos{}; + VkRenderingInfo render_info2{}; + render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + render_info2.renderArea = render_area; + render_info2.layerCount = 1; + render_info2.pDepthAttachment = VK_NULL_HANDLE; + // Input texture + target_camera->GetRenderTexture()->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + // Attachments + post_processing_stack.source_color_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + + target_camera->GetRenderTexture()->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + { + vkCmdBeginRendering(vk_command_buffer, &render_info2); + combine_pipeline->states.depth_test = false; + combine_pipeline->states.color_blend_attachment_states.clear(); + combine_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : combine_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + combine_pipeline->Bind(vk_command_buffer); + combine_pipeline->BindDescriptorSet(vk_command_buffer, 0, combine_descriptor_set->GetVkDescriptorSet()); + combine_pipeline->states.view_port = viewport; + combine_pipeline->states.scissor = scissor; + mesh->DrawIndexed(vk_command_buffer, combine_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + } + }); +} + +void ScreenSpaceAmbientOcclusion::BuildPipelines() { + combine_layout = std::make_shared(); + combine_layout->PushDescriptorBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + combine_layout->PushDescriptorBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + combine_layout->Initialize(); + + geometry_pipeline = std::make_shared(); + geometry_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + geometry_pipeline->fragment_shader = Shader::CreateTemporary( + ShaderType::Fragment, Platform::Constants::shader_global_defines, + std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/SSAOGeometry.frag"); + geometry_pipeline->geometry_type = GeometryType::Mesh; + geometry_pipeline->descriptor_set_layouts.emplace_back(RenderLayer::per_frame_layout); + geometry_pipeline->descriptor_set_layouts.emplace_back(Camera::g_buffer_layout); + geometry_pipeline->descriptor_set_layouts.emplace_back(RenderTexture::render_texture_present_layout); + geometry_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + geometry_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + geometry_pipeline->color_attachment_formats = {2, Platform::Constants::render_texture_color}; + auto& ssr_reflect_pipeline_push_constant_range = geometry_pipeline->push_constant_ranges.emplace_back(); + ssr_reflect_pipeline_push_constant_range.size = sizeof(PushConstant); + ssr_reflect_pipeline_push_constant_range.offset = 0; + ssr_reflect_pipeline_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; + geometry_pipeline->Initialize(); + + combine_pipeline = std::make_shared(); + combine_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + combine_pipeline->fragment_shader = Shader::CreateTemporary( + ShaderType::Fragment, Platform::Constants::shader_global_defines, + std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/SSAOCombine.frag"); + combine_pipeline->geometry_type = GeometryType::Mesh; + combine_pipeline->descriptor_set_layouts.emplace_back(combine_layout); + combine_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + combine_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + combine_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; + combine_pipeline->Initialize(); + + if (!combine_descriptor_set) { + combine_descriptor_set = std::make_shared(combine_layout); + } + + if (!blur_layout) { + blur_layout = std::make_shared(); + blur_layout->PushDescriptorBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + blur_layout->Initialize(); + } + + if (!blur_horizontal_descriptor_set) { + blur_horizontal_descriptor_set = std::make_shared(blur_layout); + } + if (!blur_vertical_descriptor_set) { + blur_vertical_descriptor_set = std::make_shared(blur_layout); + } + + if (!blur_pipeline) { + blur_pipeline = std::make_shared(); + blur_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + blur_pipeline->fragment_shader = + Shader::CreateTemporary(ShaderType::Fragment, std::filesystem::path("./DefaultResources") / + "Shaders/Graphics/Fragment/PostProcessing/SSAOBlur.frag"); + blur_pipeline->geometry_type = GeometryType::Mesh; + blur_pipeline->descriptor_set_layouts.emplace_back(blur_layout); + blur_pipeline->descriptor_set_layouts.emplace_back(Camera::g_buffer_layout); + blur_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + blur_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + blur_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; + auto& ssr_blur_pipeline_push_constant_range = blur_pipeline->push_constant_ranges.emplace_back(); + ssr_blur_pipeline_push_constant_range.size = sizeof(BlurPushConstant); + ssr_blur_pipeline_push_constant_range.offset = 0; + ssr_blur_pipeline_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; + blur_pipeline->Initialize(); + } +} \ No newline at end of file diff --git a/EvoEngine_SDK/src/ScreenSpaceReflection.cpp b/EvoEngine_SDK/src/ScreenSpaceReflection.cpp new file mode 100644 index 00000000..e8e39aae --- /dev/null +++ b/EvoEngine_SDK/src/ScreenSpaceReflection.cpp @@ -0,0 +1,243 @@ +#include "PostProcessingStack.hpp" + +#include "Application.hpp" +#include "Camera.hpp" +#include "EditorLayer.hpp" +#include "GeometryStorage.hpp" +#include "GraphicsPipeline.hpp" +#include "Mesh.hpp" +#include "Platform.hpp" +#include "RenderLayer.hpp" +#include "Resources.hpp" +#include "Shader.hpp" +using namespace evo_engine; + +bool ScreenSpaceReflection::OnInspect(const std::shared_ptr& editor_layer) { + bool changed = false; + if (ImGui::DragFloat("Max march distance", &max_distance, 0.01f, 0.01f, 100.0f)) + changed = true; + if (ImGui::DragFloat("Resolution", &resolution, 0.1f, 0.0f, 128.0f)) + changed = true; + if (ImGui::DragInt("Max iteration count", &max_iteration_count, 1, 1, 256)) + changed = true; + if (ImGui::DragInt("Steps", &initial_steps, 1, 1, 64)) + changed = true; + if (ImGui::DragFloat("Thickness", &thickness, 0.01f, 0.0f, 10.0f)) + changed = true; + if (ImGui::Checkbox("Blur", &blur)) { + changed = true; + } + if (ImGui::Button("Rebuild pipelines")) { + BuildPipelines(); + } + + return changed; +} + +void ScreenSpaceReflection::Process(const PostProcessingStack& post_processing_stack, + const std::shared_ptr& target_camera) { + if (!reflect_pipeline || !combine_pipeline || !reflect_pipeline->Initialized() || !combine_pipeline->Initialized()) + return; + const auto render_layer = Application::GetLayer(); + + { + VkDescriptorImageInfo image_info; + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + image_info.imageView = post_processing_stack.source_color_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = post_processing_stack.source_color_texture->GetColorSampler()->GetVkSampler(); + combine_descriptor_set->UpdateImageDescriptorBinding(0, image_info); + image_info.imageView = post_processing_stack.result_texture->GetColorImageView()->GetVkImageView(); + image_info.sampler = post_processing_stack.result_texture->GetColorSampler()->GetVkSampler(); + combine_descriptor_set->UpdateImageDescriptorBinding(1, image_info); + } + PushConstant push_constant; + push_constant.max_distance = max_distance; + push_constant.max_iteration_count = max_iteration_count; + push_constant.resolution = resolution; + push_constant.initial_steps = initial_steps; + push_constant.thickness = thickness; + push_constant.camera_index = + render_layer->GetCurrentRenderInstanceStorage()->GetCameraIndex(target_camera->GetHandle()); + const auto mesh = Resources::GetResource("PRIMITIVE_TEX_PASS_THROUGH"); + + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { +#pragma region Viewport and scissor + VkRect2D render_area; + render_area.offset = {0, 0}; + render_area.extent.width = target_camera->GetSize().x; + render_area.extent.height = target_camera->GetSize().y; + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = target_camera->GetSize().x; + viewport.height = target_camera->GetSize().y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = target_camera->GetSize().x; + scissor.extent.height = target_camera->GetSize().y; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + + std::vector color_attachment_infos; + VkRenderingInfo render_info2{}; + render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + render_info2.renderArea = render_area; + render_info2.layerCount = 1; + render_info2.pDepthAttachment = VK_NULL_HANDLE; + + // Input texture + target_camera->TransitGBufferImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + target_camera->GetRenderTexture()->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + // Attachments + post_processing_stack.source_color_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.source_color_texture->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + post_processing_stack.result_texture->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + + vkCmdBeginRendering(vk_command_buffer, &render_info2); + reflect_pipeline->states.depth_test = false; + reflect_pipeline->states.color_blend_attachment_states.clear(); + reflect_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : reflect_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + reflect_pipeline->Bind(vk_command_buffer); + reflect_pipeline->BindDescriptorSet(vk_command_buffer, 0, + render_layer->GetPerFrameDescriptorSet()->GetVkDescriptorSet()); + reflect_pipeline->BindDescriptorSet(vk_command_buffer, 1, + target_camera->GetGBufferDescriptorSet()->GetVkDescriptorSet()); + reflect_pipeline->BindDescriptorSet( + vk_command_buffer, 2, target_camera->GetRenderTexture()->GetPresentDescriptorSet()->GetVkDescriptorSet()); + reflect_pipeline->states.view_port = viewport; + reflect_pipeline->states.scissor = scissor; + + reflect_pipeline->PushConstant(vk_command_buffer, 0, push_constant); + mesh->DrawIndexed(vk_command_buffer, reflect_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + }); + + post_processing_stack.GaussianBlur(target_camera->GetSize()); + + Platform::RecordCommandsMainQueue([&](const VkCommandBuffer vk_command_buffer) { +#pragma region Viewport and scissor + VkRect2D render_area; + render_area.offset = {0, 0}; + render_area.extent.width = target_camera->GetSize().x; + render_area.extent.height = target_camera->GetSize().y; + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = target_camera->GetSize().x; + viewport.height = target_camera->GetSize().y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = {0, 0}; + scissor.extent.width = target_camera->GetSize().x; + scissor.extent.height = target_camera->GetSize().y; +#pragma endregion + GeometryStorage::BindVertices(vk_command_buffer); + + std::vector color_attachment_infos{}; + VkRenderingInfo render_info2{}; + render_info2.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + render_info2.renderArea = render_area; + render_info2.layerCount = 1; + render_info2.pDepthAttachment = VK_NULL_HANDLE; + + // Input texture + target_camera->TransitGBufferImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + target_camera->GetRenderTexture()->GetColorImage()->TransitImageLayout(vk_command_buffer, VK_IMAGE_LAYOUT_GENERAL); + // Attachments + post_processing_stack.source_color_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + post_processing_stack.result_texture->GetColorImage()->TransitImageLayout(vk_command_buffer, + VK_IMAGE_LAYOUT_GENERAL); + + target_camera->GetRenderTexture()->AppendColorAttachmentInfos( + color_attachment_infos, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); + render_info2.colorAttachmentCount = color_attachment_infos.size(); + render_info2.pColorAttachments = color_attachment_infos.data(); + { + vkCmdBeginRendering(vk_command_buffer, &render_info2); + combine_pipeline->states.depth_test = false; + combine_pipeline->states.color_blend_attachment_states.clear(); + combine_pipeline->states.color_blend_attachment_states.resize(color_attachment_infos.size()); + for (auto& i : combine_pipeline->states.color_blend_attachment_states) { + i.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + i.blendEnable = VK_FALSE; + } + combine_pipeline->Bind(vk_command_buffer); + combine_pipeline->BindDescriptorSet(vk_command_buffer, 0, + render_layer->GetPerFrameDescriptorSet()->GetVkDescriptorSet()); + combine_pipeline->BindDescriptorSet(vk_command_buffer, 1, combine_descriptor_set->GetVkDescriptorSet()); + combine_pipeline->BindDescriptorSet(vk_command_buffer, 2, + target_camera->GetGBufferDescriptorSet()->GetVkDescriptorSet()); + combine_pipeline->states.view_port = viewport; + combine_pipeline->states.scissor = scissor; + combine_pipeline->PushConstant(vk_command_buffer, 0, push_constant); + mesh->DrawIndexed(vk_command_buffer, combine_pipeline->states, 1); + vkCmdEndRendering(vk_command_buffer); + } + }); +} + +void ScreenSpaceReflection::BuildPipelines() { + combine_layout = std::make_shared(); + combine_layout->PushDescriptorBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + combine_layout->PushDescriptorBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0); + combine_layout->Initialize(); + + reflect_pipeline = std::make_shared(); + reflect_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + reflect_pipeline->fragment_shader = Shader::CreateTemporary( + ShaderType::Fragment, Platform::Constants::shader_global_defines, + std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/SSRReflect.frag"); + reflect_pipeline->geometry_type = GeometryType::Mesh; + reflect_pipeline->descriptor_set_layouts.emplace_back(RenderLayer::per_frame_layout); + reflect_pipeline->descriptor_set_layouts.emplace_back(Camera::g_buffer_layout); + reflect_pipeline->descriptor_set_layouts.emplace_back(RenderTexture::render_texture_present_layout); + reflect_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + reflect_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + reflect_pipeline->color_attachment_formats = {2, Platform::Constants::render_texture_color}; + auto& ssr_reflect_pipeline_push_constant_range = reflect_pipeline->push_constant_ranges.emplace_back(); + ssr_reflect_pipeline_push_constant_range.size = sizeof(PushConstant); + ssr_reflect_pipeline_push_constant_range.offset = 0; + ssr_reflect_pipeline_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; + reflect_pipeline->Initialize(); + + combine_pipeline = std::make_shared(); + combine_pipeline->vertex_shader = Resources::GetResource("TEXTURE_PASS_THROUGH_VERT"); + combine_pipeline->fragment_shader = Shader::CreateTemporary( + ShaderType::Fragment, Platform::Constants::shader_global_defines, + std::filesystem::path("./DefaultResources") / "Shaders/Graphics/Fragment/PostProcessing/SSRCombine.frag"); + combine_pipeline->geometry_type = GeometryType::Mesh; + combine_pipeline->descriptor_set_layouts.emplace_back(RenderLayer::per_frame_layout); + combine_pipeline->descriptor_set_layouts.emplace_back(combine_layout); + combine_pipeline->descriptor_set_layouts.emplace_back(Camera::g_buffer_layout); + combine_pipeline->depth_attachment_format = VK_FORMAT_UNDEFINED; + combine_pipeline->stencil_attachment_format = VK_FORMAT_UNDEFINED; + combine_pipeline->color_attachment_formats = {1, Platform::Constants::render_texture_color}; + auto& ssr_combine_pipeline_push_constant_range = combine_pipeline->push_constant_ranges.emplace_back(); + ssr_combine_pipeline_push_constant_range.size = sizeof(PushConstant); + ssr_combine_pipeline_push_constant_range.offset = 0; + ssr_combine_pipeline_push_constant_range.stageFlags = VK_SHADER_STAGE_ALL; + combine_pipeline->Initialize(); + + if (!combine_descriptor_set) { + combine_descriptor_set = std::make_shared(combine_layout); + } +} \ No newline at end of file diff --git a/Folder.DotSettings.user b/Folder.DotSettings.user index dff76d12..64a247ab 100644 --- a/Folder.DotSettings.user +++ b/Folder.DotSettings.user @@ -6,4 +6,6 @@ (Doc Ln 153 Col 51) DB94C55F-6B9A-4AAE-80D7-29FD8153E6B5/d:src/d:lib/f:IGeometry.cpp NumberedBookmarkManager - True \ No newline at end of file + True + True + True \ No newline at end of file diff --git a/Resources/EcoSysLabProject/Default.evescene b/Resources/EcoSysLabProject/Default.evescene index 124c1d42..876ed9ed 100644 --- a/Resources/EcoSysLabProject/Default.evescene +++ b/Resources/EcoSysLabProject/Default.evescene @@ -30,9 +30,15 @@ entity_metadata_list: skybox: asset_handle_: 0 asset_type_name_: Mesh - post_processing_stack: - asset_handle_: 0 - asset_type_name_: "" + post_processing_stack_ref: + asset_handle_: 15888462117146613974 + asset_type_name_: PostProcessingStack + - tn: PlayerController + e: true + velocity: 20 + sensitivity: 0.100000001 + scene_camera_yaw_angle_: -89 + scene_camera_pitch_angle_: 0 - n: Directional Light h: 4980998256074025614 e: true @@ -254,6 +260,8 @@ entity_metadata_list: systems_: [] LocalAssets: + - type_name: PostProcessingStack + handle: 15888462117146613974 - type_name: Material handle: 9351133328134294989 albedo_texture_: