| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using GLTFMATERIAL = SharpGLTF.Schema2.Material;
- namespace SharpGLTF.Runtime
- {
- class BasicEffectsLoaderContext : LoaderContext
- {
- #region lifecycle
- public BasicEffectsLoaderContext(GraphicsDevice device) : base(device) { }
- #endregion
- #region effects creation
- // Monogame's BasicEffect uses Phong's shading, while glTF uses PBR shading, so
- // given monogame's limitations, we try to guess the most appropiate values
- // to have a reasonably good looking renders.
- protected override Effect CreateEffect(GLTFMATERIAL srcMaterial, bool isSkinned)
- {
- return isSkinned ? CreateSkinnedEffect(srcMaterial) : CreateRigidEffect(srcMaterial);
- }
- protected virtual Effect CreateRigidEffect(GLTFMATERIAL srcMaterial)
- {
- var dstMaterial = srcMaterial.Alpha == Schema2.AlphaMode.MASK
- ? CreateAlphaTestEffect(srcMaterial)
- : CreateBasicEffect(srcMaterial);
- return dstMaterial;
- }
- protected virtual Effect CreateBasicEffect(GLTFMATERIAL srcMaterial)
- {
- var dstMaterial = new BasicEffect(Device);
- dstMaterial.Name = srcMaterial.Name;
- dstMaterial.Alpha = GetAlphaLevel(srcMaterial);
- dstMaterial.DiffuseColor = GetDiffuseColor(srcMaterial);
- dstMaterial.SpecularColor = GetSpecularColor(srcMaterial);
- dstMaterial.SpecularPower = GetSpecularPower(srcMaterial);
- dstMaterial.EmissiveColor = GeEmissiveColor(srcMaterial);
- dstMaterial.Texture = UseDiffuseTexture(srcMaterial);
- if (srcMaterial.Unlit)
- {
- dstMaterial.EmissiveColor = dstMaterial.DiffuseColor;
- dstMaterial.SpecularColor = Vector3.Zero;
- dstMaterial.SpecularPower = 16;
- }
- dstMaterial.PreferPerPixelLighting = true;
- dstMaterial.TextureEnabled = dstMaterial.Texture != null;
- return dstMaterial;
- }
- protected virtual Effect CreateAlphaTestEffect(GLTFMATERIAL srcMaterial)
- {
- var dstMaterial = new AlphaTestEffect(Device);
- dstMaterial.Name = srcMaterial.Name;
- dstMaterial.Alpha = GetAlphaLevel(srcMaterial);
- //dstMaterial.AlphaFunction = CompareFunction.GreaterEqual;
- dstMaterial.ReferenceAlpha = (int)(srcMaterial.AlphaCutoff * 255);
- dstMaterial.DiffuseColor = GetDiffuseColor(srcMaterial);
- dstMaterial.Texture = UseDiffuseTexture(srcMaterial);
- return dstMaterial;
- }
- protected virtual Effect CreateSkinnedEffect(GLTFMATERIAL srcMaterial)
- {
- var dstMaterial = new SkinnedEffect(Device);
- dstMaterial.Name = srcMaterial.Name;
- dstMaterial.Alpha = GetAlphaLevel(srcMaterial);
- dstMaterial.DiffuseColor = GetDiffuseColor(srcMaterial);
- dstMaterial.SpecularColor = GetSpecularColor(srcMaterial);
- dstMaterial.SpecularPower = GetSpecularPower(srcMaterial);
- dstMaterial.EmissiveColor = GeEmissiveColor(srcMaterial);
- dstMaterial.Texture = UseDiffuseTexture(srcMaterial);
- dstMaterial.WeightsPerVertex = 4;
- dstMaterial.PreferPerPixelLighting = true;
- // apparently, SkinnedEffect does not support disabling textures, so we set a white texture here.
- if (dstMaterial.Texture == null) dstMaterial.Texture = UseTexture(null, null); // creates a dummy white texture.
- return dstMaterial;
- }
- #endregion
- #region meshes creation
- protected override void WriteMeshPrimitive(MeshPrimitiveReader srcPrimitive, Effect effect)
- {
- if (srcPrimitive.IsSkinned) WriteMeshPrimitive<VertexSkinned>(effect, srcPrimitive);
- else WriteMeshPrimitive<VertexPositionNormalTexture>(effect, srcPrimitive);
- }
- #endregion
- #region gltf helpers
- private static float GetAlphaLevel(GLTFMATERIAL srcMaterial)
- {
- if (srcMaterial.Alpha == Schema2.AlphaMode.OPAQUE) return 1;
- var baseColor = srcMaterial.FindChannel("BaseColor");
- if (baseColor == null) return 1;
- return baseColor.Value.Color.W;
- }
- private static Vector3 GetDiffuseColor(GLTFMATERIAL srcMaterial)
- {
- var diffuse = srcMaterial.FindChannel("Diffuse");
- if (diffuse == null) diffuse = srcMaterial.FindChannel("BaseColor");
- if (diffuse == null) return Vector3.One;
-
- return new Vector3(diffuse.Value.Color.X, diffuse.Value.Color.Y, diffuse.Value.Color.Z);
- }
- private static Vector3 GetSpecularColor(GLTFMATERIAL srcMaterial)
- {
- var mr = srcMaterial.FindChannel("MetallicRoughness");
- if (mr == null) return Vector3.One; // default value 16
- var diffuse = GetDiffuseColor(srcMaterial);
- var metallic = mr.Value.GetFactor("MetallicFactor");
- var roughness = mr.Value.GetFactor("RoughnessFactor");
- var k = Vector3.Zero;
- k += Vector3.Lerp(diffuse, Vector3.Zero, roughness);
- k += Vector3.Lerp(diffuse, Vector3.One, metallic);
- k *= 0.5f;
- return k;
- }
- private static float GetSpecularPower(GLTFMATERIAL srcMaterial)
- {
- var mr = srcMaterial.FindChannel("MetallicRoughness");
- if (mr == null) return 16; // default value = 16
- var metallic = mr.Value.GetFactor("MetallicFactor");
- var roughness = mr.Value.GetFactor("RoughnessFactor");
- return 4 + 16 * metallic;
- }
- private static Vector3 GeEmissiveColor(GLTFMATERIAL srcMaterial)
- {
- var emissive = srcMaterial.FindChannel("Emissive");
- if (emissive == null) return Vector3.Zero;
- return new Vector3(emissive.Value.Color.X, emissive.Value.Color.Y, emissive.Value.Color.Z);
- }
- private Texture2D UseDiffuseTexture(GLTFMATERIAL srcMaterial)
- {
- var diffuse = srcMaterial.FindChannel("Diffuse");
- if (diffuse == null) diffuse = srcMaterial.FindChannel("BaseColor");
- if (diffuse == null) return null;
- return UseTexture(diffuse, null);
- }
- #endregion
- }
- }
|