From bf997e19000aa2a746007829208e8d3c7684bda6 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Mon, 23 Feb 2026 10:54:56 -0800 Subject: [PATCH] Distance-cull terrain derivative normal mapping Fade bump strength from full at 50 units to zero at 125 units to avoid noisy/harsh appearance on distant terrain. --- assets/shaders/terrain.frag.glsl | 13 +++++++------ assets/shaders/terrain.frag.spv | Bin 12140 -> 12496 bytes 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/assets/shaders/terrain.frag.glsl b/assets/shaders/terrain.frag.glsl index ed6d8273..0a424090 100644 --- a/assets/shaders/terrain.frag.glsl +++ b/assets/shaders/terrain.frag.glsl @@ -86,15 +86,17 @@ void main() { vec3 norm = normalize(Normal); - // Derivative-based normal mapping: perturb vertex normal using texture detail - { + // Derivative-based normal mapping: perturb vertex normal using texture detail. + // Fade out with distance — looks noisy/harsh beyond ~100 units. + float fragDist = length(viewPos.xyz - FragPos); + float bumpFade = 1.0 - smoothstep(50.0, 125.0, fragDist); + if (bumpFade > 0.001) { float lum = dot(finalColor.rgb, vec3(0.299, 0.587, 0.114)); float dLdx = dFdx(lum); float dLdy = dFdy(lum); vec3 dpdx = dFdx(FragPos); vec3 dpdy = dFdy(FragPos); - // Bump strength controls how much texture detail affects lighting - const float bumpStrength = 9.0; + float bumpStrength = 9.0 * bumpFade; vec3 perturbation = (dLdx * cross(norm, dpdy) + dLdy * cross(dpdx, norm)) * bumpStrength; vec3 candidate = norm - perturbation; float len2 = dot(candidate, candidate); @@ -123,8 +125,7 @@ void main() { vec3 result = ambient + shadow * diffuse; - float distance = length(viewPos.xyz - FragPos); - float fogFactor = clamp((fogParams.y - distance) / (fogParams.y - fogParams.x), 0.0, 1.0); + float fogFactor = clamp((fogParams.y - fragDist) / (fogParams.y - fogParams.x), 0.0, 1.0); result = mix(fogColor.rgb, result, fogFactor); outColor = vec4(result, 1.0); diff --git a/assets/shaders/terrain.frag.spv b/assets/shaders/terrain.frag.spv index b633e01bf700c854b0e0d7aae77ab40446020f8f..d8f3d684ed5996afb57de60dbc2ce0df70f4fe4b 100644 GIT binary patch literal 12496 zcmZ{p37pkc703TDi>SCGNGc9!g=wVVh6o5KsEvSviWcFUd2is^o5eRXEG;@@re#@{ zEw)*yWsz-`TSjJCmbg{6SxRM#*`8WiY2WYv{m;yGK6RP%IluEe=iYPg`QLm0{~4Ob z9=Jo6jmdV-cFBG>Cd=C%*;tqit~J+7+E=vC=pQK0IO52|4A?bm%HxdLE!!z;Ml0Q= zYLAZVkz0{JAkQF=5x6^jj3F7Qi40kGCww#gm$a{0vTWIs_7m51_VumlAJ|l@tf^Id zDr?HsdZlxqy1ruExFoLH(^(rVrvWWQq;qJ=c4Tf@)?e!Gt5sI4E0udUEMK&EdjE=< zhtFBxHERw&`|M&&cc~AR+qdT=4+%F4!p!FrLWC4WXxi(D!pdH*fw zu4+%IRt#YO8{k$}>UAFN@>0FjZNAom2WGX>rb>NL?_kfs2+w29)|L9(bse6>`^iman0FnIQpD0+J0L{`VCjY zvG0K|F&SgF4adxU-q`oTr(-=h68F5Z9&s!d;8>3i$IN=(Sli*#u^to`CP^ ztvmgEJ%2zi#V+ySeb#@*?y8s8o>1+l@(u2<=;f9AVpg3$=T_q6Z0oC)4QijAoX@DQ z-g}*Ee+JGZrkC0KC9e+Lbaaqp1qte_D(A&-SJwG zQg=tS(lZd-lCc`|YQ^WgmiP7#kMI4^)w?!{ZOnIEgHQHgWBeWA8|Q4;#pq4hlkhh8 zf_D%_S!*6^_bhhDV0Yi*Qn@$}P1%kVq&C={$L|3yx0myE+kZmC_Q>Y`N!ooQ{ueat z!rz+hkL~y?2I`fbwFB!K{aUj&_`XV=W7tt@RK4-sX25rrddk&uX}}4Yb0%D^(lfKs zw)xD*80+mh2Yn!NxUws<*B4_x>L_ z3(eWx*!4>PV2#W^r~9zk3yVvg1I2yTlD|uO2S@hO62`fXB-0SWv#_U{n5OOfXbR%q zK8bN}K-&&%sA10ja_;4bvyYtnFF4PD+<0UOd(H8TGne;PIu~u{;=b1J{gwK)^_x@w zt!U?J4(+YzG+x_y=c?a3EA?yZ_uT3Cu1fvd`o|W2@2S+Ut>3e0fA6Q%udP4k=e^{7 z#~>#W@0qum-+F~@y=*CGO?J<@MnA_$`)S+ncqIDCjqc}K(tg_Z8$zO=+(^I1yj+8E zcOVhxbC7!=;T&6Td%{^CIq%`<>-cgOBRKbs-0lhIoh8=>=l-!q&d+*#Z%spNVNY$C zx$RwMy>0qES82Sq@u=MIw^zjPMHcf+C1(>_JQ3tt+K|b7Gr0zB`zz4`?@PREGOmsM zuEi!d3415B{T*Nb&S+!hr}C6MGy3hP&zyS{T;#yaTiE8@6UI2l+^gZvIde|Hc1+i! ze{Zxo<;^(}t>1q7jM*0*Ydr*8|Ne+=Z)|JUhK$K|b9MmQczNU1Q<3LrVNb_4egZQ& z7#-v0AB)-0Y{#7k--g)qYtKiVd&DmVvtt&7y)w6l=12TFxjoWkDoQ*}X5VUn=(d44ie)@3`9DpYdEjS77@&FZGRxE#~2UYST8a_o;IU|5mUq`rie1 z{P25!+QNRYVGhUt2;03K{znUc*xrve*YkU{x!wEvwY@Lp_QC!O+8X*Srf@R62joKZ z{XcR1zu|Z8_H%sgCkrmt_Y}6z+xVvopJT>+yic4@Jm=@Y++GXA&Yjsa!*&b7y?b7C zZ1~4xUo!Ekd13E@{jn1#=6lt=yJA1I@$tEbG7Ial8@7Fn(--}Y25;DQ$V_dY>nYgY zyWu|*``&Hsc^>`eV84}BS&&o$z2#-4QZ zX|t`9<9e^!^qcQ~Z123VAIA1fIQ}oejumy*_8yiyid8u`=Wdhx2aIbq*EQ&C5yuL9 zOJaL(`TJ1#z0Yn-Z2k8nw*Gq)TmK`8t$%xBdnZ4U*v9*gi+tM8jUJk$Uek+G<{OnP--_EJu@8+=W?{{<9_Ft9Q`u%QB z{eCxxt>5qFu*7mydaW1?+sa zt;1K5t%YqJ?m*Hyd=1+edHa~>PQ-DSQ&DU2^@5WR8P7@A_YH*7XEP9UJD%}TH~s%) zjj>jB)bX2O>*)K&+}811h*)J_JK|g)LCZ%Se+f?O_$%zk3cq#yHImlxH`vC=M;(6)cHF4r<6yZ|qK?0Vk2;#$ z@r;i;>bH)uR<(I{LjMu*TVy<^K>JUKW1WcTbBrg@^49)o^xu&uk*APY^FIoH8E3?C z{)xybHpd)`MBaaapFu8SOymEJ*hk*Ew4(om*l!`C-?{h>l8-u#AwbSr*k>%ZeGW(R zZy0UFJo=l!D~mYCd$!Psj@Z4y#y(KQP6W#t>pNK6 zSnIwI*yrH5+LN*6jP?Dj9kKg@jdfgO_rsPm)_1pd%wY=HI$m6??*Qzj*z(5vZkLPr zsbJR;xu${LcVQohZI1EW&*nY|%ujX#Vyynl$))dwVEv96(+GD&IgI!yu? z2OA@Af4_g^qW>(gT-ZkxcI>euv5k?pzu!x8G2f%Wa>SG}b;5 zyAbSn#@a{Q*f_iDxZh3yd%wlI#dqV0aPo1U7lY*#o67TiVR1H=Ko}GE>PcW@yjS%( zk40$t$oq1zc~3z*Z}YZ;mI>Jp;@SE8wop`5p2*>#TyG4sXnvh&fL~>oceOvB#J<2qjnmXCF=2FocnmFtYX^(qKs96M^e2AtOFTx>bTrb=s7f^Zz;ocAiU zoVWw+du0JDD1$4AbM8c+gO0Uz6}~uQYq90Ji1Cb7!8XsBzIBM4dtV$ic{SMa(>+>) zlaHEogXI*P%Jsw^?SU{R_GmBI826|?*L5CRKK4T$obHEyY-3_S41kT1kNq$R<|p3| z`r}=^9&F9@$9rM}_g^yY$(yl=p^-)ZzQ??qraTX1hIIO*UnE;ye7B2Ft}We+yVnv8l}E+V(}i6~g$-5XW%tZv)FO$MR0N z94r@dDShSN4(Is#oy(>3obwRJJgx;tU1E*b!O6!OKMt02jm{&+QO7(!0XC0wGu|A| zEWK7+_P z4{^-nb71E&pWvv+=dtBu9$x^<#XMphbNuz8%D@#b(IUqZ(`jQJuW=RCyj-J8%i zBXO>71v{rWSGR%X6q_pM|7DEP^S>QVKGyRUusPx$-U>EGKF-Eh!RE0AcSpfV$6fI? z3}f{qt4$3pIq49i{Ak|r|{ncUWLTFWgA$|xXqkd@5p<> zj-$^x+>Mrtbv*!fUH7BYbv=l!FV^{8u)o*FGx{F3G4e6i_rd>btcT$BMcfaPxb$1( zhw%C$$B)4FmG{oK20sRyTVK@tCt!Z~n|H(Sy2#V_Fa$@hji9LLyrF8U+KufXPr zz5Z*koGrND6r6N$zb&}*ef~I{{f*ZjwRsGz??24y7{vbru*RMZ+j!(?YPchMmjdsM z-W74L?vD2V0(_6}hwM<;2cX+V**+WnuGLtdk+=;#74ZyALp!eeX~sPW{X)d1|3zs1 zYU?xw{bHmIxskd1{&@)^=Qq7~y!L^JW7$`1Ugr~e4=sFZ^UgrO46&K_FtmNuk=MWH zI7Z~136_hz+Al>M%f4d!jziBvtYAPqFwtVcrg<$*If?EWZ za~*L;{5y%U`Wz!-{npnv7CD<0y2izbHIvuxTIH7@?j`4}eNw?0ANx$sXXx|vIjEyn zCxflk5dGatryz1Z!`LHo_K!W{^VD`xsK=8CY&9@+`61={cQ@ZJUUAPWM7jD)8RueGqfJ0PQ)IJ00;H#<@LvlwC?}j29|zcSc<-Ua$P5&Ky;ebKK1 zmb-;DdoQg;^OU(&qI8s+ScjSi1m*DL+b_`BOhm|2P|)M z-)K9o<2zTMX}!Qc&;60eHvmra4Pu)wYP%k6|Fr%au;u+d-r8_T&(FraJr@;>~u|=u}81z4RG?Y zhKs;*=^EaMJ%s3sHCzlfpT1bbo51q6Si>dYbPbnc%NZMMkc&0E8Jw=+E!gQAF2i;W ztC7g@RkdHN71$Hcbv4;19&8IKc@By&AE!OZsaJq&M dVapjCYmkfh4}*=5zZZQ3EO#~H+0*vU{x7yG5itM& literal 12140 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