@group(0) @binding(0) var viewProjectionMatrix : mat4x4; @group(0) @binding(1) var cameraPosition : vec3; struct VertexOutput { @builtin(position) position : vec4, @location(0) worldPosition : vec3, @location(1) worldNormal : vec3, }; @vertex fn v_main( @location(0) position : vec3, @location(1) normal : vec3 ) -> VertexOutput { var output : VertexOutput; output.position = viewProjectionMatrix * vec4( position, 1.0 ); output.worldPosition = position; output.worldNormal = normalize( normal ); return output; } struct FragmentOutput { @location(0) color : vec4, @builtin(frag_depth) depth : f32, }; @fragment fn f_main( input : VertexOutput ) -> FragmentOutput { let surfaceDir : vec3 = normalize( input.worldPosition ); let up : vec3 = vec3( 0.0, 1.0, 0.0 ); let cosAngle : f32 = clamp( dot( surfaceDir, up ), 0.0, 1.0 ); let skyZenith : vec3 = vec3( 0.45, 0.78, 0.98 ); let skyHorizon : vec3 = vec3( 0.12, 0.28, 0.52 ); let sunDir : vec3 = normalize( vec3( -0.1, 0.97, 0.2 ) ); let sunAngle : f32 = clamp( dot( surfaceDir, sunDir ), 0.0, 1.0 ); let sunExposure : f32 = smoothstep( 0.94, 0.999, sunAngle ); let skyGradient : vec3 = mix( skyHorizon, skyZenith, pow( cosAngle, 1.1 ) ); let airglow : vec3 = vec3( 0.09, 0.16, 0.28 ) * pow( 1.0 - cosAngle, 3.0 ); let scattering : vec3 = skyGradient + airglow; let sunDisk : vec3 = vec3( 1.0, 0.94, 0.76 ) * sunExposure * sunExposure * 1.6; let skyColor : vec3 = mix( scattering, scattering + sunDisk, sunExposure ); let horizonBlend : f32 = smoothstep( 0.0, 0.6, 1.0 - cosAngle ); let baseColor : vec3 = mix( skyHorizon, skyZenith, max( cosAngle, 0.1 ) ); let color : vec3 = mix( baseColor * 1.1 + vec3( 0.02, 0.03, 0.04 ), skyColor * 0.9, 1.0 - horizonBlend ); return FragmentOutput( vec4( color, 1.0 ), 0.999 ); }