Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[new feature] add vertex color morph target #16179

Merged
merged 7 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ export class TransformFeedbackBoundingHelper implements IBoundingInfoHelperPlatf
false, // useNormalMorph
false, // useTangentMorph
false, // useUVMorph
false // useUV2Morph
false, // useUV2Morph
false // useColorMorph
)
: 0;

Expand Down
4 changes: 3 additions & 1 deletion packages/dev/core/src/Layers/thinEffectLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ export class ThinEffectLayer {

let uv1 = false;
let uv2 = false;
const color = false;

// Diffuse
if (material) {
Expand Down Expand Up @@ -652,7 +653,8 @@ export class ThinEffectLayer {
false, // useNormalMorph
false, // useTangentMorph
uv1, // useUVMorph
uv2 // useUV2Morph
uv2, // useUV2Morph
color // useColorMorph
)
: 0;

Expand Down
4 changes: 3 additions & 1 deletion packages/dev/core/src/Lights/Shadows/shadowGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,7 @@ export class ShadowGenerator implements IShadowGenerator {
let useNormal = false;
let uv1 = false;
let uv2 = false;
const color = false;

// Normal bias.
if (this.normalBias && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
Expand Down Expand Up @@ -1677,7 +1678,8 @@ export class ShadowGenerator implements IShadowGenerator {
useNormal, // useNormalMorph
false, // useTangentMorph
uv1, // useUVMorph
uv2 // useUV2Morph
uv2, // useUV2Morph
color // useColorMorph
)
: 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
);
this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2);
this.registerInput("uv2", NodeMaterialBlockConnectionPointTypes.Vector2);
this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Color4);
this.registerOutput("positionOutput", NodeMaterialBlockConnectionPointTypes.Vector3);
this.registerOutput("normalOutput", NodeMaterialBlockConnectionPointTypes.Vector3);
this.registerOutput("tangentOutput", NodeMaterialBlockConnectionPointTypes.Vector4);
this.registerOutput("uvOutput", NodeMaterialBlockConnectionPointTypes.Vector2);
this.registerOutput("uv2Output", NodeMaterialBlockConnectionPointTypes.Vector2);
this.registerOutput("colorOutput", NodeMaterialBlockConnectionPointTypes.Color4);
}

/**
Expand Down Expand Up @@ -85,6 +87,13 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
return this._inputs[4];
}

/**
* Gets the color input component
*/
public get color(): NodeMaterialConnectionPoint {
return this._inputs[5];
}

/**
* Gets the position output component
*/
Expand Down Expand Up @@ -120,6 +129,13 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
return this._outputs[4];
}

/**
* Gets the color output component
*/
public get colorOutput(): NodeMaterialConnectionPoint {
return this._outputs[5];
}

public override initialize(state: NodeMaterialBuildState) {
state._excludeVariableName("morphTargetInfluences");

Expand Down Expand Up @@ -195,6 +211,15 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
}
uv2Input.output.connectTo(this.uv2);
}
if (!this.color.isConnected) {
let colorInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "color" && additionalFilteringInfo(b));

if (!colorInput) {
colorInput = new InputBlock("color");
colorInput.setAsAttribute("color");
}
colorInput.output.connectTo(this.color);
}
}

public override prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
Expand Down Expand Up @@ -234,11 +259,13 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
const tangent = this.tangent;
const uv = this.uv;
const uv2 = this.uv2;
const color = this.color;
const positionOutput = this.positionOutput;
const normalOutput = this.normalOutput;
const tangentOutput = this.tangentOutput;
const uvOutput = this.uvOutput;
const uv2Output = this.uv2Output;
const colorOutput = this.colorOutput;
const state = vertexShaderState;
const repeatCount = defines.NUM_MORPH_INFLUENCERS as number;

Expand All @@ -248,6 +275,7 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
const supportTangents = manager && manager.supportsTangents;
const supportUVs = manager && manager.supportsUVs;
const supportUV2s = manager && manager.supportsUV2s;
const supportColors = manager && manager.supportsColors;

let injectionCode = "";

Expand Down Expand Up @@ -310,6 +338,15 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
injectionCode += `${uv2Output.associatedVariableName} += (readVector3FromRawSampler(i, vertexID).xy - ${uv2.associatedVariableName}) * morphTargetInfluences[i];\n`;
injectionCode += `#endif\n`;
}
injectionCode += `#ifdef MORPHTARGETTEXTURE_HASUV2S\n`;
injectionCode += `vertexID += 1.0;\n`;
injectionCode += `#endif\n`;

