From 6a473bdc535651be7226dc2af80e2dac36d18578 Mon Sep 17 00:00:00 2001 From: emil28092005 Date: Thu, 18 Jun 2026 21:56:10 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20flip=20normal=20only=20by=20view=20direc?= =?UTF-8?q?tion=20=E2=80=94=20fixes=20both=20cubes=20and=20spheres?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous fix flipped normal by both light AND view direction: if (dot(N,L) < 0) N = -N; if (dot(N,V) < 0) N = -N; This double-flip broke spheres: when light is behind sphere, front faces get N flipped by light (now facing away from camera), then flipped back by view — but back faces get flipped once, causing inconsistency. Correct approach: flip ONLY by view direction: if (dot(N, V) < 0.0) N = -N; This ensures the normal always faces the camera. Faces pointing away from light naturally get NdotL=0 (no lighting) — correct behavior. Spheres keep smooth normals, cubes get inward normals fixed. --- .../Shaders/triangle.frag | 13 ++----------- .../Shaders/triangle.frag.spv | Bin 13808 -> 13640 bytes 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag index d0ceb73..ed0214b 100644 --- a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag +++ b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag @@ -138,17 +138,8 @@ void main() float dist = length(toLight); vec3 L = toLight / max(dist, 0.001); - // Flip normal if it faces away from light (fixes inward normals from bad winding) - if (dot(N, L) < 0.0) - { - N = -N; - } - - // Also flip for view direction if needed - if (dot(N, V) < 0.0) - { - N = -N; - } + // Flip normal to face camera — fixes cubes with bad winding without breaking spheres + if (dot(N, V) < 0.0) N = -N; float attenuation = pow(clamp(1.0 - dist / max(lightRange, 0.001), 0.0, 1.0), 2.0); vec3 radiance = lightColor * lightIntensity * attenuation; diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv index d349aecb67c68d27ea260aafb36bcea0d80adac5..f615ce72c89730c1d0135a90293100ff4d0addb3 100644 GIT binary patch delta 3337 zcmZ9OX>1i$7>3X7U0Ol^2rhtI(f65qKArYvPUd~zZ#(myb7t&Nz5THX{D}#Ca2!v%ZQ{*QY|=d|y!ayWCf!KFEp$s4Esl!r8W)suFHhjR z$MK}wBfiABa7ppSxs-cnf_0zx;&8BddXRD-jkBfQr{bOcYg>EreO*1#w9;-=T1#tZ z*V?wuNKI=_N2T?4x328($m14G`8R3pD+>4ocu}E6W5P>Yy85p2`HG61>u6iOrf*?e z=juXm%1xEHva7=vO}R6~|L<$s)rxoZ_g(H?R50ykhnq^W6|-gGx30TTx?yN{NjA|+ zKy|^QUL+lEcs6ShEhHUrCGsh>72MPbTD>^GC5mg1UtNI~_)t^n&dilN^nj)N>zgic z8Apnp;%GL`S7=81m(rZOaiQ@e;<@d6=UUv!@Un_rP@y8qHs8FaMSSyo^U8|j!@y>K zX9>^QacF`0%@jwoQL9Rv z4~kl%I|s%1BykRjaqJwDIOmYWIfo?9IV5q;A&K$u(rkH}IwRroY}Irsa3ahD%kD6r zoi_{1TN5mt2J^(eFC5L*1e}Ao$~iDjKF)w~qS*g&&fbr6_P=rBIRnOt=M2Pnk((NB zsLTxwR}L2?+QaK|cLZ#hyA*Z1Mw9vszgzfbjWWf;?-ADJ8oX_q$gMgU*zOf39-o`M zwn@0z+sd?Z_}wQ>m$s2}*qd~hPw-!n&E8>#cgA~x_6nN-89oR064|J<&k1*XPHUeR?$=o6le{2|W`ngQ`HRwYxeGOTDUk@$uSb9tL6ms3igKX zZ)#Yzw}ov%IKFVJ_O7s1<0!)${aWo6W|zLMJ2{EPhZ=kmv0IJz5_-373pZ6|gFF4{ z_&{dK?tKkAVIK_TDYB)W*zuO0!|pL z1K$ekiaLOu4%no=6X&Cbk0m`M953>{IE!gDeh|h7J*uI93GT3nuBZqO@ghHpQwSeU z68q{WVe}&!Jn3jSFf$wQyi5a+pM^&??1=m#jAnz^BuC^|X~#6Mlj*4LX!bbAh3PRi zUh;6W{Vt5g>s7e|_lL+y4GcDsKZW}>>>d1^_2Gt^>`Xex zcl9*y!sIK3qlXE{YI5Z$r%Sb*un)6Vf4uFI5(e|57& ch{qp0TaBW%!q~<%rMViHM74%)t6Nq1FAyVzZ2$lO delta 3586 zcmZ9O*>6=<6vp?xx3`qGAmvu8McZN>K!(=%Vk0FQMiYZ=_zP}mg-U5lY2m?#qd^lB z6O1`NI#qB$K`d3vP(>6JE7k@U6pm#tn(jkNRfZPT{%r#Lc)pDJ5Gldv3UT)D1z#eI(O7 zpJMN@5C!g&5q#eWeqb2SxX;Ds`dCMX*$UjzVLa=;5$_0km$i21dpf(LPFeS(#Fo~M z&Sh;Kk($+rPf1(R)w-y+J&#*7hjY@FE{ySc@a(u|*|c*DS~`1f^YMzs+uIf|>1pd& z9QQ47mr7gI*&gMbOyO%J{9ov-nynMQ0{IZy8*bbPtyY}BdFod$zlkx8`9Ndw_QG4=&}54b)HY6a zg^mz!ilbSZqOOI~f0E|h-8UOQDPA$S_eSe?A-tumBDhRR6m5oiRYrX64D*^Gjt>o+ z`CTPkx9!+W^SfFc&038{ajkepV>qOCljjr)ttu{3l{+kgbDa!&qUzubuMba_9dBNz zfiqFmBE2~|#z%{DYK&v&)Fe5lCdmiG=G=rVoSUdH)0u%hCHz2wKP`N(TB(MO z{TX3BZju_d@oM+`Njxh|e|%PZZG9?;Z%2%!+F1m7PFRn&xpV6UnBjaiOY*$8S4zVd zX9mw6#bz_zC>(fB+!uuJQd^_sRC$x|MjSBM3||x`kU8}W+%IekvQHRp1N%(a26jLgZi{tLm~Bcj zV$v5M2Ef&Z-Ew>(Jj8i0;gAGY&u)Rk!Z@MZS@=>|Pjuk0b5;m`L>QaJ`bv1G8n&Z) z!yEi!eJxzAe)KsS=pRm8p%`qI-wIPs(6{t&?l zgC+S>SWlD$dosyi;v~X{gT-e3TNwSM8Z+gCf@Xs_EzIoU_@5ERr^yBJAv`OBXpKvh z1N4tHI%6mBDZSAw@V~;89NRg);b!C0j>hFntd#f#adaC