Smooth look on WebGPU: WGSL port fed by GPU inputs and CPU overrides (t88 phase 2c)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// The plain-cell rules mirror cellPixel; built geometry stays in the CPU override.
|
||||
const GPU_COLOUR = `
|
||||
function gpuColourShader(smooth) { return `
|
||||
struct Params { view: vec4f, world: vec4f, style: vec4f, effects: vec4f, camera: vec4f, light: vec4f, screen: vec4f, extra: vec4f }
|
||||
@group(0) @binding(0) var<uniform> u: Params;
|
||||
@group(0) @binding(1) var<storage, read> lut: array<vec4f>;
|
||||
@@ -9,6 +9,14 @@ ${['mat','flags','life','part','bgm','digp','noise','fog'].map((n,i)=>`@group(0)
|
||||
@group(0) @binding(12) var overrideT: texture_2d<f32>;
|
||||
@group(0) @binding(13) var overrideGlow: texture_2d<f32>;
|
||||
@group(0) @binding(14) var outputT: texture_storage_2d<rgba8unorm, write>;
|
||||
${smooth ? `@group(0) @binding(16) var backOut: texture_storage_2d<rgba8unorm, write>;
|
||||
@group(0) @binding(17) var treeOut: texture_storage_2d<rgba8unorm, write>;
|
||||
@group(0) @binding(18) var fieldOut: texture_storage_2d<rgba8unorm, write>;
|
||||
@group(0) @binding(19) var backOver: texture_2d<f32>;
|
||||
@group(0) @binding(20) var treeOver: texture_2d<f32>;
|
||||
@group(0) @binding(21) var fieldOver: texture_2d<f32>;
|
||||
@group(0) @binding(22) var maskOver: texture_2d<u32>;
|
||||
` : ""}
|
||||
@group(0) @binding(15) var glowT: texture_storage_2d<rgba8unorm, write>;
|
||||
fn phase(p: vec2i) -> i32 { return i32(lut[textureLoad(matT,p,0).r*3u+1u].x); }
|
||||
fn powder(p: vec2i) -> bool {
|
||||
@@ -20,6 +28,7 @@ fn colour(@builtin(global_invocation_id) id: vec3u) {
|
||||
let q=vec2i(id.xy); if (any(q>=vec2i(u.view.zw))) { return; }
|
||||
let p=q+vec2i(u.view.xy); let x=p.x; let y=p.y;
|
||||
var rgb=vec3f(0); var bloom=vec3f(0);
|
||||
${smooth ? "var cl=4.; var backValue=vec4f(0); var treeValue=vec4f(0); var fieldValue=vec4f(1,0,0,0);" : ""}
|
||||
if (all(p>=vec2i(0)) && all(p<vec2i(u.world.xy))) {
|
||||
let m=textureLoad(matT,p,0).r; let nz=f32(textureLoad(noiseT,p,0).r)-128.;
|
||||
let T=textureLoad(tempT,p,0).r; let mc=lut[m*3u]; let props=lut[m*3u+1u];
|
||||
@@ -32,7 +41,7 @@ fn colour(@builtin(global_invocation_id) id: vec3u) {
|
||||
if (fv>0.) {
|
||||
var shade=1.;
|
||||
let built=props.x==${PH_SOLID}. && (textureLoad(flagsT,p,0).r & ${F_NAT}u)==0u;
|
||||
if (m!=${EMPTY}u && !built) {
|
||||
if (${smooth ? "false" : `m!=${EMPTY}u && !built`}) {
|
||||
if (props.x==${PH_POWDER}.) { shade=1.1+nz*0.00065; }
|
||||
else if (props.x==${PH_SOLID}. && (powder(p+vec2i(-1,0)) || powder(p+vec2i(1,0)) || powder(p+vec2i(0,-1)) || powder(p+vec2i(0,1)))) { shade=0.72; }
|
||||
}
|
||||
@@ -43,7 +52,7 @@ fn colour(@builtin(global_invocation_id) id: vec3u) {
|
||||
let tb=textureLoad(bgmT,p,0).r; let dp=f32(textureLoad(digpT,p,0).r);
|
||||
let column=land[x]; let sky=land[i32(u.world.x)+y].rgb;
|
||||
var back: vec3f;
|
||||
if (tb!=0u) { back=(lut[tb*3u+2u].rgb+vec3f(nz*lut[tb*3u].a/128.))*(1.+dp/700.); }
|
||||
if (${smooth ? "false" : "tb!=0u"}) { back=(lut[tb*3u+2u].rgb+vec3f(nz*lut[tb*3u].a/128.))*(1.+dp/700.); }
|
||||
else if (f32(y)<column.x) {
|
||||
back=sky;
|
||||
if (u.style.y>0.01) { let gy=(sky.r+sky.g+sky.b)/3.*0.82; back+= (vec3f(gy)-sky)*u.style.y*vec3f(0.7,0.7,0.65); }
|
||||
@@ -52,13 +61,18 @@ fn colour(@builtin(global_invocation_id) id: vec3u) {
|
||||
if (f32(y)<column.y) { back=vec3f(${BG.dirt.join(',')}); }
|
||||
else if (f32(y)<column.z) { back=vec3f(${BG.stone.join(',')}); }
|
||||
else if (f32(y)<column.w) { back=vec3f(${BG.granite.join(',')}); }
|
||||
back+=vec3f(nz*0.06);
|
||||
${smooth ? "" : "back+=vec3f(nz*0.06);"}
|
||||
}
|
||||
${smooth ? `backValue=vec4f(quant(back),select(0.,1.,f32(y)<column.x));
|
||||
if (tb!=0u) { treeValue=vec4f(quant((lut[tb*3u+2u].rgb+vec3f(nz*lut[tb*3u].a/256.))*(1.+dp/700.)),select(128./255.,1.,tb==${LEAVES}u)); }
|
||||
cl=0.; if (m!=${EMPTY}u) { cl=5.; if(props.x==${PH_SOLID}.) { cl=1.; } else if(props.x==${PH_POWDER}.) { cl=2.; } else if(props.x==${PH_LIQUID}.) { cl=3.; } }
|
||||
fieldValue=vec4f(select(0.,1.,cl==1.),select(0.,1.,cl==3.),select(0.,1.,cl==5.),select(0.,1.,tb!=0u));
|
||||
` : ""}
|
||||
rgb=back;
|
||||
if (m!=${EMPTY}u) {
|
||||
rgb=(mc.rgb+vec3f(nz*mc.a*u.style.z/128.))*shade;
|
||||
rgb=(mc.rgb+vec3f(nz*mc.a*${smooth ? `select(u.style.z*0.35,0.,props.x==${PH_SOLID}.)` : "u.style.z"}/128.))*shade;
|
||||
if (m==${FIRE}u) { let f=f32(textureLoad(lifeT,p,0).r & 15u)*6.; rgb=vec3f(255.,120.+f,30.+f*0.5); }
|
||||
else if (m==${WATER}u && ((x*3+y*5+(i32(u.style.w)>>2)) & 15)==0) { rgb+=vec3f(14.); }
|
||||
else if (${smooth ? "false && " : ""}m==${WATER}u && ((x*3+y*5+(i32(u.style.w)>>2)) & 15)==0) { rgb+=vec3f(14.); }
|
||||
rgb=back+(rgb-back)*props.y;
|
||||
if (dp>0.) { let lift=dp/255.*(30.+sin(u.style.w*1.9+f32(x)*1.3+f32(y)*0.7)*6.); rgb+=lift*vec3f(1,1,1.08); }
|
||||
}
|
||||
@@ -72,11 +86,16 @@ fn colour(@builtin(global_invocation_id) id: vec3u) {
|
||||
}
|
||||
}
|
||||
rgb=quant(rgb*fv/255.);
|
||||
${smooth ? "backValue=vec4f(quant(backValue.rgb*fv),backValue.a); treeValue=vec4f(quant(treeValue.rgb*fv),treeValue.a);" : ""}
|
||||
}
|
||||
}
|
||||
// Flying grains replace colour, while the glow behind them remains.
|
||||
let over=textureLoad(overrideT,q,0);
|
||||
if (over.a>0.) { rgb=over.rgb; bloom=max(bloom,textureLoad(overrideGlow,q/2,0).rgb); }
|
||||
textureStore(outputT,q,vec4f(rgb,1));
|
||||
if (${smooth ? "textureLoad(maskOver,q,0).r>0u" : "over.a>0."}) { rgb=over.rgb; ${smooth ? "cl=over.a*255.; backValue=textureLoad(backOver,q,0); treeValue=textureLoad(treeOver,q,0); fieldValue=textureLoad(fieldOver,q,0);" : ""} bloom=max(bloom,textureLoad(overrideGlow,q/2,0).rgb); }
|
||||
${smooth ? "textureStore(backOut,q,backValue); textureStore(treeOut,q,treeValue); textureStore(fieldOut,q,fieldValue);" : ""}
|
||||
textureStore(outputT,q,vec4f(rgb,${smooth ? "cl/255." : "1"}));
|
||||
if (((q.x | q.y) & 1)==0) { textureStore(glowT,q/2,vec4f(bloom,1)); }
|
||||
}`;
|
||||
}
|
||||
const GPU_COLOUR = gpuColourShader(false);
|
||||
const GPU_COLOUR_SMOOTH = gpuColourShader(true);
|
||||
|
||||
Reference in New Issue
Block a user