载入中...
搜索中...
未找到
ScreenEffectsWgsl.h
浏览该文件的文档.
18fn color_at(uv:vec2f)->vec3f{return textureSampleLevel(mainTex,samp,clamp(uv,vec2f(0),vec2f(1)),0).rgb;}
19fn depth_at(uv:vec2f)->f32{let d=textureDimensions(depthTex);let q=vec2i(clamp(uv,vec2f(0),vec2f(1))*vec2f(d));return textureLoad(depthTex,clamp(q,vec2i(0),vec2i(d)-1),0).r;}
20fn normal_at(uv:vec2f)->vec3f{return textureSampleLevel(normalTex,normalSamp,clamp(uv,vec2f(0),vec2f(1)),0).xyz*2-1;}
21fn pbr_at(uv:vec2f)->u32{return u32(round(textureSampleLevel(normalTex,normalSamp,clamp(uv,vec2f(0),vec2f(1)),0).a*255));}
24fn color_rough(uv:vec2f,r:f32)->vec3f{let d=vec2f(max(p(21),.00001),max(p(22),.00001))*(1+r*6);return color_at(uv)*.4+(color_at(uv+vec2f(d.x,0))+color_at(uv-vec2f(d.x,0))+color_at(uv+vec2f(0,d.y))+color_at(uv-vec2f(0,d.y)))*.15;}
25fn world(m:mat4x4f,uv:vec2f,z:f32)->vec3f{let h=m*vec4f(uv*2-1,clamp(z,0,1),1);return h.xyz/max(h.w,.000001);}
26fn history_weights(t:f32)->vec4f{let t2=t*t;let t3=t2*t;return vec4f(-.5*t+t2-.5*t3,1-2.5*t2+1.5*t3,.5*t+2*t2-1.5*t3,-.5*t2+.5*t3);}
27fn history_cubic(uv:vec2f)->vec4f{let size=vec2f(textureDimensions(depthTex));let position=uv*size-.5;let base=floor(position);let f=fract(position);let wx=history_weights(f.x);let wy=history_weights(f.y);var result=vec4f(0);for(var y=0;y<4;y++){for(var x=0;x<4;x++){let suv=(base+vec2f(f32(x-1),f32(y-1))+.5)/size;result+=textureSampleLevel(depthTex,samp,clamp(suv,vec2f(0),vec2f(1)),0)*wx[x]*wy[y];}}return result;}
31fn gi_depth(uv:vec2f,use:f32)->f32{if use>.5{let levels=floor(floor(p(31))/8);let q=select(uv,vec2f(uv.x*.5,uv.y),levels>.5);return depth_at(q);}return textureSampleLevel(mainTex,samp,clamp(uv,vec2f(0),vec2f(1)),0).a;}
32fn gi_depth_range(uv0:vec2f,requested:i32)->vec2f{let uv=clamp(uv0,vec2f(0),vec2f(1));let levels=i32(floor(floor(p(31))/8));if levels<=0{return vec2f(depth_at(uv));}let mip=clamp(requested,0,levels-1);let atlas=textureDimensions(depthTex);var width=max(atlas.x/2u,1u);var height=max(atlas.y,1u);var offset=0u;for(var level=0;level<mip;level++){offset+=width;width=max(width/2u,1u);height=max(height/2u,1u);}let pixel=vec2u(clamp(floor(uv*vec2f(f32(width),f32(height))),vec2f(0),vec2f(f32(width-1u),f32(height-1u))));return textureLoad(depthTex,vec2i(offset+pixel.x,pixel.y),0).rg;}
33@fragment fn fs_main(i:FSIn)->@location(0) vec4f{let m=invvp();let radius=max(p(18),.0001);let intensity=max(p(19),0);let count=i32(clamp(p(20),4,32));let tw=max(p(27),.00001);let th=max(p(28),.00001);let use=p(29);let z=gi_depth(i.uv,use);
34 if z>=select(.999,.9999,use>.5)||intensity<.0001{return vec4f(0);}let pos=world(m,i.uv,z);let nh=m*vec4f(0,0,0,1);let fh=m*vec4f(0,0,1,1);let nc=nh.xyz/max(nh.w,.000001);let fc=fh.xyz/max(fh.w,.000001);let cam=nc-normalize(fc-nc)*max(p(16),.0001);
35 let dr=gi_depth(i.uv+vec2f(tw,0),use);let du=gi_depth(i.uv+vec2f(0,th),use);var n=normalize(cross(world(m,i.uv+vec2f(tw,0),dr)-pos,world(m,i.uv+vec2f(0,th),du)-pos));let packed=normal_at(i.uv);let receiverMetal=select(0.0,metallic_at(i.uv),p(30)>.5);if p(30)>.5&&dot(packed,packed)>.25{n=normalize(packed);}if dot(n,cam-pos)<0{n=-n;}
36 let up=select(vec3f(0,1,0),vec3f(1,0,0),abs(n.y)>.999);let tangent=normalize(up-n*dot(up,n));let bit=cross(n,tangent);let vp=inverse(m);let lightDir=normalize(vec3f(p(21),p(22),p(23))+vec3f(.000001));let lightColor=max(vec3f(p(24),p(25),p(26)),vec3f(0));var bounce=vec3f(0);var weight=0.0;var hitCount=0.0;
37 for(var q=1;q<=32;q++){if q>count{break;}let f=f32(q);let phase=floor(p(31))-floor(floor(p(31))/8)*8;let a=(f+phase*.618033989)*2.39996323;let rr=sqrt(fract((f+phase*.754877666)*.618033989));let dir=normalize(tangent*cos(a)+bit*sin(a)+n*.55);let samplePos=pos+dir*radius*rr;let clip=vp*vec4f(samplePos,1);let suv=clip.xy/max(clip.w,.000001)*.5+.5;if any(suv<vec2f(0))||any(suv>vec2f(1)){continue;}let levels=i32(floor(floor(p(31))/8));if levels>0&&use>.5{let footprint=abs(suv-i.uv)/vec2f(tw,th);let mip=clamp(i32(floor(log2(max(max(footprint.x,footprint.y)*.125,1)))),0,levels-1);let range=gi_depth_range(suv,mip);let padding=max(.0001,max(fract(p(31)),max(radius*.08,.01))/max(p(17),.001));if ndc.z<range.x-padding||ndc.z>range.y+padding{continue;}}let sz=gi_depth(suv,use);let hit=world(m,suv,sz);let mismatch=distance(hit,samplePos);let thick=max(fract(p(31)),max(radius*.08,.01));if mismatch>thick{continue;}var sn=normal_at(suv);if p(30)<.5||dot(sn,sn)<.25{sn=n;}else{sn=normalize(sn);}let toHit=hit-pos;let dist=length(toHit);if dist<.0001||dist>radius{continue;}let l=toHit/dist;let recv=max(dot(n,l),0);let send=max(dot(sn,-l),0);let directional=mix(.35,1,max(dot(sn,lightDir),0));let w=(1-smoothstep(radius*.4,radius,dist))*recv*send*(1-smoothstep(thick*.25,thick,mismatch))*directional;bounce+=color_at(suv)*lightColor*w;weight+=w;hitCount+=1;}
38 if weight<.0001{return vec4f(0);}let coverage=hitCount/max(f32(count),1);let receiverAlbedo=select(color_at(i.uv),textureSampleLevel(albedoTex,albedoSamp,i.uv,0).rgb,p(29)>.5&&p(30)>.5);bounce=bounce/weight*smoothstep(.08,.35,coverage)*intensity*receiverAlbedo*(1-receiverMetal);let alpha=clamp(max(bounce.r,max(bounce.g,bounce.b)),0,1);return vec4f(bounce/max(alpha,.0001),alpha)*i.color;}
42fn ssr_depth_range(uv0:vec2f,requested:i32)->vec2f{let uv=clamp(uv0,vec2f(0),vec2f(1));if p(31)<.5{return vec2f(depth_at(uv));}let mip=clamp(requested,0,max(i32(floor(p(31)))-1,0));let atlas=textureDimensions(depthTex);var width=max(atlas.x/2u,1u);var height=max(atlas.y,1u);var offset=0u;for(var level=0;level<mip;level++){offset+=width;width=max(width/2u,1u);height=max(height/2u,1u);}let pixel=vec2u(clamp(floor(uv*vec2f(f32(width),f32(height))),vec2f(0),vec2f(f32(width-1u),f32(height-1u))));return textureLoad(depthTex,vec2i(offset+pixel.x,pixel.y),0).rg;}
44@fragment fn fs_main(i:FSIn)->@location(0) vec4f{if p(28)<.5{return vec4f(0);}let z=ssr_depth(i.uv);if z>.999{return vec4f(0);}let m=invvp();let vp=inverse(m);let pos=world(m,i.uv,z);let tw=max(p(21),.00001);let th=max(p(22),.00001);let rough=roughness_at(i.uv);if rough>clamp(p(30),0,1){return vec4f(0);}
45 var n=normal_at(i.uv);if dot(n,n)<.25{n=normalize(cross(world(m,i.uv+vec2f(tw,0),ssr_depth(i.uv+vec2f(tw,0)))-pos,world(m,i.uv+vec2f(0,th),ssr_depth(i.uv+vec2f(0,th)))-pos));}else{n=normalize(n);}let cam=vec3f(p(16),p(17),p(18));if dot(n,cam-pos)<0{n=-n;}let v=normalize(cam-pos);let metal=metallic_at(i.uv);let surface=color_at(i.uv);let r=reflect(-v,n);if dot(r,v)>.1{return vec4f(0);}
46 let maxd=max(p(23),.01);let step=max(p(24),.001)*mix(.65,1.35,rough);let thickness=max(p(26),.001);let rayOrigin=pos+n*max(thickness*.02,.002);let count=i32(clamp(p(25),1,512));var ray=step;var previousRay=0.0;
47 for(var q=0;q<512;q++){if q>=count||ray>maxd{break;}let rayPos=rayOrigin+r*ray;let clip=vp*vec4f(rayPos,1);let ndc=clip.xyz/max(clip.w,.000001);var uv=ndc.xy*.5+.5;if any(uv<vec2f(0))||any(uv>vec2f(1))||ndc.z<0||ndc.z>1{break;}var traceMip=0;if p(31)>.5{let cone=1+rough*2*ray/max(step,.0001);traceMip=clamp(i32(floor(log2(max(cone,1)))),0,max(i32(floor(p(31)))-1,0));let range=ssr_depth_range(uv,traceMip);let padding=max(p(29),(range.y-range.x)*.25);if ndc.z<range.x-padding{previousRay=ray;ray+=step*exp2(f32(traceMip));continue;}}let scenePos=world(m,uv,ssr_depth(uv));let gap=distance(rayPos,scenePos);if ndc.z>ssr_depth(uv)-p(29)&&gap<=max(thickness,step*1.25){var lo=previousRay;var hi=ray;var refined=uv;for(var refine=0;refine<5;refine++){let mid=(lo+hi)*.5;let rc=vp*vec4f(rayOrigin+r*mid,1);let rn=rc.xyz/max(rc.w,.000001);let candidate=rn.xy*.5+.5;if rn.z>ssr_depth(candidate)-p(29){hi=mid;refined=candidate;}else{lo=mid;}}ray=hi;uv=refined;let refinedGap=distance(rayOrigin+r*ray,world(m,uv,ssr_depth(uv)));let hitAccuracy=1-smoothstep(thickness*.2,max(thickness,step*1.25),refinedGap);let hn=normal_at(uv);let hitFacing=select(1.0,smoothstep(.02,.25,dot(normalize(hn),-r)),dot(hn,hn)>.25);let center=ssr_depth(uv);let depthEdge=max(max(abs(ssr_depth(uv+vec2f(tw,0))-center),abs(ssr_depth(uv-vec2f(tw,0))-center)),max(abs(ssr_depth(uv+vec2f(0,th))-center),abs(ssr_depth(uv-vec2f(0,th))-center)));let continuity=1-smoothstep(.002,.025,depthEdge);let border=min(min(uv.x,uv.y),min(1-uv.x,1-uv.y));let sourceBorder=min(min(i.uv.x,i.uv.y),min(1-i.uv.x,1-i.uv.y));let rf=1-smoothstep(.35,1,rough)*.85;let confidence=clamp(smoothstep(.02,.12,border)*smoothstep(.01,.06,sourceBorder)*(1-smoothstep(0,maxd,ray))*max(p(27),0)*rf*hitFacing*continuity*hitAccuracy,0,1);let materialAlbedo=textureSampleLevel(albedoTex,albedoSamp,i.uv,0).rgb;let diffuseBasis=materialAlbedo*(1-metal);let safeBasis=max(diffuseBasis,vec3f(.001));let diffuseScale=max(min(surface.r/safeBasis.r,min(surface.g/safeBasis.g,surface.b/safeBasis.b)),0);let diffuseEstimate=min(diffuseBasis*diffuseScale,surface);let f0=mix(vec3f(.04),materialAlbedo,metal);let noV=max(dot(n,v),0);let brdf=rough*vec4f(-1,-.0275,-.572,.022)+vec4f(1,.0425,1.04,-.04);let a004=min(brdf.x*brdf.x,exp2(-9.28*noV))*brdf.x+brdf.y;let dfg=vec2f(-1.04,1.04)*a004+brdf.zw;let specWeight=max(f0*dfg.x+dfg.y,vec3f(0));let directionalAlbedo=max(dfg.x+dfg.y,.001);let multiScatter=vec3f(1)+f0*(min(1/directionalAlbedo,8)-1);let reflectedScene=diffuseEstimate+color_rough(uv,rough)*specWeight*multiScatter;return vec4f(reflectedScene*confidence,confidence)*i.color;}previousRay=ray;ray+=step;}
55fn temporal_encode_output(v0:vec4f)->vec4f{var v=v0;if p(23)>.5{v=vec4f(v.rgb/max(v.a,.0001),v.a);}return v;}
56fn temporal_spatial(uv:vec2f)->vec4f{let base=vec2f(p(16),p(17));let t=base*max(p(24),1);let centerDepth=textureSampleLevel(normalTex,normalSamp,uv,0).r;let center=temporal_decode_input(textureSampleLevel(mainTex,samp,uv,0));let centerRadiance=center.rgb/max(center.a,.05);let centerLog=log2(1+dot(max(centerRadiance,vec3f(0)),vec3f(.2126,.7152,.0722)));let dx=max(abs(textureSampleLevel(normalTex,normalSamp,uv+vec2f(base.x,0),0).r-centerDepth),abs(textureSampleLevel(normalTex,normalSamp,uv-vec2f(base.x,0),0).r-centerDepth));let dy=max(abs(textureSampleLevel(normalTex,normalSamp,uv+vec2f(0,base.y),0).r-centerDepth),abs(textureSampleLevel(normalTex,normalSamp,uv-vec2f(0,base.y),0).r-centerDepth));let depthScale=max(.0015,max(dx,dy)*2+.0005);var sum=center*4;var total=4.0;let offsets=array<vec2f,8>(vec2f(1,0),vec2f(-1,0),vec2f(0,1),vec2f(0,-1),vec2f(1,1),vec2f(-1,1),vec2f(1,-1),vec2f(-1,-1));for(var q=0;q<8;q++){let suv=uv+offsets[q]*t;let value=temporal_decode_input(textureSampleLevel(mainTex,samp,suv,0));let sampleDepth=textureSampleLevel(normalTex,normalSamp,suv,0).r;let depthWeight=exp(-abs(sampleDepth-centerDepth)/depthScale);let radiance=value.rgb/max(value.a,.05);let sampleLog=log2(1+dot(max(radiance,vec3f(0)),vec3f(.2126,.7152,.0722)));let radianceWeight=exp(-abs(sampleLog-centerLog)*1.5);let confidenceWeight=mix(.35,1,clamp(value.a*6,0,1));let kernelWeight=select(1.0,2.0,q<4);let weight=kernelWeight*depthWeight*radianceWeight*confidenceWeight*clamp(p(22),0,1);sum+=value*weight;total+=weight;}return sum/max(total,.0001);}
57fn temporal_rgb_to_ycocg(c:vec3f)->vec3f{return vec3f(c.r*.25+c.g*.5+c.b*.25,c.r*.5-c.b*.5,-c.r*.25+c.g*.5-c.b*.25);}
59fn temporal_hdr_encode(c:vec3f)->vec3f{let q=temporal_rgb_to_ycocg(max(c,vec3f(0)));let r=1+max(q.x,0);return vec3f(log2(r),q.yz/r);}
60fn temporal_hdr_decode(c:vec3f)->vec3f{let y=max(exp2(c.x)-1,0);let r=1+y;return max(temporal_ycocg_to_rgb(vec3f(y,c.yz*r)),vec3f(0));}
63 let texel=vec2f(p(16),p(17));let currentEncoded=temporal_hdr_encode(current.rgb);var lo=currentEncoded;var hi=currentEncoded;var sum=vec3f(0);var sumSq=vec3f(0);
64 for(var y=-1;y<=1;y++){for(var x=-1;x<=1;x++){let s=temporal_hdr_encode(temporal_decode_input(textureSampleLevel(mainTex,samp,i.uv+vec2f(f32(x)*texel.x,f32(y)*texel.y),0)).rgb);lo=min(lo,s);hi=max(hi,s);sum+=s;sumSq+=s*s;}}
65 let mean=sum/9;let sigma=sqrt(max(sumSq/9-mean*mean,vec3f(0)));lo=max(lo,mean-sigma*1.5);hi=min(hi,mean+sigma*1.5);hi.x=min(hi.x,mean.x+3);current=vec4f(temporal_hdr_decode(clamp(currentEncoded,lo,hi)),current.a);
66 let md=textureSampleLevel(normalTex,normalSamp,i.uv,0);let n=max(p(19),.0001);let f=max(p(20),n+.001);let vd=mix(n,f,md.r);let z=(f-n*f/max(vd,n))/(f-n);let pc=ssr_reprojection()*vec4f(i.uv*2-1,z,1);var huv=pc.xy/max(abs(pc.w),.000001)*.5+.5;huv+=(md.gb-vec2f(.5))*2;
67 let valid=all(huv>=vec2f(0))&&all(huv<=vec2f(1))&&pc.w>0;var history=temporal_decode_input(history_cubic(clamp(huv,vec2f(0),vec2f(1))));history=vec4f(temporal_hdr_decode(clamp(temporal_hdr_encode(history.rgb),lo,hi)),clamp(history.a,0,1));let cd=abs(current.a-history.a);let velocity=length((md.gb-vec2f(.5))*2);let historyDepth=textureSampleLevel(normalTex,normalSamp,clamp(huv,vec2f(0),vec2f(1)),0).r;let depthGradient=max(max(abs(textureSampleLevel(normalTex,normalSamp,i.uv+vec2f(texel.x,0),0).r-md.r),abs(textureSampleLevel(normalTex,normalSamp,i.uv-vec2f(texel.x,0),0).r-md.r)),max(abs(textureSampleLevel(normalTex,normalSamp,i.uv+vec2f(0,texel.y),0).r-md.r),abs(textureSampleLevel(normalTex,normalSamp,i.uv-vec2f(0,texel.y),0).r-md.r)));let depthTolerance=max(.0015,depthGradient*2+velocity*.5);let depthReject=smoothstep(depthTolerance,depthTolerance*4,abs(historyDepth-md.r));var reject=max(depthReject,max(smoothstep(.08,.35,cd),smoothstep(.01,.08,velocity)));if !valid||current.a<.01{reject=1;}return temporal_encode_output(mix(history,current,mix(clamp(p(21),.02,1),1,reject)))*i.color;
constexpr const char * kSsrTemporal
Definition ScreenEffectsWgsl.h:52
constexpr const char * kScreenEffectCommon
Definition ScreenEffectsWgsl.h:5