if (supportColors) {
injectionCode += `#ifdef MORPHTARGETS_COLOR\n`;
injectionCode += `${colorOutput.associatedVariableName} += (readVector4FromRawSampler(i, vertexID) - ${color.associatedVariableName}) * ${uniformsPrefix}morphTargetInfluences[i];\n`;
injectionCode += `#endif\n`;
}

injectionCode += "}\n";
} else {
Expand Down Expand Up @@ -349,6 +386,12 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
injectionCode += `${uv2Output.associatedVariableName}.xy += (uv2_${index} - ${uv2.associatedVariableName}.xy) * morphTargetInfluences[${index}];\n`;
injectionCode += `#endif\n`;
}

if (supportColors && defines["VERTEXCOLOR_NME"]) {
injectionCode += `#ifdef MORPHTARGETS_COLOR\n`;
injectionCode += `${colorOutput.associatedVariableName} += (color${index} - ${color.associatedVariableName}) * ${uniformsPrefix}morphTargetInfluences[${index}];\n`;
injectionCode += `#endif\n`;
}
}
}
injectionCode += `#endif\n`;
Expand Down Expand Up @@ -376,6 +419,10 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
if (supportUV2s && defines["UV2"]) {
state.attributes.push(VertexBuffer.UV2Kind + "_" + index);
}

if (supportColors && defines["VERTEXCOLOR_NME"]) {
state.attributes.push(VertexBuffer.ColorKind + index);
}
}
}
}
Expand All @@ -398,11 +445,13 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
const tangent = this.tangent;
const uv = this.uv;
const uv2 = this.uv2;
const color = this.color;
const positionOutput = this.positionOutput;
const normalOutput = this.normalOutput;
const tangentOutput = this.tangentOutput;
const uvOutput = this.uvOutput;
const uv2Output = this.uv2Output;
const colorOutput = this.colorOutput;
const comments = `//${this.name}`;

state.uniforms.push("morphTargetInfluences");
Expand Down Expand Up @@ -437,6 +486,11 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
state.compilationString += `#else\n`;
state.compilationString += `${state._declareOutput(uv2Output)} = vec2(0., 0.);\n`;
state.compilationString += `#endif\n`;
state.compilationString += `#ifdef VERTEXCOLOR_NME\n`;
state.compilationString += `${state._declareOutput(colorOutput)} = ${color.associatedVariableName};\n`;
state.compilationString += `#else\n`;
state.compilationString += `${state._declareOutput(colorOutput)} = vec4(0., 0., 0., 0.);\n`;
state.compilationString += `#endif\n`;

// Repeatable content
this._repeatableContentAnchor = state._repeatableContentAnchor;
Expand Down
2 changes: 2 additions & 0 deletions packages/dev/core/src/Materials/Node/nodeMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export class NodeMaterialDefines extends MaterialDefines implements IImageProces
public MORPHTARGETS_UV = false;
/** Morph target uv2 */
public MORPHTARGETS_UV2 = false;
public MORPHTARGETS_COLOR = false;
/** Morph target support positions */
public MORPHTARGETTEXTURE_HASPOSITIONS = false;
/** Morph target support normals */
Expand All @@ -169,6 +170,7 @@ export class NodeMaterialDefines extends MaterialDefines implements IImageProces
public MORPHTARGETTEXTURE_HASUVS = false;
/** Morph target support uv2s */
public MORPHTARGETTEXTURE_HASUV2S = false;
public MORPHTARGETTEXTURE_HASCOLORS = false;
/** Number of morph influencers */
public NUM_MORPH_INFLUENCERS = 0;
/** Using a texture to store morph target data */
Expand Down
2 changes: 2 additions & 0 deletions packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,13 @@ export class PBRMaterialDefines extends MaterialDefines implements IImageProcess
public MORPHTARGETS_TANGENT = false;
public MORPHTARGETS_UV = false;
public MORPHTARGETS_UV2 = false;
public MORPHTARGETS_COLOR = false;
public MORPHTARGETTEXTURE_HASPOSITIONS = false;
public MORPHTARGETTEXTURE_HASNORMALS = false;
public MORPHTARGETTEXTURE_HASTANGENTS = false;
public MORPHTARGETTEXTURE_HASUVS = false;
public MORPHTARGETTEXTURE_HASUV2S = false;
public MORPHTARGETTEXTURE_HASCOLORS = false;
public NUM_MORPH_INFLUENCERS = 0;
public MORPHTARGETS_TEXTURE = false;

