From 321b1f62cc50c27eeb45533773c6321092e4803e Mon Sep 17 00:00:00 2001 From: emil28092005 Date: Thu, 18 Jun 2026 19:33:37 +0300 Subject: [PATCH] debug: simple diffuse fragment shader to test point light UBO --- .../Shaders/triangle.frag | 102 ++---------------- .../Shaders/triangle.frag.spv | Bin 9464 -> 2120 bytes src/Engine.Graphics.Vulkan/VulkanRenderer.cs | 6 ++ 3 files changed, 14 insertions(+), 94 deletions(-) diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag index 654a4cb..1a5630e 100644 --- a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag +++ b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag @@ -8,108 +8,22 @@ layout(location = 0) out vec4 outColor; layout(set = 0, binding = 0) uniform CameraUBO { mat4 vp; - vec4 pointLightPos; // xyz = position, w = intensity - vec4 pointLightColor; // xyz = color, w = range + vec4 pointLightPos; + vec4 pointLightColor; }; -const vec3 AMBIENT = vec3(0.01, 0.01, 0.02); - -const float PI = 3.14159265359; - -float distributionGGX(vec3 N, vec3 H, float roughness) -{ - float a = roughness * roughness; - float a2 = a * a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - float num = a2; - float denom = NdotH2 * (a2 - 1.0) + 1.0; - denom = PI * denom * denom; - return num / denom; -} - -float geometrySchlickGGX(float NdotV, float roughness) -{ - float r = roughness + 1.0; - float k = (r * r) / 8.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) -{ - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); -} - -vec3 fresnelSchlick(float cosTheta, vec3 F0) -{ - return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); -} - -vec3 acesTonemap(vec3 color) -{ - float a = 2.51; - float b = 0.03; - float c = 2.43; - float d = 0.59; - float e = 0.14; - return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0, 1.0); -} - -vec3 calcLight(vec3 N, vec3 V, vec3 L, vec3 radiance, vec3 albedo, float roughness, float metallic) -{ - vec3 H = normalize(V + L); - vec3 F0 = mix(vec3(0.04), albedo, metallic); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; - vec3 specular = numerator / denominator; - - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - - float NdotL = max(dot(N, L), 0.0); - return (kD * albedo / PI + specular) * radiance * NdotL; -} - void main() { vec3 N = normalize(fragNormal); - vec3 V = normalize(-fragWorldPos); - - vec3 albedo = fragAlbedo; - float roughness = 0.5; - float metallic = 0.1; - - // Only point light — no directional, near-zero ambient - vec3 color = AMBIENT * albedo; - - vec3 lightPos = pointLightPos.xyz; - float lightIntensity = pointLightPos.w; - vec3 lightColor = pointLightColor.xyz; - float lightRange = pointLightColor.w; - - vec3 toLight = lightPos - fragWorldPos; + vec3 toLight = pointLightPos.xyz - fragWorldPos; float dist = length(toLight); - vec3 L = toLight / max(dist, 0.001); + vec3 L = normalize(toLight); - // Unity-style attenuation - float attenuation = pow(clamp(1.0 - dist / lightRange, 0.0, 1.0), 2.0); - vec3 radiance = lightColor * lightIntensity * attenuation; + float NdotL = max(dot(N, L), 0.0); + float atten = 1.0 / (1.0 + dist * dist * 0.1); + float intensity = pointLightPos.w; - if (lightIntensity > 0.0 && lightRange > 0.0) - { - color += calcLight(N, V, L, radiance, albedo, roughness, metallic); - } - - // Tonemap + gamma - color = acesTonemap(color); - color = pow(color, vec3(1.0 / 2.2)); + vec3 color = fragAlbedo * pointLightColor.xyz * NdotL * intensity * atten; outColor = vec4(color, 1.0); } diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv index 8cf664694e8633fcfa322c1a7dca297592586889..78d2883697ab207150d2d0dfbf7c7ea38b2b662d 100644 GIT binary patch literal 2120 zcmZ9NSx-|@6on6zG6*t=3{KdB1BxOlAc{Z>YO7Yj7~^xb6`K?;X|E=}X^e?aKKYA$ z#{c7siR(M}Y-qSvo$i`G#D(7$>gNpM}z^(rh!X%+4>& z;nD9>-VvVx*W)^LBD>|<9)@1YS;+%QQ8Flh?7B!=O4*(Jt>CoS*0{86J+e_pTK~xN zzER%Uj2gS;dg9+NE{;mIoe#1184}(o?^YY-*Xvu-JCzZR@6$fG%VTQYk7|3d58aNM z!e*nMBilw)j~dFIa>L^J((Xjs1e21G5U#T_Y#4qKtQc4nRmvnAcqS)|t z;c^^T84~^7)v1cAd(B$>*>fH4zRq{Pg2aaza&Nx=wpxi2j+sUuME0sD(ZY zs+}3oSFvRtX^+!~^I;!@$G9nBzM|?Q2l?P~6644Vw=Lmr=0x9oh9?u~F|(sKKJ4@a zCJ&f?%swm@KC2#hW$2^QI(23wWAdkNF!qdaw@x?&d_reiz{>$MA2{L%bP~_o8`ocE z00*83eH#Z)&Qm(6g_)2OOy6)L!l!j+B-}9*@JPVKk4ndvd{z^4!5{ktoz@re)Hf~R zGd$zbmo>w;g#R2ItZ@Il^o+MB{@?|P&1g|N_mkJ|XAiCQJ`6t8Q;<%q)eB}%aEqD| zxtJFp++Q)gFLJXFe#i7*NbJE%CH|50t zyo4Bd?qm*d=6_K-9CfmrjD(!)5^TgUtBk~ACZ$^pcT7o$p*L*AWOc$@%w_5HYxs(E ze154;?!79(2fk00!(Ee*cUpp-lichE8@ceiA)!XYHv|42a?b`Ic;n`z!}Er}2EW_V zdE?lA1ny4YuyHr<04}eadDHhKwlm(l)vy$7#PC+Y*88$_-oEX9MLIcn|M;-?Rj(iI zeJybCe9VQt(+@kyNyv+z)sUCYtbPWcb?G??y!mWMr#|y}Bpp9^^I@;_Z9Y$=;|EWF zynQ(QspY8z?q!(av%u*%w?w CL3)D# literal 9464 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 bnHMJxof!7BAWZFEvwCsj(0TX5dH4PwWmZK^ diff --git a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs index 08ba118..12edcf1 100644 --- a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs @@ -86,6 +86,7 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen { lightPos = new Vector4(lt.Position, l.Intensity); lightColor = new Vector4(l.Color, l.Range); + Console.WriteLine($"[Vulkan] Point light: pos={lt.Position}, intensity={l.Intensity}, range={l.Range}, color={l.Color}"); } }); if (lightPos.W == 0) @@ -96,9 +97,14 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen { lightPos = new Vector4(l.Position, l.Intensity); lightColor = new Vector4(l.Color, l.Range); + Console.WriteLine($"[Vulkan] Point light (fallback): pos={l.Position}, intensity={l.Intensity}"); } }); } + if (lightPos.W == 0) + { + Console.WriteLine("[Vulkan] WARNING: No point light found in ECS!"); + } // Pack UBO: mat4 vp (64 bytes) + vec4 lightPos (16) + vec4 lightColor (16) = 96 bytes var uboData = stackalloc byte[128];