Skip to content

f0 will be infinity when refractionIndex is zero #6911

Description

@scarletsky
20240905093445_rec_-convert.mp4

PlayCanvas Editor is using v1.73.4.

Let's have a look how refractionIndex works:

StandardMaterialOptionsBuilder#_updateMaterialOptions:

        options.refractionTint = (stdMat.refraction !== 1.0) ? 1 : 0;
        options.refractionIndexTint = (stdMat.refractionIndex !== 1.0 / 1.5) ? 1 : 0;
        options.iorTint = stdMat.refractionIndex !== 1.0 / 1.5 ? 1 : 0;

options.iorTint will pass to ShaderGeneratorStandard#_addMap

        const isFloatTint = !!(tintOption & 1);
        const isVecTint = !!(tintOption & 2);
        const invertOption = !!(options[invertName]);
        subCode = this._addMapDefs(isFloatTint, isVecTint, vertexColorOption, textureOption, invertOption) + subCode;

isFloatTint will replace iorPS's macro:

#ifdef MAPFLOAT
uniform float material_refractionIndex;
#endif

void getIor() {
#ifdef MAPFLOAT
    dIor = material_refractionIndex;
#else
    dIor = 1.0 / 1.5;
#endif
}

In the end, the dIor will be used to calculate f0:

    float f0 = 1.0 / litArgs_ior;
    f0 = (f0 - 1.0) / (f0 + 1.0);
    f0 *= f0;

So when refractionIndex is zero, the f0 = (1.0 / 0.0) = infinity.

Here is the document of refraction

@Property {number} refraction Defines the visibility of refraction. Material can refract the same cube map as used for reflections.

If the refraction is zero, the refraction should be invisible.
It seems we should let options.iorTint respect refraction ?

-        options.iorTint = stdMat.refractionIndex !== 1.0 / 1.5 ? 1 : 0;
+        options.iorTint = (stdMaterial.refraction > 0 && stdMat.refractionIndex !== 1.0 / 1.5) ? 1 : 0;

Or how should it be ?

Metadata

Metadata

Assignees

Labels

Type

Fields

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions