MaterialConstant ExtractMaterialData(Renderer _renderer, Material _mat) { MaterialConstant data = new MaterialConstant(); data._Color = _mat.color.linear; data._CustomSpecColor = _mat.GetColor("_CustomSpecColor").linear; data._MainTex_ST = new Vector4(_mat.mainTextureScale.x, _mat.mainTextureScale.y, _mat.mainTextureOffset.x, _mat.mainTextureOffset.y); data._EmissionColor = _mat.GetColor("_EmissionColor").linear; // emission need to use linear, since it is HDR data._AlphaTestOn = (_mat.renderQueue == (int)RenderQueue.AlphaTest) ? 1f : 0f; data._Cutoff = _mat.GetFloat("_Cutoff"); data._UseMetallicMap = _mat.GetTexture("_MetallicGlossMap") ? 1f : 0f; data._GlossMapScale = _mat.GetFloat("_GlossMapScale"); data._Metallic = _mat.GetFloat("_Metallic"); data._Glossiness = _mat.GetFloat("_Glossiness"); data._AlphaAsColorMask = _mat.GetFloat("_AlphaAsColorMask"); data._AlbedoAsMask = _mat.GetFloat("_AlbedoAsMask"); data._BumpScale = _mat.GetFloat("_BumpScale"); data._ReflectionSmooth = _mat.GetFloat("_ReflectionSmooth"); data._OcclusionStrength = _mat.GetFloat("_OcclusionStrength"); data._SkyIntensity = _mat.GetFloat("_SkyIntensity"); data._AlbedoAlphaEmission = _mat.GetFloat("_AlbedoAlphaEmission"); data._UseBumpMap = _mat.GetTexture("_BumpMap") ? 1f : 0f; data._UseReflectionMask = _mat.GetTexture("_ReflectionMask") ? 1f : 0f; data._SpecHighLightOff = 1f - _mat.GetFloat("_SpecularHighlights"); return(data); }
public void CacheMaterial(Material _mat, MaterialConstant _mc) { int id = _mat.GetInstanceID(); if (!materialCache.ContainsKey(id)) { materialCache.Add(id, _mat); } }
/// <summary> /// get material constant /// </summary> /// <param name="_mat"> mat </param> /// <returns> material constant </returns> public MaterialConstant GetMaterialConstant(Material _mat) { MaterialConstant mc = new MaterialConstant(); // get diffuse int dummy = 0; SetupTexAndSampler(_mat, "_MainTex", ref mc._DiffuseIndex, ref mc._SamplerIndex, whiteTex); SetupTexAndSampler(_mat, "_SpecGlossMap", ref mc._SpecularIndex, ref dummy, blackTex); SetupTexAndSampler(_mat, "_OcclusionMap", ref mc._OcclusionIndex, ref dummy, whiteTex); SetupTexAndSampler(_mat, "_EmissionMap", ref mc._EmissionIndex, ref dummy, blackTex); SetupTexAndSampler(_mat, "_BumpMap", ref mc._NormalIndex, ref dummy, blackTex); SetupTexAndSampler(_mat, "_DetailMask", ref mc._DetailMaskIndex, ref dummy, whiteTex); SetupTexAndSampler(_mat, "_DetailAlbedoMap", ref mc._DetailAlbedoIndex, ref dummy, whiteTex); SetupTexAndSampler(_mat, "_DetailNormalMap", ref mc._DetailNormalIndex, ref dummy, blackTex); mc._MainTex_ST = new Vector4(_mat.mainTextureScale.x, _mat.mainTextureScale.y, _mat.mainTextureOffset.x, _mat.mainTextureOffset.y); mc._DetailAlbedoMap_ST = new Vector4(_mat.GetTextureScale("_DetailAlbedoMap").x, _mat.GetTextureScale("_DetailAlbedoMap").y , _mat.GetTextureOffset("_DetailAlbedoMap").x, _mat.GetTextureOffset("_DetailAlbedoMap").y); if (_mat.HasProperty("_Cutoff")) { mc._CutOff = _mat.GetFloat("_Cutoff"); if (_mat.renderQueue < 2226) { mc._CutOff = 0; } } // property mc._Color = _mat.color.linear; mc._SpecColor = _mat.GetColor("_SpecColor").linear; mc._Smoothness = _mat.GetFloat("_Glossiness"); mc._OcclusionStrength = _mat.GetFloat("_OcclusionStrength"); mc._EmissionColor = _mat.GetColor("_EmissionColor").linear; mc._BumpScale = _mat.GetFloat("_BumpScale"); mc._DetailBumpScale = _mat.GetFloat("_DetailNormalMapScale"); mc._DetailUV = _mat.GetFloat("_UVSec"); mc._ReflectionCount = _mat.GetInt("_ReflectionCount"); bool isCutOff = (_mat.renderQueue <= (int)RenderQueue.GeometryLast) && (_mat.renderQueue >= 2226); bool isTransparent = (_mat.renderQueue > (int)RenderQueue.GeometryLast); if (isCutOff) { mc._RenderQueue = 1; } else if (isTransparent) { mc._RenderQueue = 2; } else { mc._RenderQueue = 0; } return(mc); }
public void ExtractMaterialData(Material _mat, int _rendererID) { int cullMode = (_mat.HasProperty("_CullMode")) ? (int)_mat.GetFloat("_CullMode") : 2; int srcBlend = (_mat.HasProperty("_SrcBlend")) ? (int)_mat.GetFloat("_SrcBlend") : 1; int dstBlend = (_mat.HasProperty("_DstBlend")) ? (int)_mat.GetFloat("_DstBlend") : 0; bool isCutOff = (_mat.renderQueue <= (int)RenderQueue.GeometryLast) && (_mat.renderQueue >= 2226); bool isTransparent = (_mat.renderQueue > (int)RenderQueue.GeometryLast); List <string> macro = new List <string>(); if (isCutOff) { macro.Add("_CUTOFF_ON"); } if (isTransparent) { macro.Add("_TRANSPARENT_ON"); } AddTexKeyword(_mat, ref macro, "_SpecGlossMap", "_SPEC_GLOSS_MAP"); AddTexKeyword(_mat, ref macro, "_BumpMap", "_NORMAL_MAP"); AddTexKeyword(_mat, ref macro, "_DetailAlbedoMap", "_DETAIL_MAP"); AddTexKeyword(_mat, ref macro, "_DetailNormalMap", "_DETAIL_NORMAL_MAP"); bool shouldEmissionBeEnabled = (_mat.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0; if (shouldEmissionBeEnabled) { macro.Add("_EMISSION"); } if (_mat.GetFloat("_UseFresnel") > 0) { macro.Add("_FRESNEL_EFFECT"); } AddNativeMaterial(_rendererID, _mat.GetInstanceID(), _mat.renderQueue, cullMode, srcBlend, dstBlend, "ForwardPass.hlsl", macro.Count, macro.ToArray()); macro.Clear(); // cache and update props if (!HasMaterial(_mat)) { MaterialConstant mc = GetMaterialConstant(_mat); UpdateNativeMaterialProp(_mat.GetInstanceID(), (uint)matConstantSize, mc); CacheMaterial(_mat, mc); } }
static extern void UpdateNativeMaterialProp(int _instanceID, uint _byteSize, MaterialConstant _mc);
void CacheMesh() { materialProps = new Dictionary <int, MaterialConstant>(); // create default texture whiteTexture = new Texture2D(16, 16, TextureFormat.ARGB32, true); whiteTexture.name = "White Texture"; Color[] c = new Color[256]; for (int i = 0; i < 256; i++) { c[i] = Color.white; } whiteTexture.SetPixels(c); whiteTexture.Apply(true, true); for (int i = 0; i < renderGroup.Count; i++) { for (int j = 0; j < renderGroup[i].renderers.Count; j++) { Renderer renderer = renderGroup[i].renderers[j]; if (HasTransparent(renderer)) { // skip model contains transparent object continue; } MeshFilter mf = renderer.GetComponent <MeshFilter>(); if (!mf || mf.sharedMesh.vertexBufferCount > 1) { continue; } Mesh staticMesh = mf.sharedMesh; uint[] indexCount = new uint[staticMesh.subMeshCount]; uint[] indexStart = new uint[staticMesh.subMeshCount]; int[] baseVertex = new int[staticMesh.subMeshCount]; for (int k = 0; k < staticMesh.subMeshCount; k++) { indexCount[k] = staticMesh.GetIndexCount(k); indexStart[k] = staticMesh.GetIndexStart(k); baseVertex[k] = (int)staticMesh.GetBaseVertex(k); } // add 1st vertex buffer only // add stride-56 mesh only (position+normal+uv0+uv1+tangent = 56 bytes) if (!AddMesh(staticMesh.GetInstanceID(), staticMesh.GetNativeVertexBufferPtr(0), staticMesh.GetNativeIndexBufferPtr(), staticMesh.vertexCount, staticMesh.subMeshCount, VertexStride, indexCount, indexStart, baseVertex)) { continue; } // add material if add mesh successfully if (renderer && renderer.enabled) { int[] matId = new int[staticMesh.subMeshCount]; for (int k = 0; k < staticMesh.subMeshCount; k++) { // add used material id matId[k] = renderer.sharedMaterials[k].GetInstanceID(); if (materialProps.ContainsKey(renderer.sharedMaterials[k].GetInstanceID())) { continue; } // extract material data MaterialConstant data = ExtractMaterialData(renderer, renderer.sharedMaterials[k]); Material mat = renderer.sharedMaterials[k]; // add texture to native, total in 8 List <int> texId = new List <int>(); texId.Add(ExtractTexture(mat.GetTexture("_MainTex") as Texture2D)); texId.Add(ExtractTexture(mat.GetTexture("_BumpMap") as Texture2D)); texId.Add(ExtractTexture(mat.GetTexture("_MetallicGlossMap") as Texture2D)); texId.Add(ExtractTexture(mat.GetTexture("_ReflectionMask") as Texture2D)); texId.Add(ExtractTexture(mat.GetTexture("_OcclusionMap") as Texture2D)); texId.Add(ExtractTexture(mat.GetTexture("_EmissionMap") as Texture2D)); int queue = (renderer.sharedMaterials[k].renderQueue == (int)RenderQueue.Geometry) ? 0 : 1; bool matValid = AddMaterial(renderer.sharedMaterials[k].GetInstanceID(), Marshal.SizeOf(typeof(MaterialConstant)), texId.Count, queue, texId.ToArray()); texId.Clear(); if (matValid) { materialProps.Add(renderer.sharedMaterials[k].GetInstanceID(), data); } else { Debug.LogError("Add material failed."); } } // extract lightmap here since it is used by renderer not materials bool hasLightMap = renderer.lightmapIndex >= 0 && renderer.lightmapIndex < LightmapSettings.lightmaps.Length; LightmapData lightMapData = (hasLightMap) ? LightmapSettings.lightmaps[renderer.lightmapIndex] : new LightmapData(); int[] lightmapId = new int[2]; lightmapId[0] = ExtractTexture(lightMapData.lightmapColor); lightmapId[1] = ExtractTexture(lightMapData.shadowMask); AddRenderer(Matrix4x4ToFloat16(renderer.localToWorldMatrix) , Matrix4x4ToFloat16(renderer.worldToLocalMatrix) , VectorToFloat4(renderer.lightmapScaleOffset) , renderer.GetInstanceID() , staticMesh.GetInstanceID() , matId , lightmapId , i); renderer.gameObject.layer = LayerMask.NameToLayer("NativeRenderer"); // mark as native renderer } } } }