Implements standard texture importing with shader

This commit is contained in:
Masataka SUMI
2021-05-27 22:27:51 +09:00
parent 06715ab77b
commit 9aee0b1ea3
4 changed files with 135 additions and 66 deletions

View File

@@ -0,0 +1,68 @@
Shader "Hidden/UniGLTF/StandardMapImporter"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_GltfMetallicFactor ("glTF Metallic Factor", Float) = 0.0
_GltfRoughnessFactor ("glTF Roughness Factor", Float) = 0.0
_GltfMetallicRoughnessTexture ("glTF Metallic Roughness Texture", 2D) = "black" {}
_GltfOcclusionTexture ("glTF Occlusion Texture", 2D) = "black" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
half _GltfMetallicFactor;
half _GltfRoughnessFactor;
sampler2D _GltfMetallicRoughnessTexture;
sampler2D _GltfOcclusionTexture;
fixed4 frag (v2f i) : SV_Target
{
half4 metallicRoughness = tex2D(_GltfMetallicRoughnessTexture, i.uv);
half metallic = metallicRoughness.b * _GltfMetallicFactor;
half roughness = metallicRoughness.g * _GltfRoughnessFactor;
half occlusion = tex2D(_GltfOcclusionTexture, i.uv).r;
fixed4 result;
result.r = metallic; // R: Unity Metallic
result.g = occlusion; // G: Unity Occlusion
result.b = 0; // B: Unity Heightmap (no use)
result.a = 1.0 - roughness; // A: Unity Smoothness
return result;
}
ENDCG
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: fa5d94522a5d93442a7515698d7ab799
timeCreated: 1533558728
licenseType: Free
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -21,77 +21,42 @@ namespace VRMShaders
/// </summary>
public static class OcclusionMetallicRoughnessConverter
{
public static Texture2D Import(Texture2D metallicRoughnessTexture,
float metallicFactor, float roughnessFactor, Texture2D occlusionTexture)
private static Material exporter;
private static Material Exporter
{
// TODO: Replace with Shader implementation
if (metallicRoughnessTexture != null && occlusionTexture != null)
get
{
if (metallicRoughnessTexture == occlusionTexture)
if (exporter == null)
{
var copyMetallicRoughness = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, true, null);
var metallicRoughnessPixels = copyMetallicRoughness.GetPixels32();
for (int i = 0; i < metallicRoughnessPixels.Length; ++i)
{
metallicRoughnessPixels[i] = ImportPixel(metallicRoughnessPixels[i], metallicFactor, roughnessFactor, metallicRoughnessPixels[i]);
}
copyMetallicRoughness.SetPixels32(metallicRoughnessPixels);
copyMetallicRoughness.Apply();
copyMetallicRoughness.name = metallicRoughnessTexture.name;
return copyMetallicRoughness;
exporter = new Material(Shader.Find("Hidden/UniGLTF/StandardMapImporter"));
}
else
{
var copyMetallicRoughness = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, true, null);
var metallicRoughnessPixels = copyMetallicRoughness.GetPixels32();
var copyOcclusion = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, false, null);
var occlusionPixels = copyOcclusion.GetPixels32();
if (metallicRoughnessPixels.Length != occlusionPixels.Length)
{
throw new NotImplementedException();
}
for (int i = 0; i < metallicRoughnessPixels.Length; ++i)
{
metallicRoughnessPixels[i] = ImportPixel(metallicRoughnessPixels[i], metallicFactor, roughnessFactor, occlusionPixels[i]);
}
copyMetallicRoughness.SetPixels32(metallicRoughnessPixels);
copyMetallicRoughness.Apply();
copyMetallicRoughness.name = metallicRoughnessTexture.name;
DestroyTexture(copyOcclusion);
return copyMetallicRoughness;
}
}
else if (metallicRoughnessTexture != null)
{
var copyTexture = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, true, null);
copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ImportPixel(x, metallicFactor, roughnessFactor, default)).ToArray());
copyTexture.Apply();
copyTexture.name = metallicRoughnessTexture.name;
return copyTexture;
}
else if (occlusionTexture != null)
{
var copyTexture = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, true, null);
copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ImportPixel(default, metallicFactor, roughnessFactor, x)).ToArray());
copyTexture.Apply();
copyTexture.name = occlusionTexture.name;
return copyTexture;
}
else
{
throw new ArgumentNullException("no texture");
return exporter;
}
}
public static Color32 ImportPixel(Color32 metallicRoughness, float metallicFactor, float roughnessFactor, Color32 occlusion)
public static Texture2D Import(Texture2D metallicRoughnessTexture,
float metallicFactor, float roughnessFactor, Texture2D occlusionTexture)
{
var dst = new Color32
if (metallicRoughnessTexture == null && occlusionTexture == null)
{
r = (byte)(metallicRoughness.b * metallicFactor), // Metallic
g = occlusion.r, // Occlusion
b = 0, // not used
a = (byte)(255 - metallicRoughness.g * roughnessFactor), // Roughness to Smoothness
};
throw new ArgumentNullException("no texture");
}
var src = metallicRoughnessTexture != null ? metallicRoughnessTexture : occlusionTexture;
Exporter.mainTexture = src;
Exporter.SetTexture("_GltfMetallicRoughnessTexture", metallicRoughnessTexture);
Exporter.SetTexture("_GltfOcclusionTexture", occlusionTexture);
Exporter.SetFloat("_GltfMetallicFactor", metallicFactor);
Exporter.SetFloat("_GltfRoughnessFactor", roughnessFactor);
var dst = TextureConverter.CopyTexture(src, ColorSpace.Linear, true, Exporter);
Exporter.mainTexture = null;
Exporter.SetTexture("_GltfMetallicRoughnessTexture", null);
Exporter.SetTexture("_GltfOcclusionTexture", null);
Exporter.SetFloat("_GltfMetallicFactor", 0);
Exporter.SetFloat("_GltfRoughnessFactor", 0);
return dst;
}