Expand Down
18 changes: 17 additions & 1 deletion packages/dev/core/src/Materials/materialHelper.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const _TmpMorphInfluencers = {
TANGENT: false,
UV: false,
UV2: false,
COLOR: false,
};

/**
Expand Down Expand Up @@ -77,6 +78,7 @@ export function BindFogParameters(scene: Scene, mesh?: AbstractMesh, effect?: Ef
* @param useTangentMorph Whether the tangent morph target is used
* @param useUVMorph Whether the UV morph target is used
* @param useUV2Morph Whether the UV2 morph target is used
* @param useColorMorph Whether the color morph target is used
* @returns The maxSimultaneousMorphTargets for the effect
*/
export function PrepareDefinesAndAttributesForMorphTargets(
Expand All @@ -88,7 +90,8 @@ export function PrepareDefinesAndAttributesForMorphTargets(
useNormalMorph: boolean,
useTangentMorph: boolean,
useUVMorph: boolean,
useUV2Morph: boolean
useUV2Morph: boolean,
useColorMorph: boolean
): number {
const numMorphInfluencers = morphTargetManager.numMaxInfluencers || morphTargetManager.numInfluencers;
if (numMorphInfluencers <= 0) {
Expand All @@ -102,12 +105,14 @@ export function PrepareDefinesAndAttributesForMorphTargets(
if (morphTargetManager.hasTangents) defines.push("#define MORPHTARGETTEXTURE_HASTANGENTS");
if (morphTargetManager.hasUVs) defines.push("#define MORPHTARGETTEXTURE_HASUVS");
if (morphTargetManager.hasUV2s) defines.push("#define MORPHTARGETTEXTURE_HASUV2S");
if (morphTargetManager.hasColors) defines.push("#define MORPHTARGETTEXTURE_HASCOLORS");

if (morphTargetManager.supportsPositions && usePositionMorph) defines.push("#define MORPHTARGETS_POSITION");
if (morphTargetManager.supportsNormals && useNormalMorph) defines.push("#define MORPHTARGETS_NORMAL");
if (morphTargetManager.supportsTangents && useTangentMorph) defines.push("#define MORPHTARGETS_TANGENT");
if (morphTargetManager.supportsUVs && useUVMorph) defines.push("#define MORPHTARGETS_UV");
if (morphTargetManager.supportsUV2s && useUV2Morph) defines.push("#define MORPHTARGETS_UV2");
if (morphTargetManager.supportsColors && useColorMorph) defines.push("#define MORPHTARGETS_COLOR");

defines.push("#define NUM_MORPH_INFLUENCERS " + numMorphInfluencers);

Expand All @@ -120,6 +125,7 @@ export function PrepareDefinesAndAttributesForMorphTargets(
_TmpMorphInfluencers.TANGENT = useTangentMorph;
_TmpMorphInfluencers.UV = useUVMorph;
_TmpMorphInfluencers.UV2 = useUV2Morph;
_TmpMorphInfluencers.COLOR = useColorMorph;

PrepareAttributesForMorphTargets(attribs, mesh, _TmpMorphInfluencers, usePositionMorph);
return numMorphInfluencers;
Expand All @@ -137,6 +143,7 @@ export function PrepareAttributesForMorphTargetsInfluencers(attribs: string[], m
_TmpMorphInfluencers.TANGENT = false;
_TmpMorphInfluencers.UV = false;
_TmpMorphInfluencers.UV2 = false;
_TmpMorphInfluencers.COLOR = false;
PrepareAttributesForMorphTargets(attribs, mesh, _TmpMorphInfluencers, true);
}

Expand All @@ -161,6 +168,7 @@ export function PrepareAttributesForMorphTargets(attribs: string[], mesh: Abstra
const tangent = manager && manager.supportsTangents && defines["TANGENT"];
const uv = manager && manager.supportsUVs && defines["UV1"];
const uv2 = manager && manager.supportsUV2s && defines["UV2"];
const color = manager && manager.supportsColors && defines["COLOR"];
for (let index = 0; index < influencers; index++) {
if (position) {
attribs.push(Constants.PositionKind + index);
Expand All @@ -182,6 +190,10 @@ export function PrepareAttributesForMorphTargets(attribs: string[], mesh: Abstra
attribs.push(Constants.UV2Kind + "_" + index);
}

if (color) {
attribs.push(Constants.ColorKind + index);
}

if (attribs.length > maxAttributesCount) {
Logger.Error("Cannot add more vertex attributes for mesh " + mesh.name);
}
Expand Down Expand Up @@ -764,12 +776,14 @@ export function PrepareDefinesForMorphTargets(mesh: AbstractMesh, defines: any)
defines["MORPHTARGETS_TANGENT"] = manager.supportsTangents && defines["TANGENT"];
defines["MORPHTARGETS_NORMAL"] = manager.supportsNormals && defines["NORMAL"];
defines["MORPHTARGETS_POSITION"] = manager.supportsPositions;
defines["MORPHTARGETS_COLOR"] = manager.supportsColors;

defines["MORPHTARGETTEXTURE_HASUVS"] = manager.hasUVs;
defines["MORPHTARGETTEXTURE_HASUV2S"] = manager.hasUV2s;
defines["MORPHTARGETTEXTURE_HASTANGENTS"] = manager.hasTangents;
defines["MORPHTARGETTEXTURE_HASNORMALS"] = manager.hasNormals;
defines["MORPHTARGETTEXTURE_HASPOSITIONS"] = manager.hasPositions;
defines["MORPHTARGETTEXTURE_HASCOLORS"] = manager.hasColors;

defines["NUM_MORPH_INFLUENCERS"] = manager.numMaxInfluencers || manager.numInfluencers;
defines["MORPHTARGETS"] = defines["NUM_MORPH_INFLUENCERS"] > 0;
Expand All @@ -781,12 +795,14 @@ export function PrepareDefinesForMorphTargets(mesh: AbstractMesh, defines: any)
defines["MORPHTARGETS_TANGENT"] = false;
defines["MORPHTARGETS_NORMAL"] = false;
defines["MORPHTARGETS_POSITION"] = false;
defines["MORPHTARGETS_COLOR"] = false;

defines["MORPHTARGETTEXTURE_HASUVS"] = false;
defines["MORPHTARGETTEXTURE_HASUV2S"] = false;
defines["MORPHTARGETTEXTURE_HASTANGENTS"] = false;
defines["MORPHTARGETTEXTURE_HASNORMALS"] = false;
defines["MORPHTARGETTEXTURE_HASPOSITIONS"] = false;
defines["MORPHTARGETTEXTURE_HAS_COLORS"] = false;

defines["MORPHTARGETS"] = false;
defines["NUM_MORPH_INFLUENCERS"] = 0;
Expand Down
4 changes: 3 additions & 1 deletion packages/dev/core/src/Materials/shaderMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ export class ShaderMaterial extends PushMaterial {
const uv2 = defines.indexOf("#define UV2") !== -1;
const tangent = defines.indexOf("#define TANGENT") !== -1;
const normal = defines.indexOf("#define NORMAL") !== -1;
const color = defines.indexOf("#define VERTEXCOLOR") !== -1;
numInfluencers = PrepareDefinesAndAttributesForMorphTargets(
manager,
defines,
Expand All @@ -785,7 +786,8 @@ export class ShaderMaterial extends PushMaterial {
normal, // useNormalMorph
tangent, // useTangentMorph
uv, // useUVMorph
uv2 // useUV2Morph
uv2, // useUV2Morph
color // useColorMorph
);
if (manager.isUsingTextureForTargets) {
if (uniforms.indexOf("morphTargetTextureIndices") === -1) {
Expand Down
2 changes: 2 additions & 0 deletions packages/dev/core/src/Materials/standardMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,13 @@ export class StandardMaterialDefines extends MaterialDefines implements IImagePr
public MORPHTARGETS_TANGENT = false;
public MORPHTARGETS_UV = false;
public MORPHTARGETS_UV2 = false;
public MORPHTARGETS_COLOR = false;
public MORPHTARGETTEXTURE_HASPOSITIONS = false;
public MORPHTARGETTEXTURE_HASNORMALS = false;
public MORPHTARGETTEXTURE_HASTANGENTS = false;
public MORPHTARGETTEXTURE_HASUVS = false;
public MORPHTARGETTEXTURE_HASUV2S = false;
public MORPHTARGETTEXTURE_HASCOLORS = false;
public NUM_MORPH_INFLUENCERS = 0;
public MORPHTARGETS_TEXTURE = false;
public NONUNIFORMSCALING = false; // https://playground.babylonjs.com#V6DWIH
Expand Down
6 changes: 6 additions & 0 deletions packages/dev/core/src/Meshes/abstractMesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ function applyMorph(data: FloatArray, kind: string, morphTargetManager: MorphTar
case VertexBuffer.UVKind:
getTargetData = (target) => target.getUVs();
break;
case VertexBuffer.UV2Kind:
getTargetData = (target) => target.getUV2s();
break;
case VertexBuffer.ColorKind:
getTargetData = (target) => target.getColors();
break;
default:
return;
}
Expand Down
Loading