playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
71 lines (70 loc) • 3.24 kB
JavaScript
import { Debug } from "../../../core/debug.js";
import { BINDGROUP_VIEW, bindGroupNames, uniformTypeToName } from "../constants.js";
import { ShaderProcessorGLSL } from "../shader-processor-glsl.js";
class WebglShaderProcessorGLSL extends ShaderProcessorGLSL {
/**
* @param {GraphicsDevice} device - The graphics device.
* @param {object} shaderDefinition - The shader definition.
* @param {Shader} shader - The shader.
* @returns {{ vshader: string, fshader: string }} The processed shader sources.
*/
static run(device, shaderDefinition, shader) {
const vertexExtracted = WebglShaderProcessorGLSL.extract(shaderDefinition.vshader, true);
const fragmentExtracted = WebglShaderProcessorGLSL.extract(shaderDefinition.fshader, true);
const concatUniforms = vertexExtracted.uniforms.concat(fragmentExtracted.uniforms);
const uniforms = Array.from(new Set(concatUniforms));
const parsedUniforms = WebglShaderProcessorGLSL.parseUniformLines(uniforms, shader);
const code = WebglShaderProcessorGLSL.processUniformsGL2(parsedUniforms, shaderDefinition.processingOptions);
const vshader = vertexExtracted.src.replace(ShaderProcessorGLSL.MARKER, code);
const fshader = fragmentExtracted.src.replace(ShaderProcessorGLSL.MARKER, code);
return { vshader, fshader };
}
/**
* Generate the uniform code for a WebGL2 shader: a single std140 view uniform block plus all
* non-view uniforms re-emitted as individual uniforms (which keep their per-uniform commit path).
*
* @param {Array<UniformLine>} uniforms - The parsed uniform lines.
* @param {ShaderProcessorOptions} processingOptions - The shader processing options.
* @returns {string} The generated GLSL.
*/
static processUniformsGL2(uniforms, processingOptions) {
let code = "";
const viewFormat = processingOptions.uniformFormats[BINDGROUP_VIEW];
if (viewFormat) {
code += WebglShaderProcessorGLSL.getUniformShaderDeclarationGL2(viewFormat, BINDGROUP_VIEW);
}
uniforms.forEach((uniform) => {
if (!processingOptions.hasUniform(uniform.name)) {
code += `uniform ${uniform.line};
`;
}
});
return code;
}
/**
* Generate a WebGL2 std140 uniform block declaration. Unlike the base
* {@link ShaderProcessorGLSL#getUniformShaderDeclaration} it emits no `set` / `binding` layout
* qualifiers - the block is linked to its binding point at runtime by WebglShader via
* `gl.uniformBlockBinding`.
*
* @param {UniformBufferFormat} format - The uniform buffer format.
* @param {number} bindGroup - The bind group index, used to name the block `ub_<bindGroupName>`.
* @returns {string} The block declaration.
*/
static getUniformShaderDeclarationGL2(format, bindGroup) {
const name = bindGroupNames[bindGroup];
let code = `layout(std140) uniform ub_${name} {
`;
format.uniforms.forEach((uniform) => {
const typeString = uniformTypeToName[uniform.type];
Debug.assert(typeString.length > 0, `Uniform type ${uniform.type} is not handled.`);
code += ` ${typeString} ${uniform.shortName}${uniform.count ? `[${uniform.count}]` : ""};
`;
});
return `${code}};
`;
}
}
export {
WebglShaderProcessorGLSL
};