Skip to content

Commit 34fc37e

Browse files
mvaligurskyMartin Valigursky
and
Martin Valigursky
authored
WGSL shaders expose inputs as globals + fog fix (#7554)
Co-authored-by: Martin Valigursky <[email protected]>
1 parent 5bf6e62 commit 34fc37e

File tree

2 files changed

+51
-17
lines changed

2 files changed

+51
-17
lines changed

src/platform/graphics/webgpu/webgpu-shader-processor-wgsl.js

+47-11
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,9 @@ class WebgpuShaderProcessorWGSL {
324324
// generate fragment output struct
325325
const fOutput = WebgpuShaderProcessorWGSL.generateFragmentOutputStruct(fragmentExtracted.src, device.maxColorAttachments);
326326

327-
// VS - inject input copy to globals
327+
// inject the call to the function which copies the shader input globals
328328
vertexExtracted.src = WebgpuShaderProcessorWGSL.copyInputs(vertexExtracted.src, shader);
329+
fragmentExtracted.src = WebgpuShaderProcessorWGSL.copyInputs(fragmentExtracted.src, shader);
329330

330331
// VS - insert the blocks to the source
331332
const vBlock = `${attributesBlock}\n${vertexVaryingsBlock}\n${uniformsData.code}\n${resourcesData.code}\n`;
@@ -633,6 +634,8 @@ class WebgpuShaderProcessorWGSL {
633634

634635
static processVaryings(varyingLines, varyingMap, isVertex) {
635636
let block = '';
637+
let blockPrivates = '';
638+
let blockCopy = '';
636639
varyingLines.forEach((line, index) => {
637640
const match = line.match(VARYING);
638641
Debug.assert(match, `Varying line is not valid: ${line}`);
@@ -650,20 +653,51 @@ class WebgpuShaderProcessorWGSL {
650653

651654
// generates: `@location(0) @interpolate(perspective, centroid) smoothColor : vec3f`
652655
block += ` @location(${index}) ${line},\n`;
656+
657+
// fragment shader inputs (varyings)
658+
if (!isVertex) {
659+
660+
// private global variable for fragment varying
661+
blockPrivates += ` var<private> ${line};\n`;
662+
663+
// copy input variable to the private variable
664+
blockCopy += ` ${name} = input.${name};\n`;
665+
}
653666
}
654667
});
655668

656669
// add built-in varyings
657670
if (isVertex) {
658-
block += ' @builtin(position) position : vec4f,\n'; // output position
671+
block += ' @builtin(position) position : vec4f,\n'; // output position
659672
} else {
660-
block += ' @builtin(position) position : vec4f,\n'; // interpolated fragment position
673+
block += ' @builtin(position) position : vec4f,\n'; // interpolated fragment position
661674
block += ' @builtin(front_facing) frontFacing : bool,\n'; // front-facing
662675
block += ' @builtin(sample_index) sampleIndex : u32\n'; // sample index for MSAA
663676
}
664677

678+
// global variables for build-in input into fragment shader
679+
const fragmentGlobals = isVertex ? '' : `
680+
var<private> pcPosition: vec4f;
681+
var<private> pcFrontFacing: bool;
682+
var<private> pcSampleIndex: u32;
683+
${blockPrivates}
684+
685+
// function to copy inputs (varyings) to private global variables
686+
fn _pcCopyInputs(input: FragmentInput) {
687+
${blockCopy}
688+
pcPosition = input.position;
689+
pcFrontFacing = input.frontFacing;
690+
pcSampleIndex = input.sampleIndex;
691+
}
692+
`;
693+
665694
const structName = isVertex ? 'VertexOutput' : 'FragmentInput';
666-
return `struct ${structName} {\n${block}};\n`;
695+
return `
696+
struct ${structName} {
697+
${block}
698+
};
699+
${fragmentGlobals}
700+
`;
667701
}
668702

669703
static generateFragmentOutputStruct(src, numRenderTargets) {
@@ -757,25 +791,27 @@ class WebgpuShaderProcessorWGSL {
757791
}
758792
});
759793

760-
// add built-in attributes
761-
blockAttributes += ' @builtin(vertex_index) vertexIndex : u32,\n'; // vertex index
762-
blockAttributes += ' @builtin(instance_index) instanceIndex : u32\n'; // instance index
763-
764794
return `
765795
struct VertexInput {
766796
${blockAttributes}
797+
@builtin(vertex_index) vertexIndex : u32, // built-in vertex index
798+
@builtin(instance_index) instanceIndex : u32 // built-in instance index
767799
};
768800
769801
${blockPrivates}
802+
var<private> pcVertexIndex: u32;
803+
var<private> pcInstanceIndex: u32;
770804
771-
fn _copyInputs_(input: VertexInput) {
805+
fn _pcCopyInputs(input: VertexInput) {
772806
${blockCopy}
807+
pcVertexIndex = input.vertexIndex;
808+
pcInstanceIndex = input.instanceIndex;
773809
}
774810
`;
775811
}
776812

777813
/**
778-
* Injects a call to _copyInputs_ with the function's input parameter right after the opening
814+
* Injects a call to _pcCopyInputs with the function's input parameter right after the opening
779815
* brace of a WGSL function marked with `@vertex` or `@fragment`.
780816
*
781817
* @param {string} src - The source string containing the WGSL code.
@@ -799,7 +835,7 @@ class WebgpuShaderProcessorWGSL {
799835
const beginning = src.slice(0, braceIndex + 1);
800836
const end = src.slice(braceIndex + 1);
801837

802-
const lineToInject = `\n _copyInputs_(${inputName});`;
838+
const lineToInject = `\n _pcCopyInputs(${inputName});`;
803839
return beginning + lineToInject + end;
804840
}
805841

src/scene/shader-lib/chunks-wgsl/common/frag/fog.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
export default /* wgsl */`
22
3+
var<private> dBlendModeFogFactor : f32 = 1.0;
4+
35
#if (FOG != NONE)
46
uniform fog_color : vec3f;
57
@@ -11,13 +13,9 @@ export default /* wgsl */`
1113
#endif
1214
#endif
1315
14-
uniform dBlendModeFogFactor : f32;
15-
1616
fn getFogFactor() -> f32 {
1717
18-
// TODO: find a way to do this in WGSL, for now the fog is not working
19-
// let depth = gl_FragCoord.z / gl_FragCoord.w;
20-
let depth = 1.0;
18+
let depth = pcPosition.z / pcPosition.w;
2119
2220
var fogFactor : f32 = 0.0;
2321
@@ -34,7 +32,7 @@ fn getFogFactor() -> f32 {
3432
3533
fn addFog(color : vec3f) -> vec3f {
3634
#if (FOG != NONE)
37-
return mix(uniform.fog_color * uniform.dBlendModeFogFactor, color, getFogFactor());
35+
return mix(uniform.fog_color * dBlendModeFogFactor, color, getFogFactor());
3836
#else
3937
return color;
4038
#endif

0 commit comments

Comments
 (0)