diff --git a/Data/Shaders/outline.shader b/Data/Shaders/outline.shader index cfcb5d8b..8c77fb07 100644 --- a/Data/Shaders/outline.shader +++ b/Data/Shaders/outline.shader @@ -1,90 +1,172 @@ -#shader vertex -#version 440 core - -layout(location = 0) in vec3 VertexPosition; -layout(location = 1) in vec2 UVPosition; - -out flat vec2 a_UV; - -void main() +// Transforms +struct ModelData { - a_UV = UVPosition; - gl_Position = vec4(VertexPosition, 1.0f); + float4x4 model; +}; +[[vk::binding(0, 0)]] +StructuredBuffer model : register(t1); + +// Vertex +struct Vertex +{ + float3 position; + float uv_x; + float3 normal; + float uv_y; + float3 tangent; + float3 bitangent; +}; + +[[vk::binding(0, 1)]] +StructuredBuffer vertexBuffer : register(t2); + +// Samplers +[[vk::binding(0, 2)]] +SamplerState mySampler : register(s0); + +// Materials +struct Material +{ + bool hasAlbedo; + float3 albedo; + bool hasNormal; + bool hasMetalness; + bool hasRoughness; + bool hasAO; + float metalnessValue; + float roughnessValue; + float aoValue; + int albedoTextureId; + int normalTextureId; + int metalnessTextureId; + int roughnessTextureId; + int aoTextureId; +}; +[[vk::binding(0, 3)]] +StructuredBuffer material; + +// Textures +[[vk::binding(0, 4)]] +Texture2D textures[]; + +// Lights +struct Light +{ + float3 position; + int type; + float4 color; + float3 direction; + float outerConeAngle; + float innerConeAngle; + bool castShadow; + int shadowMapTextureId[4]; + int transformId[4]; +}; + +[[vk::binding(0, 5)]] +StructuredBuffer lights; + +// Cameras +struct CameraView { + float4x4 View; + float4x4 Projection; + float4x4 ViewProjection; + float4x4 InverseView; + float4x4 InverseProjection; + float3 Position; + float Near; + float Far; +}; +[[vk::binding(0, 6)]] +StructuredBuffer cameras; + +struct PSInput { + float4 Position : SV_Position; + float2 UV : TEXCOORD0; +}; + +struct PSOutput { + float4 oColor0 : SV_TARGET; +}; + +struct OutlinePushConstant +{ + float4 Color; + float Thickness; + int SourceTextureID; + int EntityIDTextureID; + int DepthTextureID; + float SelectedEntity; +}; + +[[vk::push_constant]] +OutlinePushConstant pushConstants; + +float2 GetTexelSize(Texture2D tex) +{ + uint width, height; + tex.GetDimensions(width, height); + return 1.0 / float2(width, height); } -#shader fragment -#version 440 core - -uniform int u_EntityID; -uniform usampler2D u_EntityTexture; -uniform vec4 u_OutlineColor; -uniform sampler2D u_Depth; - -uniform float u_Radius; -out vec4 FragColor; - -in vec2 a_UV; - -void main() +PSOutput main(PSInput input) { - int target = u_EntityID; + PSOutput output; + + float4 outlineColor = pushConstants.Color; + float target = pushConstants.SelectedEntity; + float radius = pushConstants.Thickness; + float2 uv = input.UV; + + int entityIDTextureID = pushConstants.EntityIDTextureID; + float hasHit = 0.0f; + + float sampleValue = textures[entityIDTextureID].Sample(mySampler, uv).r; + float depth = textures[pushConstants.DepthTextureID].Sample(mySampler, uv).r; + + float4 fragColor = float4(0, 0, 0, 0); const float TAU = 6.28318530; const float steps = 32.0; - - float radius = u_Radius; - vec2 uv = a_UV; - - // sample middle - uint middleSample = texture(u_EntityTexture, uv).r; - float depth = texture(u_Depth, uv).r; - - // Correct aspect ratio - vec2 aspect = 1.0 / vec2(textureSize(u_EntityTexture, 0)); - - float hasHit = 0.0f; - vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0f); - for (float i = 0.0; i < TAU; i += TAU / steps) + for(float i = 0.0f; i < TAU; i += TAU / steps) { - // Sample image in a circular pattern - vec2 offset = vec2(sin(i), cos(i)) * aspect * radius; - - // We dont want to sample outside the viewport - vec2 sampleUv = uv + offset; - sampleUv.x = clamp(sampleUv.x, 0.0, 0.999); - sampleUv.y = clamp(sampleUv.y, 0.0, 0.999); + float2 uvOffset = float2(sin(i), cos(i)) * (GetTexelSize(textures[entityIDTextureID])) * radius; - uint col = texture(u_EntityTexture, sampleUv).r; - float depthTarget = texture(u_Depth, sampleUv).r; - if(col == target && depthTarget != 0.0f && depthTarget < depth) - { - hasHit = 1.0f; - } + float2 sampleUV = uv + uvOffset; + sampleUV.x = clamp(sampleUV.x, 0.0, 0.999); + sampleUV.y = clamp(sampleUV.y, 0.0, 0.999); + + float sample = textures[entityIDTextureID].Sample(mySampler, sampleUV).r; + float sampleDepth = textures[pushConstants.DepthTextureID].Sample(mySampler, sampleUV).r; + if(sample == target && sampleDepth != 1.0f && sampleDepth > depth) + { + hasHit = 1.0f; + } - // Mix outline with background - float alpha = smoothstep(0.5, 0.9, int(col != target) * hasHit * 10.0f); - - - vec4 outputColor = vec4( - mix(fragColor.r, u_OutlineColor.r, alpha), - mix(fragColor.g, u_OutlineColor.g, alpha), - mix(fragColor.b, u_OutlineColor.b, alpha), - mix(fragColor.a, u_OutlineColor.a, alpha) + float alpha = smoothstep(0.5, 0.9, hasHit); + float4 outputColor = float4( + lerp(fragColor.r, outlineColor.r, alpha), + lerp(fragColor.g, outlineColor.g, alpha), + lerp(fragColor.b, outlineColor.b, alpha), + lerp(fragColor.a, outlineColor.a, alpha) ); - fragColor = outputColor; - } - + fragColor = outputColor; + } + if(fragColor.a > 0.1) { fragColor.a = 1.0f; } - - float ratio = float(middleSample != target && hasHit > 0.0f); - vec4 finalColor = vec4( - mix(0, fragColor.r, ratio), - mix(0, fragColor.g, ratio), - mix(0, fragColor.b, ratio), - mix(0, fragColor.a, ratio) - ); - FragColor = finalColor; -} + + float3 sourceTexture = textures[pushConstants.SourceTextureID].Sample(mySampler, uv).rgb; + float ratio = float(sampleValue != target && hasHit > 0.0f); + float4 finalColor = float4( + lerp(sourceTexture.r, fragColor.r, ratio), + lerp(sourceTexture.g, fragColor.g, ratio), + lerp(sourceTexture.b, fragColor.b, ratio), + lerp(1.0f, fragColor.a, ratio) + ); + + output.oColor0 = finalColor; + return output; +} \ No newline at end of file diff --git a/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.cpp b/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.cpp index c9d7e344..15d52864 100644 --- a/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.cpp +++ b/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.cpp @@ -9,6 +9,8 @@ #include "Nuake/Scene/Components/TransformComponent.h" #include "Nuake/Scene/Components/ModelComponent.h" +#include "Engine.h" +#include "Nuake/Resource/Project.h" #include "VulkanAllocator.h" @@ -194,7 +196,7 @@ SceneRenderPipeline::SceneRenderPipeline() TonemappedOutput = CreateRef(ImageFormat::RGBA8, defaultSize); TonemappedOutput->SetDebugName("TonemappedOutput"); - GBufferEntityID = CreateRef(ImageFormat::RGBA8, defaultSize); + GBufferEntityID = CreateRef(ImageFormat::RGBA16F, defaultSize); GBufferEntityID->SetDebugName("GBufferEntityID"); OutlineOutput = CreateRef(ImageFormat::RGBA8, defaultSize); @@ -690,8 +692,8 @@ void SceneRenderPipeline::RecreatePipeline() outlineConstant.EntityIDTextureID = GPUResources::Get().GetBindlessTextureID(GBufferEntityID->GetID()); outlineConstant.DepthTextureID = GPUResources::Get().GetBindlessTextureID(GBufferDepth->GetID()); outlineConstant.SelectedEntityID = ctx.selectedEntity; - outlineConstant.Color = Vector4(1, 0, 0, 1); - outlineConstant.Thickness = 4.0f; + outlineConstant.Color = Engine::GetProject()->Settings.PrimaryColor; + outlineConstant.Thickness = Engine::GetProject()->Settings.OutlineRadius; auto& cmd = ctx.commandBuffer; cmd.PushConstants(ctx.renderPass->PipelineLayout, sizeof(OutlineConstant), &outlineConstant);