import defined from "../../Core/defined.js"; import defaultValue from "../../Core/defaultValue.js"; import ShaderDestination from "../../Renderer/ShaderDestination.js"; import AlphaMode from "../AlphaMode.js"; import LightingModel from "./LightingModel.js"; import MaterialStageFS from "../../Shaders/ModelExperimental/MaterialStageFS.js"; import Pass from "../../Renderer/Pass.js"; import Matrix3 from "../../Core/Matrix3.js"; import Cartesian3 from "../../Core/Cartesian3.js"; import Cartesian4 from "../../Core/Cartesian4.js"; import ModelComponents from "../ModelComponents.js"; var Material = ModelComponents.Material; var MetallicRoughness = ModelComponents.MetallicRoughness; var SpecularGlossiness = ModelComponents.SpecularGlossiness; /** * The material pipeline stage processes textures and other uniforms needed * to render a primitive. This handles the following material types: *
u_baseColorTexture
* @param {String} defineName The name of the texture for use in the defines, minus any prefix or suffix. For example, "BASE_COLOR" or "EMISSIVE"
*
* @private
*/
function processTextureTransform(
shaderBuilder,
uniformMap,
textureReader,
uniformName,
defineName
) {
// Add a define to enable the texture transformation code in the shader.
var transformDefine = "HAS_" + defineName + "_TEXTURE_TRANSFORM";
shaderBuilder.addDefine(
transformDefine,
undefined,
ShaderDestination.FRAGMENT
);
// Add a uniform for the transformation matrix
var transformUniformName = uniformName + "Transform";
shaderBuilder.addUniform(
"mat3",
transformUniformName,
ShaderDestination.FRAGMENT
);
uniformMap[transformUniformName] = function () {
return textureReader.transform;
};
}
/**
* Process a single texture and add it to the shader and uniform map.
*
* @param {ShaderBuilder} shaderBuilder The shader builder to modify
* @param {Object.u_baseColorTexture
* @param {String} defineName The name of the texture for use in the defines, minus any prefix or suffix. For example, "BASE_COLOR" or "EMISSIVE"
*
* @private
*/
function processTexture(
shaderBuilder,
uniformMap,
textureReader,
uniformName,
defineName,
defaultTexture
) {
// Add a uniform for the texture itself
shaderBuilder.addUniform(
"sampler2D",
uniformName,
ShaderDestination.FRAGMENT
);
uniformMap[uniformName] = function () {
return defaultValue(textureReader.texture, defaultTexture);
};
// Add a #define directive to enable using the texture in the shader
var textureDefine = "HAS_" + defineName + "_TEXTURE";
shaderBuilder.addDefine(textureDefine, undefined, ShaderDestination.FRAGMENT);
// Add a #define to tell the shader which texture coordinates varying to use.
var texCoordIndex = textureReader.texCoord;
var texCoordVarying = "v_texCoord_" + texCoordIndex;
var texCoordDefine = "TEXCOORD_" + defineName;
shaderBuilder.addDefine(
texCoordDefine,
texCoordVarying,
ShaderDestination.FRAGMENT
);
// Some textures have matrix transforms (e.g. for texture atlases). Add those
// to the shader if present.
var textureTransform = textureReader.transform;
if (
defined(textureTransform) &&
!Matrix3.equals(textureTransform, Matrix3.IDENTITY)
) {
processTextureTransform(
shaderBuilder,
uniformMap,
textureReader,
uniformName,
defineName
);
}
}
function processMaterialUniforms(
material,
uniformMap,
shaderBuilder,
defaultTexture,
defaultNormalTexture,
defaultEmissiveTexture
) {
var emissiveTexture = material.emissiveTexture;
if (defined(emissiveTexture)) {
processTexture(
shaderBuilder,
uniformMap,
emissiveTexture,
"u_emissiveTexture",
"EMISSIVE",
defaultEmissiveTexture
);
}
var emissiveFactor = material.emissiveFactor;
if (
defined(emissiveFactor) &&
!Cartesian3.equals(emissiveFactor, Material.DEFAULT_EMISSIVE_FACTOR)
) {
shaderBuilder.addUniform(
"vec3",
"u_emissiveFactor",
ShaderDestination.FRAGMENT
);
uniformMap.u_emissiveFactor = function () {
return material.emissiveFactor;
};
shaderBuilder.addDefine(
"HAS_EMISSIVE_FACTOR",
undefined,
ShaderDestination.FRAGMENT
);
}
var normalTexture = material.normalTexture;
if (defined(normalTexture)) {
processTexture(
shaderBuilder,
uniformMap,
normalTexture,
"u_normalTexture",
"NORMAL",
defaultNormalTexture
);
}
var occlusionTexture = material.occlusionTexture;
if (defined(occlusionTexture)) {
processTexture(
shaderBuilder,
uniformMap,
occlusionTexture,
"u_occlusionTexture",
"OCCLUSION",
defaultTexture
);
}
}
function processSpecularGlossinessUniforms(
material,
uniformMap,
shaderBuilder,
defaultTexture
) {
var specularGlossiness = material.specularGlossiness;
shaderBuilder.addDefine(
"USE_SPECULAR_GLOSSINESS",
undefined,
ShaderDestination.FRAGMENT
);
var diffuseTexture = specularGlossiness.diffuseTexture;
if (defined(diffuseTexture)) {
processTexture(
shaderBuilder,
uniformMap,
diffuseTexture,
"u_diffuseTexture",
"DIFFUSE",
defaultTexture
);
}
var diffuseFactor = specularGlossiness.diffuseFactor;
if (
defined(diffuseFactor) &&
!Cartesian4.equals(diffuseFactor, SpecularGlossiness.DEFAULT_DIFFUSE_FACTOR)
) {
shaderBuilder.addUniform(
"vec4",
"u_diffuseFactor",
ShaderDestination.FRAGMENT
);
uniformMap.u_diffuseFactor = function () {
return specularGlossiness.diffuseFactor;
};
shaderBuilder.addDefine(
"HAS_DIFFUSE_FACTOR",
undefined,
ShaderDestination.FRAGMENT
);
}
var specularGlossinessTexture = specularGlossiness.specularGlossinessTexture;
if (defined(specularGlossinessTexture)) {
processTexture(
shaderBuilder,
uniformMap,
specularGlossinessTexture,
"u_specularGlossinessTexture",
"SPECULAR_GLOSSINESS",
defaultTexture
);
}
var specularFactor = specularGlossiness.specularFactor;
if (
defined(specularFactor) &&
!Cartesian3.equals(
specularFactor,
SpecularGlossiness.DEFAULT_SPECULAR_FACTOR
)
) {
shaderBuilder.addUniform(
"vec3",
"u_specularFactor",
ShaderDestination.FRAGMENT
);
uniformMap.u_specularFactor = function () {
return specularGlossiness.specularFactor;
};
shaderBuilder.addDefine(
"HAS_SPECULAR_FACTOR",
undefined,
ShaderDestination.FRAGMENT
);
}
var glossinessFactor = specularGlossiness.glossinessFactor;
if (
defined(glossinessFactor) &&
glossinessFactor !== SpecularGlossiness.DEFAULT_GLOSSINESS_FACTOR
) {
shaderBuilder.addUniform(
"float",
"u_glossinessFactor",
ShaderDestination.FRAGMENT
);
uniformMap.u_glossinessFactor = function () {
return specularGlossiness.glossinessFactor;
};
shaderBuilder.addDefine(
"HAS_GLOSSINESS_FACTOR",
undefined,
ShaderDestination.FRAGMENT
);
}
}
function processMetallicRoughnessUniforms(
material,
uniformMap,
shaderBuilder,
defaultTexture
) {
var metallicRoughness = material.metallicRoughness;
shaderBuilder.addDefine(
"USE_METALLIC_ROUGHNESS",
undefined,
ShaderDestination.FRAGMENT
);
var baseColorTexture = metallicRoughness.baseColorTexture;
if (defined(baseColorTexture)) {
processTexture(
shaderBuilder,
uniformMap,
baseColorTexture,
"u_baseColorTexture",
"BASE_COLOR",
defaultTexture
);
}
var baseColorFactor = metallicRoughness.baseColorFactor;
if (
defined(baseColorFactor) &&
!Cartesian4.equals(
baseColorFactor,
MetallicRoughness.DEFAULT_BASE_COLOR_FACTOR
)
) {
shaderBuilder.addUniform(
"vec4",
"u_baseColorFactor",
ShaderDestination.FRAGMENT
);
uniformMap.u_baseColorFactor = function () {
return metallicRoughness.baseColorFactor;
};
shaderBuilder.addDefine(
"HAS_BASE_COLOR_FACTOR",
undefined,
ShaderDestination.FRAGMENT
);
}
var metallicRoughnessTexture = metallicRoughness.metallicRoughnessTexture;
if (defined(metallicRoughnessTexture)) {
processTexture(
shaderBuilder,
uniformMap,
metallicRoughnessTexture,
"u_metallicRoughnessTexture",
"METALLIC_ROUGHNESS",
defaultTexture
);
}
var metallicFactor = metallicRoughness.metallicFactor;
if (
defined(metallicFactor) &&
metallicFactor !== MetallicRoughness.DEFAULT_METALLIC_FACTOR
) {
shaderBuilder.addUniform(
"float",
"u_metallicFactor",
ShaderDestination.FRAGMENT
);
uniformMap.u_metallicFactor = function () {
return metallicRoughness.metallicFactor;
};
shaderBuilder.addDefine(
"HAS_METALLIC_FACTOR",
undefined,
ShaderDestination.FRAGMENT
);
}
var roughnessFactor = metallicRoughness.roughnessFactor;
if (
defined(roughnessFactor) &&
roughnessFactor !== MetallicRoughness.DEFAULT_ROUGHNESS_FACTOR
) {
shaderBuilder.addUniform(
"float",
"u_roughnessFactor",
ShaderDestination.FRAGMENT
);
uniformMap.u_roughnessFactor = function () {
return metallicRoughness.roughnessFactor;
};
shaderBuilder.addDefine(
"HAS_ROUGHNESS_FACTOR",
undefined,
ShaderDestination.FRAGMENT
);
}
}
// Exposed for testing
MaterialPipelineStage._processTexture = processTexture;
MaterialPipelineStage._processTextureTransform = processTextureTransform;
export default MaterialPipelineStage;