How to properly use "defines"

I’m creating a shader using ShaderMaterial and I’m including some defines in the shader’s constructor, but they aren’t getting output in the shader code.

export default class StandardTriplanarShader extends THREE.ShaderMaterial {
	constructor(hasMorphTargets: boolean = false) {
		const uniforms = THREE.UniformsUtils.merge([
			THREE.UniformsLib['lights'],
			{
				normalScale: { value: new THREE.Vector2(1, 1) },
				normalMap: { value: null },
				albedoFactor: { value: new THREE.Vector3(1, 1, 1) },
				albedoMap: { value: null },
				metallicFactor: { value: 1.0 },
				roughnessFactor: { value: 1.0 },
				metallicRoughnessMap: { value: null },
				radianceMap: { value: null },
			}
		]);

		super({
			uniforms,
			vertexShader,
			fragmentShader,
			lights: true,
			morphTargets: hasMorphTargets,
			morphNormals: hasMorphTargets,
			name: 'StandardTriplanarShader',
			defines: {
				USE_COLOR_MAP: true,
				USE_NORMAL_MAP: true,
				USE_METALLIC_ROUGHNESS_MAP: true,
			}
		})
	}
	
	onBeforeCompile() {
		this.defines.USE_COLOR_MAP = !!this.uniforms.albedoMap.value;
		this.defines.USE_NORMAL_MAP = !!this.uniforms.normalMap.value;
		this.defines.USE_METALLIC_ROUGHNESS_MAP = !!this.uniforms.metallicRoughnessMap.value;
		console.log("onBeforeCompile");
		console.log(this.uniforms);
		console.log(this.defines);
	}
}

When I try to use this code in a #if statement I get a comilation error.

ERROR: 0:571: 'USE_NORMAL_MAP' : unexpected token after conditional expression
ERROR: 0:585: 'USE_COLOR_MAP' : unexpected token after conditional expression
ERROR: 0:595: 'USE_METALLIC_ROUGHNESS_MAP' : unexpected token after conditional expression

Looking at WegGLProgram.js I found that if the value of a defines field is false it is skipped.

function generateDefines( defines ) {

	const chunks = [];

	for ( const name in defines ) {

		const value = defines[ name ];

		if ( value === false ) continue;

		chunks.push( '#define ' + name + ' ' + value );

	}

	return chunks.join( '\n' );

}

If you absolutely need to use #if. Use 0 or 1 instead of true and false. Otherwise, use #ifdef.

2 Likes