rj-action-library/Runtime/Reallusion/CCImportFile/CCMaterialInfo.cs

556 lines
19 KiB
C#
Raw Normal View History

using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System;
using Godot;
namespace Rokojori.Reallusion
{
public class CCMaterialInfo:CCImportFileBase
{
public string name;
public CCJSONProperty<string> materialType = new CCJSONProperty<string>( "Material Type" );
public CCJSONProperty<int> multiUVIndex = new CCJSONProperty<int>( "MultiUV Index" );
public CCJSONProperty<string> nodeType = new CCJSONProperty<string>( "Node Type" );
public CCJSONProperty<bool> twoSide = new CCJSONProperty<bool>( "Two Side" );
public CCJSONProperty<List<float>> diffuseColor = new CCJSONProperty<List<float>>( "Diffuse Color" );
public CCJSONProperty<List<float>> ambientColor = new CCJSONProperty<List<float>>( "Ambient Color" );
public CCJSONProperty<List<float>> specularColor = new CCJSONProperty<List<float>>( "Specular Color" );
public CCJSONProperty<float> opacity = new CCJSONProperty<float>( "Opacity" );
public CCJSONProperty<float> selfIllumination = new CCJSONProperty<float>( "Self Illumination" );
public CCJSONProperty<float> specular = new CCJSONProperty<float>( "Specular" );
public CCJSONProperty<float> glossiness = new CCJSONProperty<float>( "Glossiness" );
public CCJSONProperty<List<CCTextureInfo>> textures = new CCJSONProperty<List<CCTextureInfo>>( "Textures" );
public CCJSONProperty<CCCustomShader> customShader = new CCJSONProperty<CCCustomShader>( "Custom Shader" );
public CCJSONProperty<CCSubsurfaceScatter> subsurfaceScatter = new CCJSONProperty<CCSubsurfaceScatter>( "Subsurface Scatter" );
public CCMaterialInfo( CCImportFile ccImportFile, string name ):base( ccImportFile )
{
this.name = name;
textures.SetReader(
( data ) =>
{
var list = new List<CCTextureInfo>();
var obj = data.AsObject();
Info( "Reading textures:", obj.keys );
obj.keys.ForEach(
k =>
{
var ti = CCTextureInfo.Create( importFile, k, obj.Get( k ) );
Info( "Adding texture for material", name, ti.name, ti.texturePath.value );
list.Add( ti );
}
);
return list;
}
);
customShader.SetReader(
( data ) =>
{
var shaderName = data.AsObject().Get( "Shader Name" ).stringValue;
var cs = new CCCustomShader( importFile, shaderName );
Info( "Found Shader", shaderName );
cs.ReadFrom( data.AsObject() );
return cs;
}
);
subsurfaceScatter.SetReader(
( data ) =>
{
var ss = new CCSubsurfaceScatter( importFile );
ss.ReadFrom( data.AsObject() );
return ss;
}
);
}
public void ReadFrom( JSONObject root )
{
materialType.Read( root );
multiUVIndex.Read( root );
nodeType.Read( root );
twoSide.Read( root );
diffuseColor.Read( root );
ambientColor.Read( root );
specularColor.Read( root );
opacity.Read( root );
selfIllumination.Read( root );
textures.Read( root );
customShader.Read( root );
subsurfaceScatter.Read( root );
}
public bool IsCustomShader( string shaderName )
{
return customShader.exists && customShader.value.name == shaderName;
}
public Material CreateMaterial( CCMaterialSettings settings )
{
RJLog.Log( "Custom Shader", customShader.exists ? customShader.value.name : "none" );
if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLHair )
{
return CreateHairMaterial( settings );
}
if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLEyeOcclusion )
{
return CreateEyeOcclusionMaterial( settings );
}
if ( settings.materialType.shaderType == CCMaterialType.CCShaderType.RLEye )
{
return CreateEyeMaterial( settings );
}
if (
settings.materialType.shaderType == CCMaterialType.CCShaderType.RLSkin ||
settings.materialType.shaderType == CCMaterialType.CCShaderType.RLHead
)
{
return CreateSkinMaterial( settings );
}
if ( HasOpacityTexture() )
{
return CreateOpacityMaterial( settings );
}
return CreatePBRMaterial( settings );
}
public Color GetAlbedoColor( float gamma )
{
var a = opacity.GetOr( 1.0f );
var color = ColorX.From( diffuseColor.GetOr( new List<float>{ 255, 255, 255, 255 } ), 255 );
color.A *= a;
color = color.Gamma( gamma );
return color;
}
public bool HasOpacityTexture()
{
if ( textures.exists )
{
var opacityTexture = textures.value.Find( t => t.name == CCTextureInfo.Opacity );
return opacityTexture != null;
}
return false;
}
public bool IsTransparent()
{
return HasOpacityTexture() || GetAlbedoColor( 1.0f ).A < 1.0f;
}
public CCMaterialType GetMaterialType()
{
var materialType = new CCMaterialType();
materialType.shaderType = CCMaterialType.CCShaderType.PBR;
if ( customShader.exists )
{
materialType.shaderType = ReflectionHelper.StringToEnum( customShader.value.name, CCMaterialType.CCShaderType.Unknown );
}
return materialType;
}
public StandardMaterial3D CreatePBRMaterial( CCMaterialSettings settings, bool skin = false )
{
var material = new StandardMaterial3D();
material.CullMode = twoSide.GetOr( false ) ? BaseMaterial3D.CullModeEnum.Disabled : BaseMaterial3D.CullModeEnum.Back;
material.Metallic = 1.0f;
material.AlbedoColor = GetAlbedoColor( settings.configuration.gammaForAlbedoColor );
material.Transparency = IsTransparent() ? BaseMaterial3D.TransparencyEnum.Alpha : BaseMaterial3D.TransparencyEnum.Disabled;
material.MetallicSpecular = skin ? 0.0f : 0.5f;
if ( skin && subsurfaceScatter.exists)
{
material.SubsurfScatterEnabled = true;
material.SubsurfScatterStrength = subsurfaceScatter.value.radius.value / 3.0f;
material.SubsurfScatterSkinMode = true;
}
if ( ! textures.exists )
{
return material;
}
textures.value.ForEach(
( t ) =>
{
if ( t.isBaseColor )
{
material.AlbedoTexture = t.GetTexture();
var uv1Scale = t.tiling.GetOr( new List<float>(){ 1, 1 } );
var uv1Offset = t.offset.GetOr( new List<float>(){ 0, 0 } );
material.Uv1Scale = new Vector3( uv1Scale[ 0 ], uv1Scale[ 1 ], 1 );
material.Uv1Offset = new Vector3( uv1Offset[ 0 ], uv1Offset[ 1 ], 1 );
}
else if ( t.isNormal )
{
material.NormalTexture = t.GetTexture();
material.NormalEnabled = true;
}
else if ( t.isRoughness )
{
material.RoughnessTexture = t.GetTexture();
material.RoughnessTextureChannel = BaseMaterial3D.TextureChannel.Red;
}
else if ( t.isMetallic )
{
material.MetallicTexture = t.GetTexture();
material.MetallicTextureChannel = BaseMaterial3D.TextureChannel.Red;
}
else if ( t.isGlow )
{
material.EmissionEnabled = true;
material.EmissionTexture = t.GetTexture();
}
else if ( t.isAO )
{
material.AOEnabled = true;
material.AOTexture = t.GetTexture();
material.AOTextureChannel = BaseMaterial3D.TextureChannel.Red;
}
}
);
return material;
}
public ShaderMaterial CreateEyeOcclusionMaterial( CCMaterialSettings settings )
{
var eyeOcclusionMaterial = new CCEyeOcclusionMaterial();
eyeOcclusionMaterial.shadowTopColor.Set(
ColorX.From( customShader.value.shadowTopColor.value, 255.0f )
);
eyeOcclusionMaterial.shadowBottomColor.Set(
ColorX.From( customShader.value.shadowBottomColor.value, 255.0f )
);
return eyeOcclusionMaterial;
}
public ShaderMaterial CreateEyeMaterial( CCMaterialSettings settings )
{
var eyeMaterial = new CCEyeMaterial();
textures.value.ForEach(
( t ) =>
{
if ( t.isBaseColor )
{
eyeMaterial.textureAlbedo.Set( t.GetTexture() );
}
}
);
eyeMaterial.textureNormal.Set( customShader.value.GetIrisNormal() );
return eyeMaterial;
}
public ShaderMaterial CreateSkinMaterial( CCMaterialSettings settings )
{
var skinMaterial = new CCSkinMaterial();
CustomMaterial outputMaterial = skinMaterial;
if ( settings.configuration.transmissiveSkin )
{
outputMaterial = new CCSkinTransmissiveMaterial();
}
if ( settings.configuration.applyAlbedoNoise )
{
var skinScale = 2.0f;
if ( name.EndsWith( "Head" ) )
{
skinScale = 1.0f;
}
else if ( name.EndsWith( "Body" ) )
{
skinScale = 5.0f;
}
skinMaterial.albedoNoiseUvScale.AssignFor( outputMaterial, skinScale );
skinMaterial.albedoNoiseOffset.AssignFor( outputMaterial, settings.configuration.albedoNoiseBrightness );
skinMaterial.albedoNoise.AssignFor( outputMaterial, settings.configuration.albedoNoiseAmount );
skinMaterial.textureAlbedoNoise.AssignFor( outputMaterial, settings.configuration.skinAlbedoNoise );
}
skinMaterial.albedo.AssignFor( outputMaterial, GetAlbedoColor( settings.configuration.gammaForAlbedoColor ) );
skinMaterial.specular.AssignFor( outputMaterial, 0.5f );
var tiling = customShader.value.GetFloatVariable( "MicroNormal Tiling", 20f );
skinMaterial.uv1Scale.AssignFor( outputMaterial, Vector3.One );
skinMaterial.uv2Scale.AssignFor( outputMaterial, Vector3.One * tiling );
skinMaterial.microNormalTexture.AssignFor( outputMaterial, customShader.value.GetMicroNormal() );
skinMaterial.microNormalMaskTexture.AssignFor( outputMaterial, customShader.value.GetMicroNormalMask() );
skinMaterial.microNormalScale.AssignFor( outputMaterial, customShader.value.GetFloatVariable( "MicroNormal Strength", 0.5f ) );
if ( outputMaterial is CCSkinTransmissiveMaterial st )
{
st.textureSubsurfaceTransmittance.Set( customShader.value.GetTransmisionMap() );
}
// skinMaterial.textureSubsurfaceTransmittance.Set( customShader.value.GetTransmisionMap() );
skinMaterial.textureSpecular.AssignFor( outputMaterial, customShader.value.GetSpecularMask() );
skinMaterial.textureSubsurfaceScattering.AssignFor( outputMaterial, customShader.value.GetSSSMap() );
textures.value.ForEach(
( t ) =>
{
if ( t.isBaseColor )
{
skinMaterial.textureAlbedo.AssignFor( outputMaterial, t.GetTexture() );
var uv1Scale = t.tiling.GetOr( new List<float>(){ 1, 1 } );
var uv1Offset = t.offset.GetOr( new List<float>(){ 0, 0 } );
skinMaterial.uv1Scale.AssignFor( outputMaterial, new Vector3( uv1Scale[ 0 ], uv1Scale[ 1 ], 1 ) );
skinMaterial.uv1Offset.AssignFor( outputMaterial, new Vector3( uv1Offset[ 0 ], uv1Offset[ 1 ], 1 ) );
}
else if ( t.isNormal )
{
skinMaterial.textureNormal.AssignFor( outputMaterial, t.GetTexture() );
}
else if ( t.isRoughness )
{
skinMaterial.textureRoughness.AssignFor( outputMaterial, t.GetTexture() );
}
else if ( t.isAO )
{
skinMaterial.textureAmbientOcclusion.AssignFor( outputMaterial, t.GetTexture() );
}
}
);
return outputMaterial;
}
public ShaderMaterial CreateOpacityMaterial( CCMaterialSettings settings )
{
var opacityMaterial = new CCPBROpacityMaterial();
opacityMaterial.albedo.Set( GetAlbedoColor( settings.configuration.gammaForAlbedoColor ) );
opacityMaterial.specular.Set( 0.0f );
opacityMaterial.opacity.Set( opacity.GetOr( 1 ) );
opacityMaterial.uv1Scale.Set( Vector3.One );
opacityMaterial.uv2Scale.Set( Vector3.One );
textures.value.ForEach(
( t ) =>
{
if ( t.isBaseColor )
{
opacityMaterial.textureAlbedo.Set( t.GetTexture() );
var uv1Scale = t.tiling.GetOr( new List<float>(){ 1, 1 } );
var uv1Offset = t.offset.GetOr( new List<float>(){ 0, 0 } );
opacityMaterial.uv1Scale.Set( new Vector3( uv1Scale[ 0 ], uv1Scale[ 1 ], 1 ) );
opacityMaterial.uv1Offset.Set( new Vector3( uv1Offset[ 0 ], uv1Offset[ 1 ], 1 ) );
}
if ( t.isOpacity )
{
opacityMaterial.textureOpacity.Set( t.GetTexture() );
}
else if ( t.isNormal )
{
opacityMaterial.textureNormal.Set( t.GetTexture() );
}
else if ( t.isRoughness )
{
opacityMaterial.textureRoughness.Set( t.GetTexture() );
}
else if ( t.isMetallic )
{
opacityMaterial.textureMetallic.Set( t.GetTexture() );
opacityMaterial.metallicTextureChannel.Set( new Vector4( 1, 0, 0, 0 ) );
}
else if ( t.isAO )
{
opacityMaterial.textureAmbientOcclusion.Set( t.GetTexture() );
opacityMaterial.aoTextureChannel.Set( new Vector4( 1, 0, 0, 0 ) );
}
}
);
return opacityMaterial;
}
public ShaderMaterial CreateHairMaterial( CCMaterialSettings settings )
{
var scissorMaterial = new CCHairScissorMaterial();
var alphaMaterial = new CCHairAlphaMaterial();
var alphaBackMaterial = new CCHairAlphaBackMaterial();
scissorMaterial.NextPass = alphaBackMaterial;
alphaBackMaterial.NextPass = alphaMaterial;
alphaBackMaterial.RenderPriority = settings.materialRenderPriorityIndexBack;
alphaMaterial.RenderPriority = settings.materialRenderPriorityIndexFront;
var m = new List<CustomMaterial>(){ scissorMaterial, alphaMaterial, alphaBackMaterial };
var mat = scissorMaterial;
CustomMaterial outputMaterial = scissorMaterial;
var opacityScale = 1.0f;
if ( CCImportConfiguration.HairShaderMode.Alpha_Only == settings.configuration.hairShaderMode )
{
var hairMaterial = new CCHairMaterial();
hairMaterial.RenderPriority = settings.materialRenderPriorityIndexBack;
outputMaterial = hairMaterial;
m = new List<CustomMaterial>(){ hairMaterial };
opacityScale = 1.5f;
}
else if ( CCImportConfiguration.HairShaderMode.Shadow_Scissor_AlphaBack_AlphaFront == settings.configuration.hairShaderMode )
{
scissorMaterial.NextPass = null;
var shadowMaterial = new CCHairShadowMaterial();
shadowMaterial.RenderPriority = -2;
var hairMaterial = new CCHairScissorMaterial();
outputMaterial = shadowMaterial;
shadowMaterial.NextPass = hairMaterial;
hairMaterial.NextPass = alphaBackMaterial;
m = new List<CustomMaterial>(){ shadowMaterial, hairMaterial, alphaMaterial, alphaBackMaterial };
opacityScale = 1f;
}
mat.naturalColors.AssignFor( m, settings.configuration.naturalColors );
mat.maximumHighlightAmount.AssignFor( m, settings.configuration.maximumHighlightAmount );
mat.opacityGamma.AssignFor( m, settings.configuration.GetHairOpacityGamma( settings.meshName, settings.materialIndex ) );
mat.flowMap.AssignFor( m, customShader.value.GetHairFlowMap() );
mat.rootMap.AssignFor( m, customShader.value.GetHairRootMap() );
mat.idMap.AssignFor( m, customShader.value.GetHairIDMap() );
2025-06-12 09:03:02 +00:00
mat.anisotropyRatio.AssignFor( m, settings.configuration.anisotropicRatio );
mat.vertexGreyToColor.AssignFor( m, customShader.value.GetColorVariable( "VertexGrayToColor", 255f, false ) );
mat.vertexColorStrength.AssignFor( m, customShader.value.GetFloatVariable( "VertexColorStrength" ) );
mat.diffuseStrength.AssignFor( m, customShader.value.GetFloatVariable( "Diffuse Strength" ) );
mat.baseColorMapStrength.AssignFor( m, customShader.value.GetFloatVariable( "BaseColorMapStrength" ) );
mat.strandRootColor.AssignFor( m, customShader.value.GetColorVariable( "RootColor", 255f, false ) );
mat.strandRootStrength.AssignFor( m, customShader.value.GetFloatVariable( "RootColorStrength" ) );
mat.strandEndColor.AssignFor( m, customShader.value.GetColorVariable( "TipColor", 255f, false ) );
mat.strandEndStrength.AssignFor( m, customShader.value.GetFloatVariable( "TipColorStrength" ) );
mat.highlightAColor.AssignFor( m, customShader.value.GetColorVariable( "_1st Dye Color", 255, false ) );
mat.highlightAStrength.AssignFor( m, customShader.value.GetFloatVariable( "_1st Dye Strength" ) );
mat.highlightARange.AssignFor( m,
customShader.value.GetColorVariable( "_1st Dye Distribution from Grayscale", 255, false ).ToVector3()
);
mat.highlightAOverlapEnd.AssignFor( m, customShader.value.GetFloatVariable( "Mask 1st Dye by RootMap" ) );
mat.highlightAInvert.AssignFor( m, customShader.value.GetFloatVariable( "Invert 1st Dye RootMap Mask" ) );
mat.highlightBColor.AssignFor( m, customShader.value.GetColorVariable( "_2nd Dye Color", 255, false ) );
mat.highlightBStrength.AssignFor( m, customShader.value.GetFloatVariable( "_2nd Dye Strength" ) );
mat.highlightBRange.AssignFor( m,
customShader.value.GetColorVariable( "_2nd Dye Distribution from Grayscale", 255, false ).ToVector3()
);
mat.highlightBOverlapEnd.AssignFor( m, customShader.value.GetFloatVariable( "Mask 2nd Dye by RootMap" ) );
mat.highlightBInvert.AssignFor( m, customShader.value.GetFloatVariable( "Invert 2nd Dye RootMap Mask" ) );
mat.albedo.AssignFor( m, GetAlbedoColor( settings.configuration.gammaForAlbedoColor ) );
// mat.specular.AssignFor( m, 0.5f );
mat.opacity.AssignFor( m, opacity.GetOr( 1 ) * opacityScale );
mat.blendAmount.AssignFor( m, 0f );
2025-06-27 05:12:53 +00:00
mat.roughnessOffset.AssignFor( m, settings.configuration.roughnessOffset );
mat.metallicOffset.AssignFor( m, settings.configuration.metallicOffset );
textures.value.ForEach(
( t ) =>
{
if ( t.isBaseColor )
{
mat.textureAlbedo.AssignFor( m, t.GetTexture() );
}
if ( t.isOpacity )
{
mat.textureOpacity.AssignFor( m, t.GetTexture() );
}
else if ( t.isRoughness )
{
mat.textureRoughness.AssignFor( m, t.GetTexture() );
}
else if ( t.isMetallic )
{
mat.textureMetallic.AssignFor( m, t.GetTexture() );
}
else if ( t.isAO )
{
mat.textureAmbientOcclusion.AssignFor( m, t.GetTexture() );
}
else if ( t.isBlend )
{
mat.textureBlend.AssignFor( m, t.GetTexture() );
mat.blendAmount.AssignFor( m, t.strength.GetOr( 0f ) / 100f ) ;
}
}
);
return outputMaterial;
}
}
}