// Field mip levels preserve the legacy trilinear AO sample at level 2.2. const GPU_FIELD_MIP = ` @group(0) @binding(0) var source: texture_2d; @group(0) @binding(1) var linear: sampler; @vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f { let pos=array(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3)); return vec4f(pos[i],0,1); } @fragment fn fs(@builtin(position) p: vec4f) -> @location(0) vec4f { let size=max(vec2u(1),textureDimensions(source)/2u); return textureSampleLevel(source,linear,p.xy/vec2f(size),0); }`; function gpuSmoothInit() { const d=GPU.device; const pipeline=(code,vertex,format)=>d.createRenderPipeline({layout:'auto',vertex:{module:d.createShaderModule({code:vertex}),entryPoint:'vs'},fragment:{module:d.createShaderModule({code}),entryPoint:'fs',targets:[{format}]},primitive:{topology:'triangle-list'}}); GPU.smooth=pipeline(GPU_SMOOTH,GPU_DRAW,GPU.format); GPU.fieldMip=pipeline(GPU_FIELD_MIP,GPU_FIELD_MIP,'rgba8unorm'); GPU.smoothUniform=d.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}); } function gpuSmoothTextures() { const w=R.bw,h=R.bh; GPU.smoothOver=Array.from({length:3},()=>gpuTexture(w,h)); GPU.smoothMask=gpuTexture(w,h,'r8uint'); GPU.backTex=gpuTexture(w,h,'rgba8unorm',true); GPU.treeTex=gpuTexture(w,h,'rgba8unorm',true); GPU.fieldTex=GPU.device.createTexture({size:[w,h],format:'rgba8unorm',mipLevelCount:Math.min(4,1+Math.floor(Math.log2(Math.max(w,h)))),usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT}); GPU.viewTextures.push(...GPU.smoothOver,GPU.smoothMask,GPU.backTex,GPU.treeTex,GPU.fieldTex); } function gpuSmoothBindings(group,view,buffer) { GPU.bindColourSmooth=group(GPU.colourSmooth,[buffer(GPU.uniform),buffer(GPU.lut),buffer(GPU.land),...GPU.worldTextures.slice(0,9).map(view),view(GPU.override),view(GPU.overrideGlow),view(GPU.colourTex),view(GPU.glowTex),view(GPU.backTex),view(GPU.treeTex),GPU.fieldTex.createView({baseMipLevel:0,mipLevelCount:1}),...GPU.smoothOver.map(view),view(GPU.smoothMask)]); GPU.bindSmooth=group(GPU.smooth,[buffer(GPU.uniform),view(GPU.colourTex),view(GPU.backTex),view(GPU.treeTex),view(GPU.fieldTex),view(GPU.lightTex),view(GPU.glowTex),GPU.sampler,buffer(GPU.smoothUniform)]); GPU.fieldMips=[]; for(let i=1;i