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

WIP: Alpha fixes #15573

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
4 changes: 2 additions & 2 deletions packages/dev/core/src/Layers/effectLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ export abstract class EffectLayer {

// Diffuse
if (material) {
const needAlphaTest = material.needAlphaTesting();
const needAlphaTest = material.needAlphaTestingForMesh(mesh);

const diffuseTexture = material.getAlphaTestTexture();
const needAlphaBlendFromDiffuse =
Expand Down Expand Up @@ -986,7 +986,7 @@ export abstract class EffectLayer {
}

if (!renderingMaterial) {
const needAlphaTest = material.needAlphaTesting();
const needAlphaTest = material.needAlphaTestingForMesh(effectiveMesh);

const diffuseTexture = material.getAlphaTestTexture();
const needAlphaBlendFromDiffuse =
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/core/src/Lights/Shadows/shadowGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1563,7 +1563,7 @@ export class ShadowGenerator implements IShadowGenerator {
}

// Alpha test
const needAlphaTesting = material.needAlphaTesting();
const needAlphaTesting = material.needAlphaTestingForMesh(mesh);

if (needAlphaTesting || material.needAlphaBlending()) {
if (this.useOpacityTextureForTransparentShadow) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ export class BackgroundMaterial extends PushMaterial {
}

// Misc.
PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, this._shouldTurnAlphaTestOn(mesh), defines);
PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, this.needAlphaTestingForMesh(mesh), defines);

// Values that need to be evaluated on every frame
PrepareDefinesForFrameBoundValues(scene, engine, this, defines, useInstances, null, subMesh.getRenderingMesh().hasThinInstances);
Expand Down
59 changes: 18 additions & 41 deletions packages/dev/core/src/Materials/PBR/pbrBaseMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -721,12 +721,6 @@ export abstract class PBRBaseMaterial extends PushMaterial {
*/
public _alphaCutOff = 0.4;

/**
* Enforces alpha test in opaque or blend mode in order to improve the performances of some situations.
* @internal
*/
public override _forceAlphaTest = false;

/**
* A fresnel is applied to the alpha of the model to ensure grazing angles edges are not alpha tested.
* And/Or occlude the blended part. (alpha is converted to gamma to compute the fresnel)
Expand Down Expand Up @@ -1008,55 +1002,38 @@ export abstract class PBRBaseMaterial extends PushMaterial {
return "PBRBaseMaterial";
}

/**
* Returns true if alpha blending should be disabled.
*/
protected override get _disableAlphaBlending(): boolean {
return (
this._transparencyMode === PBRBaseMaterial.PBRMATERIAL_OPAQUE ||
this._transparencyMode === PBRBaseMaterial.PBRMATERIAL_ALPHATEST ||
this.subSurface?.disableAlphaBlending
);
protected _shouldUseAlphaFromAlbedoTexture(): boolean {
return this._albedoTexture != null && this._albedoTexture.hasAlpha && this._useAlphaFromAlbedoTexture && this._transparencyMode !== PBRBaseMaterial.PBRMATERIAL_OPAQUE;
}

/**
* @returns whether or not this material should be rendered in alpha blend mode.
*/
protected override _hasAlpha(mesh: AbstractMesh): boolean {
return super._hasAlpha(mesh) || this._shouldUseAlphaFromAlbedoTexture() || this._opacityTexture != null;
}

/** @override */
public override needAlphaBlending(): boolean {
if (this._disableAlphaBlending) {
if (this._hasTransparencyMode) {
return this._transparencyModeIsBlend;
}

if (this.subSurface?.disableAlphaBlending) {
return false;
}

return this.alpha < 1.0 || this._opacityTexture != null || this._shouldUseAlphaFromAlbedoTexture();
return super.needAlphaBlending();
}

/**
* @returns whether or not this material should be rendered in alpha test mode.
*/
/** @override */
public override needAlphaTesting(): boolean {
if (this._forceAlphaTest) {
return true;
if (this._hasTransparencyMode) {
return this._transparencyModeIsTest;
}

if (this.subSurface?.disableAlphaBlending) {
return false;
}

return this._hasAlphaChannel() && (this._transparencyMode == null || this._transparencyMode === PBRBaseMaterial.PBRMATERIAL_ALPHATEST);
}

/**
* @returns whether or not the alpha value of the albedo texture should be used for alpha blending.
*/
protected _shouldUseAlphaFromAlbedoTexture(): boolean {
return this._albedoTexture != null && this._albedoTexture.hasAlpha && this._useAlphaFromAlbedoTexture && this._transparencyMode !== PBRBaseMaterial.PBRMATERIAL_OPAQUE;
}

/**
* @returns whether or not there is a usable alpha channel for transparency.
*/
protected _hasAlphaChannel(): boolean {
return (this._albedoTexture != null && this._albedoTexture.hasAlpha) || this._opacityTexture != null;
return super.needAlphaTesting();
}

/**
Expand Down Expand Up @@ -1897,7 +1874,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
this._useLogarithmicDepth,
this.pointsCloud,
this.fogEnabled,
this._shouldTurnAlphaTestOn(mesh) || this._forceAlphaTest,
this.needAlphaTestingForMesh(mesh),
defines,
this._applyDecalMapAfterDetailMap
);
Expand Down
60 changes: 35 additions & 25 deletions packages/dev/core/src/Materials/material.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1058,11 +1058,6 @@ export class Material implements IAnimatable, IClipPlanesHolder {
return this.sideOrientation !== null ? this.sideOrientation : mesh.sideOrientation;
}

/**
* Enforces alpha test in opaque or blend mode in order to improve the performances of some situations.
*/
protected _forceAlphaTest = false;

/**
* The transparency mode of the material.
*/
Expand Down Expand Up @@ -1094,25 +1089,32 @@ export class Material implements IAnimatable, IClipPlanesHolder {

this._transparencyMode = value;

this._forceAlphaTest = value === Material.MATERIAL_ALPHATESTANDBLEND;

this._markAllSubMeshesAsTexturesAndMiscDirty();
}

/**
* Returns true if alpha blending should be disabled.
*/
protected get _disableAlphaBlending(): boolean {
return this._transparencyMode === Material.MATERIAL_OPAQUE || this._transparencyMode === Material.MATERIAL_ALPHATEST;
protected get _hasTransparencyMode(): boolean {
return this._transparencyMode != null;
}

protected get _transparencyModeIsBlend(): boolean {
return this._transparencyMode === Material.MATERIAL_ALPHABLEND || this._transparencyMode === Material.MATERIAL_ALPHATESTANDBLEND;
}

protected get _transparencyModeIsTest(): boolean {
return this._transparencyMode === Material.MATERIAL_ALPHATEST || this._transparencyMode === Material.MATERIAL_ALPHATESTANDBLEND;
}

protected _hasAlpha(mesh: AbstractMesh): boolean {
return this.alpha < 1.0 || mesh.hasVertexAlpha;
}

/**
* Specifies whether or not this material should be rendered in alpha blend mode.
* @returns a boolean specifying if alpha blending is needed
*/
public needAlphaBlending(): boolean {
if (this._disableAlphaBlending) {
return false;
if (this._hasTransparencyMode) {
return this._transparencyModeIsBlend;
}

return this.alpha < 1.0;
Expand All @@ -1124,36 +1126,44 @@ export class Material implements IAnimatable, IClipPlanesHolder {
* @returns a boolean specifying if alpha blending is needed for the mesh
*/
public needAlphaBlendingForMesh(mesh: AbstractMesh): boolean {
if (mesh.visibility < 1.0) {
return true;
if (this._hasTransparencyMode) {
return this._transparencyModeIsBlend;
}

if (this._disableAlphaBlending) {
return false;
if (this.needAlphaBlending()) {
return true;
}

return mesh.hasVertexAlpha || this.needAlphaBlending();
return this._hasAlpha(mesh) || mesh.visibility < 1.0;
}

/**
* Specifies whether or not this material should be rendered in alpha test mode.
* @returns a boolean specifying if an alpha test is needed.
*/
public needAlphaTesting(): boolean {
if (this._forceAlphaTest) {
return true;
if (this._hasTransparencyMode) {
return this._transparencyModeIsTest;
}

return false;
}

/**
* Specifies if material alpha testing should be turned on for the mesh
* Specifies whether or not this material should be rendered in alpha test mode when used with the given mesh.
* @param mesh defines the mesh to check
* @returns a boolean specifying if alpha testing should be turned on for the mesh
* @returns a boolean specifying if an alpha test is needed.
*/
protected _shouldTurnAlphaTestOn(mesh: AbstractMesh): boolean {
return !this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting();
public needAlphaTestingForMesh(mesh: AbstractMesh): boolean {
if (this._hasTransparencyMode) {
return this._transparencyModeIsTest;
}

if (this.needAlphaTesting()) {
return true;
}

return this._hasAlpha(mesh);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/core/src/Materials/shaderMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ export class ShaderMaterial extends PushMaterial {
}

// Alpha test
if (mesh && this._shouldTurnAlphaTestOn(mesh)) {
if (mesh && this.needAlphaTestingForMesh(mesh)) {
defines.push("#define ALPHATEST");
}

Expand Down
48 changes: 9 additions & 39 deletions packages/dev/core/src/Materials/standardMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,47 +871,17 @@ export class StandardMaterial extends PushMaterial {
return "StandardMaterial";
}

/**
* Specifies if the material will require alpha blending
* @returns a boolean specifying if alpha blending is needed
*/
public override needAlphaBlending(): boolean {
if (this._disableAlphaBlending) {
return false;
}

return (
this.alpha < 1.0 ||
this._opacityTexture != null ||
this._shouldUseAlphaFromDiffuseTexture() ||
(this._opacityFresnelParameters && this._opacityFresnelParameters.isEnabled)
);
}

/**
* Specifies if this material should be rendered in alpha test mode
* @returns a boolean specifying if an alpha test is needed.
*/
public override needAlphaTesting(): boolean {
if (this._forceAlphaTest) {
return true;
}

return this._hasAlphaChannel() && (this._transparencyMode == null || this._transparencyMode === Material.MATERIAL_ALPHATEST);
}

/**
* @returns whether or not the alpha value of the diffuse texture should be used for alpha blending.
*/
protected _shouldUseAlphaFromDiffuseTexture(): boolean {
return this._diffuseTexture != null && this._diffuseTexture.hasAlpha && this._useAlphaFromDiffuseTexture && this._transparencyMode !== Material.MATERIAL_OPAQUE;
}

/**
* @returns whether or not there is a usable alpha channel for transparency.
*/
protected _hasAlphaChannel(): boolean {
return (this._diffuseTexture != null && this._diffuseTexture.hasAlpha) || this._opacityTexture != null;
protected override _hasAlpha(mesh: AbstractMesh): boolean {
return super._hasAlpha(mesh) || this._shouldUseAlphaFromDiffuseTexture() || this._opacityTexture != null;
}

/** @override */
public override needAlphaBlending(): boolean {
return super.needAlphaBlending() || this._opacityFresnelParameters?.isEnabled;
}

/**
Expand Down Expand Up @@ -1224,7 +1194,7 @@ export class StandardMaterial extends PushMaterial {
this._useLogarithmicDepth,
this.pointsCloud,
this.fogEnabled,
this._shouldTurnAlphaTestOn(mesh) || this._forceAlphaTest,
this.needAlphaTestingForMesh(mesh),
defines,
this._applyDecalMapAfterDetailMap
);
Expand Down Expand Up @@ -1686,7 +1656,7 @@ export class StandardMaterial extends PushMaterial {
BindTextureMatrix(this._opacityTexture, ubo, "opacity");
}

if (this._hasAlphaChannel()) {
if (this._hasAlpha(mesh)) {
ubo.updateFloat("alphaCutOff", this.alphaCutOff);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ export class VolumetricLightScatteringPostProcess extends PostProcess {

// Alpha test
if (material) {
if (material.needAlphaTesting()) {
if (material.needAlphaTestingForMesh(mesh)) {
defines.push("#define ALPHATEST");
}

Expand Down Expand Up @@ -463,7 +463,7 @@ export class VolumetricLightScatteringPostProcess extends PostProcess {
effect.setMatrix("viewProjection", scene.getTransformMatrix());

// Alpha test
if (material.needAlphaTesting()) {
if (material.needAlphaTestingForMesh(effectiveMesh)) {
const alphaTexture = material.getAlphaTestTexture();

if (alphaTexture) {
Expand Down
4 changes: 2 additions & 2 deletions packages/dev/core/src/Rendering/depthRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export class DepthRenderer {

if (!renderingMaterial) {
// Alpha test
if (material.needAlphaTesting()) {
if (material.needAlphaTestingForMesh(effectiveMesh)) {
const alphaTexture = material.getAlphaTestTexture();

if (alphaTexture) {
Expand Down Expand Up @@ -404,7 +404,7 @@ export class DepthRenderer {
const attribs = [VertexBuffer.PositionKind];

// Alpha test
if (material.needAlphaTesting() && material.getAlphaTestTexture()) {
if (material.needAlphaTestingForMesh(mesh) && material.getAlphaTestTexture()) {
defines.push("#define ALPHATEST");
if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
attribs.push(VertexBuffer.UVKind);
Expand Down
4 changes: 2 additions & 2 deletions packages/dev/core/src/Rendering/geometryBufferRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ export class GeometryBufferRenderer {
if (material) {
let needUv = false;
// Alpha test
if (material.needAlphaTesting() && material.getAlphaTestTexture()) {
if (material.needAlphaTestingForMesh(mesh) && material.getAlphaTestTexture()) {
defines.push("#define ALPHATEST");
defines.push(`#define ALPHATEST_UV${material.getAlphaTestTexture().coordinatesIndex + 1}`);
needUv = true;
Expand Down Expand Up @@ -951,7 +951,7 @@ export class GeometryBufferRenderer {
material._preBind(drawWrapper, sideOrientation);

// Alpha test
if (material.needAlphaTesting()) {
if (material.needAlphaTestingForMesh(effectiveMesh)) {
const alphaTexture = material.getAlphaTestTexture();
if (alphaTexture) {
effect.setTexture("diffuseSampler", alphaTexture);
Expand Down
4 changes: 2 additions & 2 deletions packages/dev/core/src/Rendering/outlineRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ export class OutlineRenderer implements ISceneComponent {
}

// Alpha test
if (material && material.needAlphaTesting()) {
if (material && material.needAlphaTestingForMesh(effectiveMesh)) {
const alphaTexture = material.getAlphaTestTexture();
if (alphaTexture) {
effect.setTexture("diffuseSampler", alphaTexture);
Expand Down Expand Up @@ -288,7 +288,7 @@ export class OutlineRenderer implements ISceneComponent {
const scene = mesh.getScene();

// Alpha test
if (material.needAlphaTesting()) {
if (material.needAlphaTestingForMesh(mesh)) {
defines.push("#define ALPHATEST");
if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
attribs.push(VertexBuffer.UVKind);
Expand Down
Loading
Loading