View File

@@ -1,3 +1,4 @@
using System.Linq;
using NUnit.Framework;
using UnityEngine;
@@ -5,6 +6,32 @@ namespace VRMShaders
{
public class MetallicRoughnessConverterTests
{
private Color32 ImportPixel(Color32 metallicRoughnessPixel, float metallicFactor, float roughnessFactor, Color32 occlusionPixel)
{
var metallicRoughnessTexture = new Texture2D(4, 4, TextureFormat.ARGB32, mipChain: false, linear: true);
metallicRoughnessTexture.SetPixels32(Enumerable.Range(0, 16).Select(_ => metallicRoughnessPixel).ToArray());
metallicRoughnessTexture.Apply();
var occlusionTexture = new Texture2D(4, 4, TextureFormat.ARGB32, mipChain: false, linear: true);
occlusionTexture.SetPixels32(Enumerable.Range(0, 16).Select(_ => occlusionPixel).ToArray());
occlusionTexture.Apply();
var converted = OcclusionMetallicRoughnessConverter.Import(
metallicRoughnessTexture,
metallicFactor,
roughnessFactor,
occlusionTexture
);
var result = converted.GetPixels32()[0];
UnityEngine.Object.DestroyImmediate(metallicRoughnessTexture);
UnityEngine.Object.DestroyImmediate(occlusionTexture);
UnityEngine.Object.DestroyImmediate(converted);
return result;
}
[Test]
public void ExportingColorTest()
{
@@ -48,7 +75,7 @@ namespace VRMShaders
{
var roughnessFactor = 1.0f;
Assert.That(
OcclusionMetallicRoughnessConverter.ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
// r <- 255 : Same metallic (src.r)
// g <- 0 : (Unused)
// b <- 0 : (Unused)
@@ -59,7 +86,7 @@ namespace VRMShaders
{
var roughnessFactor = 1.0f;
Assert.That(
OcclusionMetallicRoughnessConverter.ImportPixel(new Color32(255, 128, 255, 255), 1.0f, roughnessFactor, default),
ImportPixel(new Color32(255, 128, 255, 255), 1.0f, roughnessFactor, default),
// r <- 255 : Same metallic (src.r)
// g <- 0 : (Unused)
// b <- 0 : (Unused)
@@ -70,7 +97,7 @@ namespace VRMShaders
{
var roughnessFactor = 0.5f;
Assert.That(
OcclusionMetallicRoughnessConverter.ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
// r <- 255 : Same metallic (src.r)
// g <- 0 : (Unused)
// b <- 0 : (Unused)
@@ -81,7 +108,7 @@ namespace VRMShaders
{
var roughnessFactor = 0.0f;
Assert.That(
OcclusionMetallicRoughnessConverter.ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
// r <- 255 : Same metallic (src.r)
// g <- 0 : (Unused)
// b <- 0 : (Unused)