Skip to content

Commit

Permalink
Merge pull request #1286 from actnwit/feat/gltf-anisotropy
Browse files Browse the repository at this point in the history
feat: gltf anisotropy
  • Loading branch information
emadurandal authored Aug 6, 2023
2 parents 674576e + fa589d3 commit 96d396a
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 24 deletions.
16 changes: 16 additions & 0 deletions src/foundation/definitions/ShaderSemantics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,16 @@ const IridescenceThicknessTexture = new ShaderSemanticsClass({
const GaussianKernelSize = new ShaderSemanticsClass({
str: 'gaussianKernelSize',
});
const AnisotropyStrength = new ShaderSemanticsClass({
str: 'anisotropyStrength',
});
const AnisotropyRotation = new ShaderSemanticsClass({
str: 'anisotropyRotation',
});
const AnisotropyTexture = new ShaderSemanticsClass({
str: 'anisotropyTexture',
});

const GaussianRatio = new ShaderSemanticsClass({ str: 'gaussianRatio' });
const IsHorizontal = new ShaderSemanticsClass({ str: 'isHorizontal' });

Expand Down Expand Up @@ -538,6 +548,9 @@ const typeList = [
GaussianKernelSize,
GaussianRatio,
IsHorizontal,
AnisotropyStrength,
AnisotropyRotation,
AnisotropyTexture,
];

function from(index: ShaderSemanticsIndex): ShaderSemanticsEnum {
Expand Down Expand Up @@ -795,4 +808,7 @@ export const ShaderSemantics = Object.freeze({
GaussianKernelSize,
GaussianRatio,
IsHorizontal,
AnisotropyStrength,
AnisotropyRotation,
AnisotropyTexture,
});
19 changes: 19 additions & 0 deletions src/foundation/helpers/MaterialHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { MaterialRepository } from '../materials/core/MaterialRepository';
import { Vrm0xMaterialProperty } from '../../types';
import { Sampler } from '../textures/Sampler';
import {
dummyAnisotropyTexture,
dummyBlackTexture,
dummyBlueTexture,
dummyWhiteTexture,
Expand Down Expand Up @@ -117,6 +118,7 @@ function createPbrUberMaterial({
isSheen = false,
isSpecular = false,
isIridescence = false,
isAnisotropy = false,
isShadow = false,
useTangentAttribute = false,
useNormalTexture = true,
Expand All @@ -134,6 +136,7 @@ function createPbrUberMaterial({
(isSheen ? '+sheen' : '') +
(isSpecular ? '+specular' : '') +
(isIridescence ? '+iridescence' : '') +
(isAnisotropy ? '+anisotropy' : '') +
(useTangentAttribute ? '+tangentAttribute' : '') +
(useNormalTexture ? '' : '-normalTexture');

Expand Down Expand Up @@ -336,6 +339,21 @@ function createPbrUberMaterial({
max: Number.MAX_VALUE,
});
}
if (isAnisotropy) {
additionalShaderSemanticInfo.push({
semantic: ShaderSemantics.AnisotropyTexture,
componentType: ComponentType.Int,
compositionType: CompositionType.Texture2D,
stage: ShaderType.PixelShader,
isCustomSetting: true,
soloDatum: false,
updateInterval: ShaderVariableUpdateInterval.EveryTime,
initialValue: [textureSlotIdx++, dummyAnisotropyTexture],
min: 0,
max: Number.MAX_VALUE,
needUniformInDataTextureMode: true,
});
}

if (isShadow) {
additionalShaderSemanticInfo.push({
Expand Down Expand Up @@ -363,6 +381,7 @@ function createPbrUberMaterial({
isSheen,
isSpecular,
isIridescence,
isAnisotropy,
isShadow,
useTangentAttribute,
useNormalTexture,
Expand Down
6 changes: 6 additions & 0 deletions src/foundation/importer/Gltf2Importer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,12 @@ export class Gltf2Importer {
gltfJson.textures[iridescenceThicknessTexture.index];
}
}
if (Is.exist(extensions.KHR_materials_anisotropy)) {
const anisotropyTexture = extensions.KHR_materials_anisotropy.anisotropyTexture;
if (anisotropyTexture !== void 0) {
anisotropyTexture.texture = gltfJson.textures[anisotropyTexture.index];
}
}
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions src/foundation/importer/ModelConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,7 @@ export class ModelConverter {
isSheen: Is.exist(materialJson?.extensions?.KHR_materials_sheen),
isSpecular: Is.exist(materialJson?.extensions?.KHR_materials_specular),
isIridescence: Is.exist(materialJson?.extensions?.KHR_materials_iridescence),
isAnisotropy: Is.exist(materialJson?.extensions?.KHR_materials_anisotropy),
isShadow: rnLoaderOptions.shadow ? true : false,
useTangentAttribute,
useNormalTexture,
Expand Down Expand Up @@ -2294,6 +2295,8 @@ function setupPbrMetallicRoughness(

setup_KHR_materials_iridescence(materialJson, material, gltfModel);

setup_KHR_materials_anisotropy(materialJson, material, gltfModel);

// BaseColor TexCoord Transform
setup_KHR_texture_transform(baseColorTexture, material, metallicRoughnessTexture);
}
Expand Down Expand Up @@ -2634,3 +2637,38 @@ function setup_KHR_materials_iridescence(
}
}
}

function setup_KHR_materials_anisotropy(
materialJson: RnM2Material,
material: Material,
gltfModel: RnM2
) {
const KHR_materials_anisotropy = materialJson?.extensions?.KHR_materials_anisotropy;
if (Is.exist(KHR_materials_anisotropy)) {
const anisotropyStrength = Is.exist(KHR_materials_anisotropy.anisotropyStrength)
? KHR_materials_anisotropy.anisotropyStrength
: 0.0;
material.setParameter(ShaderSemantics.AnisotropyStrength, anisotropyStrength);
const anisotropyRotation = Is.exist(KHR_materials_anisotropy.anisotropyRotation)
? KHR_materials_anisotropy.anisotropyRotation
: 0.0;
material.setParameter(
ShaderSemantics.AnisotropyRotation,
Vector2.fromCopy2(Math.cos(anisotropyRotation), Math.sin(anisotropyRotation))
);

const anisotropyTexture = KHR_materials_anisotropy.anisotropyTexture;
if (anisotropyTexture != null) {
const rnAnisotropyTexture = ModelConverter._createTexture(
anisotropyTexture.texture!,
gltfModel
);
const rnSampler = ModelConverter._createSampler(anisotropyTexture.texture!);
material.setTextureParameter(
ShaderSemantics.AnisotropyTexture,
rnAnisotropyTexture,
rnSampler
);
}
}
}
6 changes: 6 additions & 0 deletions src/foundation/materials/contents/CustomMaterialContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class CustomMaterialContent extends AbstractMaterialContent {
isSheen,
isSpecular,
isIridescence,
isAnisotropy,
isShadow,
useTangentAttribute,
useNormalTexture,
Expand All @@ -44,6 +45,7 @@ export class CustomMaterialContent extends AbstractMaterialContent {
isSheen?: boolean;
isSpecular?: boolean;
isIridescence?: boolean;
isAnisotropy?: boolean;
isShadow?: boolean;
useTangentAttribute: boolean;
useNormalTexture: boolean;
Expand All @@ -64,6 +66,7 @@ export class CustomMaterialContent extends AbstractMaterialContent {
(isSpecular ? '+specular' : '') +
(isSheen ? '+sheen' : '') +
(isIridescence ? '+iridescence' : '') +
(isAnisotropy ? '+anisotropy' : '') +
(useTangentAttribute ? '+tangentAttribute' : ''),
{ isMorphing, isSkinning, isLighting }
);
Expand Down Expand Up @@ -135,6 +138,9 @@ export class CustomMaterialContent extends AbstractMaterialContent {
if (isIridescence) {
this.__definitions += '#define RN_USE_IRIDESCENCE\n';
}
if (isAnisotropy) {
this.__definitions += '#define RN_USE_ANISOTROPY\n';
}
if (isShadow) {
this.__definitions += '#define RN_USE_SHADOW_MAPPING\n';
}
Expand Down
4 changes: 4 additions & 0 deletions src/foundation/materials/core/DummyTextures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const dummyBlackTexture = new Texture();
export const dummyBlackCubeTexture = new CubeTexture();
export const sheenLutTexture = new Texture();
export const dummySRGBGrayTexture = new Texture();
export const dummyAnisotropyTexture = new Texture();

export async function initDefaultTextures() {
if (dummyWhiteTexture.isTextureReady) {
Expand All @@ -18,13 +19,15 @@ export async function initDefaultTextures() {
dummyBlackCubeTexture.tryToSetUniqueName('dummyBlackCubeTexture', true);
sheenLutTexture.tryToSetUniqueName('sheenLutTexture', true);
dummySRGBGrayTexture.tryToSetUniqueName('dummySRGBGrayTexture', true);
dummyAnisotropyTexture.tryToSetUniqueName('dummyAnisotropyTexture', true);

dummyWhiteTexture.generate1x1TextureFrom();
dummyBlueTexture.generate1x1TextureFrom('rgba(127.5, 127.5, 255, 1)');
dummyBlackTexture.generate1x1TextureFrom('rgba(0, 0, 0, 1)');
dummyBlackCubeTexture.load1x1Texture('rgba(0, 0, 0, 1)');
await sheenLutTexture.generateSheenLutTextureFromDataUri();
dummySRGBGrayTexture.generate1x1TextureFrom('rgba(186, 186, 186, 1)');
dummyAnisotropyTexture.generate1x1TextureFrom('rgba(255, 127.5, 255, 1)');
}

export const DefaultTextures = {
Expand All @@ -34,4 +37,5 @@ export const DefaultTextures = {
dummyBlackCubeTexture,
sheenLutTexture,
dummySRGBGrayTexture,
dummyAnisotropyTexture,
};
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ void main (){
vec3 normal_inWorld = normalize(v_normal_inWorld);
#ifdef RN_MTOON_HAS_BUMPMAP
vec3 normal = texture(u_normalTexture, v_texcoord_0).xyz * 2.0 - 1.0;
normal_inWorld = perturb_normal(normal_inWorld, viewVector, v_texcoord_0, normal);
mat3 TBN = getTBN(normal_inWorld, viewVector, v_texcoord_0);
normal_inWorld = normalize(TBN * normal);
#endif

#ifdef RN_MTOON_IS_OUTLINE
Expand Down
58 changes: 49 additions & 9 deletions src/webgl/shaderity_shaders/PbrSingleShader/PbrSingleShader.frag
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ uniform float u_ior; // initialValue=1.5
uniform float u_iridescenceThicknessMaximum; // initialValue=400
#endif

#ifdef RN_USE_ANISOTROPY
uniform float u_anisotropyStrength; // initialValue=0
uniform vec2 u_anisotropyRotation; // initialValue=(1,0)
#endif

uniform float u_alphaCutoff; // initialValue=(0.01)

#pragma shaderity: require(../common/rt0.glsl)
Expand Down Expand Up @@ -379,8 +384,19 @@ vec3 getNormalForEnv(mat3 rotEnvMatrix, vec3 normal_inWorld, float materialSID)
return normal_forEnv;
}

vec3 getReflection(mat3 rotEnvMatrix, vec3 viewDirection, vec3 normal_inWorld, float materialSID) {
vec3 getReflection(mat3 rotEnvMatrix, vec3 viewDirection, vec3 normal_inWorld, float materialSID, float perceptualRoughness, float anisotropy, vec3 anisotropyDirection) {
#ifdef RN_USE_ANISOTROPY

float tangentRoughness = mix(perceptualRoughness, 1.0, anisotropy * anisotropy);
vec3 anisotropicTangent = cross(anisotropyDirection, viewDirection);
vec3 anisotropicNormal = cross(anisotropicTangent, anisotropyDirection);
float bendFactor = 1.0 - anisotropy * (1.0 - perceptualRoughness);
float bendFactorPow4 = bendFactor * bendFactor * bendFactor * bendFactor;
vec3 bentNormal = normalize(mix(anisotropicNormal, normal_inWorld, bendFactorPow4));
vec3 reflection = rotEnvMatrix * reflect(-viewDirection, bentNormal);
#else
vec3 reflection = rotEnvMatrix * reflect(-viewDirection, normal_inWorld);
#endif
if (get_inverseEnvironment(materialSID, 0)) {
reflection.x *= -1.0;
}
Expand All @@ -391,15 +407,15 @@ vec3 IBLContribution(float materialSID, vec3 normal_inWorld, float NdotV, vec3 v
vec3 albedo, vec3 F0, float perceptualRoughness, float clearcoatRoughness, vec3 clearcoatNormal_inWorld,
float clearcoat, float VdotNc, vec3 geomNormal_inWorld, float cameraSID, float transmission, vec3 v_position_inWorld,
float thickness, vec3 sheenColor, float sheenRoughness, float albedoSheenScalingNdotV, float ior,
vec3 iridescenceFresnel, vec3 iridescenceF0, float iridescence)
vec3 iridescenceFresnel, vec3 iridescenceF0, float iridescence, float anisotropy, vec3 anisotropyDirection)
{
vec4 iblParameter = get_iblParameter(materialSID, 0);
float rot = iblParameter.w + 3.1415;
mat3 rotEnvMatrix = mat3(cos(rot), 0.0, -sin(rot), 0.0, 1.0, 0.0, sin(rot), 0.0, cos(rot));
ivec2 hdriFormat = get_hdriFormat(materialSID, 0);

vec3 normal_forEnv = getNormalForEnv(rotEnvMatrix, normal_inWorld, materialSID);
vec3 reflection = getReflection(rotEnvMatrix, viewDirection, normal_inWorld, materialSID);
vec3 reflection = getReflection(rotEnvMatrix, viewDirection, normal_inWorld, materialSID, perceptualRoughness, anisotropy, anisotropyDirection);

// IBL
#ifdef RN_USE_IRIDESCENCE
Expand Down Expand Up @@ -446,9 +462,8 @@ vec3 IBLContribution(float materialSID, vec3 normal_inWorld, float NdotV, vec3 v
#ifdef RN_USE_CLEARCOAT
float VdotNg = dot(geomNormal_inWorld, viewDirection);
vec3 clearcoatNormal_forEnv = getNormalForEnv(rotEnvMatrix, normal_inWorld, materialSID);
vec3 clearcoatReflection = getReflection(rotEnvMatrix, viewDirection, normal_inWorld, materialSID);
IblResult coatResult = getIBLRadianceGGX(materialSID, VdotNc, viewDirection, vec3(0.0), F0,
clearcoatRoughness, iblParameter, hdriFormat, rotEnvMatrix, clearcoatNormal_forEnv, clearcoatReflection);
clearcoatRoughness, iblParameter, hdriFormat, rotEnvMatrix, clearcoatNormal_forEnv, reflection);
vec3 coatLayer = coatResult.specular;

float clearcoatFresnel = 0.04 + (1.0 - 0.04) * pow(1.0 - abs(VdotNc), 5.0);
Expand Down Expand Up @@ -500,14 +515,15 @@ void main ()
int normalTexcoordIndex = get_normalTexcoordIndex(materialSID, 0);
vec2 normalTexcoord = getTexcoord(normalTexcoordIndex);
vec2 normalTexUv = uvTransform(normalTextureTransform.xy, normalTextureTransform.zw, normalTextureRotation, normalTexcoord);
mat3 TBN = getTBN(normal_inWorld, viewVector, normalTexUv);
#ifdef RN_USE_NORMAL_TEXTURE
vec3 normalTexValue = texture(u_normalTexture, normalTexUv).xyz;
if(normalTexValue.b >= 128.0 / 255.0) {
// normal texture is existence
vec3 normalTex = normalTexValue * 2.0 - 1.0;
float normalScale = get_normalScale(materialSID, 0);
vec3 scaledNormal = normalize(normalTex * vec3(normalScale, normalScale, 1.0));
normal_inWorld = perturb_normal(normal_inWorld, viewVector, normalTexUv, scaledNormal);
normal_inWorld = normalize(TBN * scaledNormal);
}
#endif

Expand Down Expand Up @@ -543,6 +559,23 @@ void main ()
vec3 viewDirection = normalize(viewVector);
float NdotV = saturateEpsilonToOne(dot(normal_inWorld, viewDirection));

#ifdef RN_USE_ANISOTROPY
float anisotropy = get_anisotropyStrength(materialSID, 0);
vec2 anisotropyRotation = get_anisotropyRotation(materialSID, 0);
vec2 direction = anisotropyRotation;
vec3 anisotropyTex = texture(u_anisotropyTexture, baseColorTexUv).rgb;
direction = anisotropyTex.rg * 2.0 - vec2(1.0);
direction = mat2(anisotropyRotation.x, anisotropyRotation.y, -anisotropyRotation.y, anisotropyRotation.x) * normalize(direction);
anisotropy *= anisotropyTex.b;
vec3 anisotropicT = normalize(TBN * vec3(direction, 0.0));
vec3 anisotropicB = normalize(cross(geomNormal_inWorld, anisotropicT));
float BdotV = dot(anisotropicB, viewDirection);
float TdotV = dot(anisotropicT, viewDirection);
#else
float anisotropy = 0.0;
vec3 anisotropicB = vec3(0.0, 0.0, 0.0);
#endif

// Clearcoat
#ifdef RN_USE_CLEARCOAT
float clearcoatFactor = get_clearCoatFactor(materialSID, 0);
Expand Down Expand Up @@ -656,7 +689,7 @@ void main ()
float clearcoatNormalTextureRotation = get_clearCoatNormalTextureRotation(materialSID, 0);
vec2 clearcoatNormalTexUv = uvTransform(clearcoatNormalTextureTransform.xy, clearcoatNormalTextureTransform.zw, clearcoatNormalTextureRotation, clearCoatNormalTexcoord);
vec3 textureNormal_tangent = texture(u_clearCoatNormalTexture, clearcoatNormalTexUv).xyz * vec3(2.0) - vec3(1.0);
vec3 clearcoatNormal_inWorld = perturb_normal(geomNormal_inWorld, viewVector, normalTexUv, textureNormal_tangent);
vec3 clearcoatNormal_inWorld = normalize(TBN * textureNormal_tangent);
float VdotNc = saturateEpsilonToOne(dot(viewDirection, clearcoatNormal_inWorld));
#else
float clearcoatRoughness = 0.0;
Expand Down Expand Up @@ -739,8 +772,15 @@ void main ()

// Specular
float NdotH = saturateEpsilonToOne(dot(normal_inWorld, halfVector));
#ifdef RN_USE_ANISOTROPY
float TdotL = dot(anisotropicT, light.direction);
float BdotL = dot(anisotropicB, light.direction);
float TdotH = dot(anisotropicT, halfVector);
float BdotH = dot(anisotropicB, halfVector);
vec3 specularContrib = BRDF_specularAnisotropicGGX(F, alphaRoughness, VdotH, NdotL, NdotV, NdotH, BdotV, TdotV, TdotL, BdotL, TdotH, BdotH, anisotropy) * vec3(NdotL) * light.attenuatedIntensity;
#else
vec3 specularContrib = cook_torrance_specular_brdf(NdotH, NdotL, NdotV, F, alphaRoughness) * vec3(NdotL) * light.attenuatedIntensity;

#endif // RN_USE_ANISOTROPY
// Base Layer
vec3 baseLayer = diffuseContrib + specularContrib;

Expand Down Expand Up @@ -782,7 +822,7 @@ void main ()
vec3 ibl = IBLContribution(materialSID, normal_inWorld, NdotV, viewDirection,
albedo, F0, perceptualRoughness, clearcoatRoughness, clearcoatNormal_inWorld,
clearcoat, VdotNc, geomNormal_inWorld, cameraSID, transmission, v_position_inWorld.xyz, thickness,
sheenColor, sheenRoughness, albedoSheenScalingNdotV, ior, iridescenceFresnel, iridescenceF0, iridescence);
sheenColor, sheenRoughness, albedoSheenScalingNdotV, ior, iridescenceFresnel, iridescenceF0, iridescence, anisotropy, anisotropicB);

int occlusionTexcoordIndex = get_occlusionTexcoordIndex(materialSID, 0);
vec2 occlusionTexcoord = getTexcoord(occlusionTexcoordIndex);
Expand Down
Loading

0 comments on commit 96d396a

Please sign in to comment.