48 lines
3.1 KiB
JavaScript
48 lines
3.1 KiB
JavaScript
// 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<f32>;
|
|
@group(0) @binding(1) var linear: sampler;
|
|
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
|
|
let pos=array<vec2f,3>(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<GPU.fieldTex.mipLevelCount;i++) GPU.fieldMips.push({
|
|
bind:group(GPU.fieldMip,[GPU.fieldTex.createView({baseMipLevel:i-1,mipLevelCount:1}),GPU.sampler]),
|
|
view:GPU.fieldTex.createView({baseMipLevel:i,mipLevelCount:1})
|
|
});
|
|
}
|
|
function gpuSmoothUpload() {
|
|
for(const [i,a] of [R.backPx,R.treePx,R.fieldPx].entries()) gpuWrite(GPU.smoothOver[i],a,R.bw,0,0,R.bw,R.bh);
|
|
gpuWrite(GPU.smoothMask,GPU.overrideMask,R.bw,0,0,R.bw,R.bh);
|
|
GPU.device.queue.writeBuffer(GPU.smoothUniform,0,new Float32Array([(performance.now()-SM.t0)/1000,smoothSurface(),SET.glow==='off'?0:SET.glow==='high'?0.9:0.55,0]));
|
|
}
|
|
function gpuSmoothMips(encoder) {
|
|
for(const m of GPU.fieldMips) {
|
|
const pass=encoder.beginRenderPass({colorAttachments:[{view:m.view,loadOp:'clear',storeOp:'store'}]});
|
|
pass.setPipeline(GPU.fieldMip);pass.setBindGroup(0,m.bind);pass.draw(3);pass.end();
|
|
}
|
|
}
|