├── Materials ├── pink1x1.png ├── transparent1x1.png ├── halftransparent1x1.png ├── FlatShadow.mat.meta ├── FlatShadowVR2d.mat.meta ├── HiddenForAll.mat.meta ├── StarNestAvatar.mat.meta ├── FlatShadowForAll.mat.meta ├── OnlyShadersDisabled.mat.meta ├── pink1x1.png.meta ├── halftransparent1x1.png.meta ├── transparent1x1.png.meta ├── OnlyShadersDisabled.mat ├── HiddenForAll.mat ├── FlatShadow.mat ├── FlatShadowForAll.mat ├── FlatShadowVR2d.mat └── StarNestAvatar.mat ├── Waifu2d ├── waifu2d_preview.png ├── Editor.meta ├── Waifu2d.cginc.meta ├── StandardSimple.shader.meta ├── StandardSimple_2d.shader.meta ├── Editor │ ├── Waifu2dGenerator.cs.meta │ └── Waifu2dGenerator.cs ├── waifu2d_preview.png.meta ├── Waifu2d.cginc ├── StandardSimple.shader └── StandardSimple_2d.shader ├── LICENSE.meta ├── README.md.meta ├── LyumaShader ├── Editor.meta ├── Hidden.shader.meta ├── DropShadowLite.shader.meta ├── StarNestAvatar.shader.meta ├── DropShadowLiteVR2d.shader.meta ├── Editor │ ├── LyumaMeshTools.cs.meta │ └── LyumaMeshTools.cs ├── Hidden.shader ├── DropShadowLite.shader ├── DropShadowLiteVR2d.shader └── StarNestAvatar.shader ├── Materials.meta ├── Waifu2d.meta ├── LyumaShader.meta ├── LICENSE └── README.md /Materials/pink1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyuma/LyumaShader/HEAD/Materials/pink1x1.png -------------------------------------------------------------------------------- /Waifu2d/waifu2d_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyuma/LyumaShader/HEAD/Waifu2d/waifu2d_preview.png -------------------------------------------------------------------------------- /Materials/transparent1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyuma/LyumaShader/HEAD/Materials/transparent1x1.png -------------------------------------------------------------------------------- /Materials/halftransparent1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyuma/LyumaShader/HEAD/Materials/halftransparent1x1.png -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bdd2fc28eed35114181a1b1d0a6a43e9 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d1463e2a32f863247bc087cb236f2081 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LyumaShader/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 62c6b59928cc2384fa7634c7b9a28c4e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d66ca11bb13241d7a151dd536878909 3 | folderAsset: yes 4 | timeCreated: 1539257821 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Waifu2d.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad50020b8dbb84ca88cdc801e4cb1ae2 3 | folderAsset: yes 4 | timeCreated: 1539154315 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /LyumaShader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fd48024535a6843bca8d7eeecea7c982 3 | folderAsset: yes 4 | timeCreated: 1539091200 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Waifu2d/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d7fd672b824b94350a19611ba595ffc9 3 | folderAsset: yes 4 | timeCreated: 1539090575 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Waifu2d/Waifu2d.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 69281b4f8b28a4e61bd5e42dcf44612c 3 | timeCreated: 1539084422 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /LyumaShader/Hidden.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9f8f1a0d40d804536a5c141fd463ba39 3 | timeCreated: 1528903415 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Waifu2d/StandardSimple.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 27c8974056caf4f0eb4b78da19ce39ab 3 | timeCreated: 1539088320 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /LyumaShader/DropShadowLite.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a1d697a1dd79a47cbae7f549265dc840 3 | timeCreated: 1539090855 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /LyumaShader/StarNestAvatar.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 606f23d576f7f470996da1eb03cb4dc5 3 | timeCreated: 1539259128 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Materials/FlatShadow.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3bebe0e6a2a7e4fc19e44d99985fcdb5 3 | timeCreated: 1539257923 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Waifu2d/StandardSimple_2d.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 814e6a006c192424885d253f2b609207 3 | timeCreated: 1539088354 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /LyumaShader/DropShadowLiteVR2d.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36a075b1caa9c434b87241c9cb5af523 3 | timeCreated: 1539090855 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Materials/FlatShadowVR2d.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0c107585d8a024bb1b6b932de1549e2b 3 | timeCreated: 1539257923 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Materials/HiddenForAll.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1bdc948fc43444e7fa7bcf7e04b17d34 3 | timeCreated: 1539258044 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Materials/StarNestAvatar.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3594a7fd9180944dfb77c43db4a633a7 3 | timeCreated: 1534014785 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Materials/FlatShadowForAll.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 98b9ddd2cdd014e6f98ba7450817201e 3 | timeCreated: 1539257923 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Materials/OnlyShadersDisabled.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c4fbee4bdfe1f480886a61e4b0a53187 3 | timeCreated: 1539258094 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /LyumaShader/Editor/LyumaMeshTools.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dbb5488ab1bbf9840ab8f624e2525933 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Waifu2d/Editor/Waifu2dGenerator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b40549c3fcc17448d9aab08525847d24 3 | timeCreated: 1539090576 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /LyumaShader/Hidden.shader: -------------------------------------------------------------------------------- 1 | // Hides a mesh by Rokk 2 | Shader "LyumaShader/HiddenToonTransparentUnlit" { Properties { 3 | _MainTex("Main Tex UNUSED", 2D) = "white" {} 4 | _Color("Color Tint", Color) = (1,1,1,1) 5 | } SubShader { 6 | Tags { "Queue"="Geometry" "IgnoreProjector"="True" "VRCFallback"="Hidden" } 7 | Pass { ZWrite Off ColorMask Off 8 | CGPROGRAM 9 | #pragma vertex vert 10 | #pragma fragment frag 11 | float4 vert() : SV_Position { return 1; } 12 | float4 frag() : SV_Target { return 0; } 13 | ENDCG 14 | } } } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018-2021 Lyuma 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Materials/pink1x1.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c8737adf5c93e414c8bfd5fc7bb987e6 3 | timeCreated: 1538310964 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 1 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 0 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 0 46 | spriteTessellationDetail: -1 47 | textureType: 0 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | spriteSheet: 62 | serializedVersion: 2 63 | sprites: [] 64 | outline: [] 65 | spritePackingTag: 66 | userData: 67 | assetBundleName: 68 | assetBundleVariant: 69 | -------------------------------------------------------------------------------- /Materials/halftransparent1x1.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1a3a1ea1b5d27407dae611fbdcde0140 3 | timeCreated: 1538310198 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 1 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 0 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 0 46 | spriteTessellationDetail: -1 47 | textureType: 0 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | spriteSheet: 62 | serializedVersion: 2 63 | sprites: [] 64 | outline: [] 65 | spritePackingTag: 66 | userData: 67 | assetBundleName: 68 | assetBundleVariant: 69 | -------------------------------------------------------------------------------- /Materials/transparent1x1.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4c6cea37f70f8479c9e66b4977b3e237 3 | timeCreated: 1538309669 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 1 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 0 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 0 46 | spriteTessellationDetail: -1 47 | textureType: 0 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | spriteSheet: 62 | serializedVersion: 2 63 | sprites: [] 64 | outline: [] 65 | spritePackingTag: 66 | userData: 67 | assetBundleName: 68 | assetBundleVariant: 69 | -------------------------------------------------------------------------------- /Materials/OnlyShadersDisabled.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: OnlyShadersDisabled 10 | m_Shader: {fileID: 4800000, guid: 9f8f1a0d40d804536a5c141fd463ba39, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 1, b: 1, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /Materials/HiddenForAll.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: HiddenForAll 10 | m_Shader: {fileID: 4800000, guid: 9f8f1a0d40d804536a5c141fd463ba39, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 2800000, guid: 4c6cea37f70f8479c9e66b4977b3e237, type: 3} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 1, b: 1, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /Materials/FlatShadow.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: FlatShadow 10 | m_Shader: {fileID: 4800000, guid: a1d697a1dd79a47cbae7f549265dc840, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 2800000, guid: 4c6cea37f70f8479c9e66b4977b3e237, type: 3} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | - _texcoord: 58 | m_Texture: {fileID: 0} 59 | m_Scale: {x: 1, y: 1} 60 | m_Offset: {x: 0, y: 0} 61 | m_Floats: 62 | - _2d_coef: 0.99 63 | - _BumpScale: 1 64 | - _Cutoff: 0.5 65 | - _DetailNormalMapScale: 1 66 | - _DstBlend: 0 67 | - _GlossMapScale: 1 68 | - _Glossiness: 0.5 69 | - _GlossyReflections: 1 70 | - _Metallic: 0 71 | - _Mode: 0 72 | - _OcclusionStrength: 1 73 | - _Parallax: 0.02 74 | - _SmoothnessTextureChannel: 0 75 | - _SpecularHighlights: 1 76 | - _SrcBlend: 1 77 | - _UVSec: 0 78 | - _ZWrite: 1 79 | - __dirty: 1 80 | - _facing_coef: 0 81 | - _local3d_coef: 0 82 | - _lock2daxis_coef: 1 83 | - _zcorrect_coef: 0.975 84 | - _ztweak_coef: 0 85 | m_Colors: 86 | - _Color: {r: 1, g: 1, b: 1, a: 1} 87 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 88 | - _shadow_offset: {r: 0, g: 0, b: 0, a: 0} 89 | -------------------------------------------------------------------------------- /Materials/FlatShadowForAll.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: FlatShadowForAll 10 | m_Shader: {fileID: 4800000, guid: a1d697a1dd79a47cbae7f549265dc840, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 2800000, guid: 1a3a1ea1b5d27407dae611fbdcde0140, type: 3} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | - _texcoord: 58 | m_Texture: {fileID: 0} 59 | m_Scale: {x: 1, y: 1} 60 | m_Offset: {x: 0, y: 0} 61 | m_Floats: 62 | - _2d_coef: 0.99 63 | - _BumpScale: 1 64 | - _Cutoff: 0.5 65 | - _DetailNormalMapScale: 1 66 | - _DstBlend: 0 67 | - _GlossMapScale: 1 68 | - _Glossiness: 0.5 69 | - _GlossyReflections: 1 70 | - _Metallic: 0 71 | - _Mode: 0 72 | - _OcclusionStrength: 1 73 | - _Parallax: 0.02 74 | - _SmoothnessTextureChannel: 0 75 | - _SpecularHighlights: 1 76 | - _SrcBlend: 1 77 | - _UVSec: 0 78 | - _ZWrite: 1 79 | - __dirty: 1 80 | - _facing_coef: 0 81 | - _local3d_coef: 0 82 | - _lock2daxis_coef: 1 83 | - _zcorrect_coef: 0.975 84 | - _ztweak_coef: 0 85 | m_Colors: 86 | - _Color: {r: 1, g: 1, b: 1, a: 1} 87 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 88 | - _shadow_offset: {r: 0, g: 0, b: 0, a: 0} 89 | -------------------------------------------------------------------------------- /Materials/FlatShadowVR2d.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: FlatShadowVR2d 10 | m_Shader: {fileID: 4800000, guid: 36a075b1caa9c434b87241c9cb5af523, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 2800000, guid: 4c6cea37f70f8479c9e66b4977b3e237, type: 3} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | - _texcoord: 58 | m_Texture: {fileID: 0} 59 | m_Scale: {x: 1, y: 1} 60 | m_Offset: {x: 0, y: 0} 61 | m_Floats: 62 | - _2d_coef: 0.99 63 | - _BumpScale: 1 64 | - _Cutoff: 0.5 65 | - _DetailNormalMapScale: 1 66 | - _DstBlend: 0 67 | - _GlossMapScale: 1 68 | - _Glossiness: 0.5 69 | - _GlossyReflections: 1 70 | - _Metallic: 0 71 | - _Mode: 0 72 | - _OcclusionStrength: 1 73 | - _Parallax: 0.02 74 | - _SmoothnessTextureChannel: 0 75 | - _SpecularHighlights: 1 76 | - _SrcBlend: 1 77 | - _UVSec: 0 78 | - _ZWrite: 1 79 | - __dirty: 1 80 | - _facing_coef: 0 81 | - _local3d_coef: 0 82 | - _lock2daxis_coef: 0 83 | - _zcorrect_coef: 0.975 84 | - _ztweak_coef: 0 85 | m_Colors: 86 | - _Color: {r: 0, g: 0, b: 0, a: 1} 87 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 88 | - _shadow_offset: {r: 0.03, g: 0.015, b: 0, a: 3} 89 | -------------------------------------------------------------------------------- /Waifu2d/waifu2d_preview.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 10055f5874c1c224bb56ede209293a67 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 0 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | - serializedVersion: 2 73 | buildTarget: Standalone 74 | maxTextureSize: 2048 75 | resizeAlgorithm: 0 76 | textureFormat: -1 77 | textureCompression: 0 78 | compressionQuality: 50 79 | crunchedCompression: 0 80 | allowsAlphaSplitting: 0 81 | overridden: 0 82 | androidETC2FallbackOverride: 0 83 | - serializedVersion: 2 84 | buildTarget: Android 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 0 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | androidETC2FallbackOverride: 0 94 | spriteSheet: 95 | serializedVersion: 2 96 | sprites: [] 97 | outline: [] 98 | physicsShape: [] 99 | bones: [] 100 | spriteID: 101 | vertices: [] 102 | indices: 103 | edges: [] 104 | weights: [] 105 | spritePackingTag: 106 | pSDRemoveMatte: 0 107 | pSDShowRemoveMatteOption: 0 108 | userData: 109 | assetBundleName: 110 | assetBundleVariant: 111 | -------------------------------------------------------------------------------- /LyumaShader/DropShadowLite.shader: -------------------------------------------------------------------------------- 1 | // Shader which uses Waifu2d.cginc to render a flat shadow behind an avatar. 2 | // Compatible with the same set of properties used in other flat shaders. 3 | // This shader was not Waifu2d Generated. 4 | Shader "LyumaShader/DropShadowLiteToonTransparent" 5 | { 6 | Properties 7 | { 8 | _2d_coef ("Twodimensionalness", Range(0, 1)) = 0.99 9 | _facing_coef ("Face in Profile", Range (-1, 1)) = 0.0 10 | _lock2daxis_coef ("Lock 2d Axis", Range (0, 1)) = 1.0 11 | //_local3d_coef ("See self in 3d", Range (0, 1)) = 0.0 12 | //_zcorrect_coef ("Squash Z (good=.975; 0=3d; 1=z-fight)", Float) = 0.975 13 | //_ztweak_coef ("Tweak z clip", Range (-1, 1)) = 0.0 14 | _shadow_offset ("Shadow Offset [W=hardness,0-100]", Vector) = (0.03,0.015,0,3) 15 | _Color ("Color", Color) = (0,0,0,1) 16 | _MainTex("Main Tex", 2D) = "transparent" {} 17 | [HideInInspector] _texcoord( "", 2D ) = "white" {} 18 | [HideInInspector] __dirty( "", Int ) = 1 19 | } 20 | 21 | SubShader 22 | { 23 | Tags{ "RenderType" = "Transparent" "Queue" = "Transparent+503" "IsEmissive" = "true" "IgnoreProjector"="True" } 24 | Cull Off 25 | ZWrite Off 26 | Blend One OneMinusSrcColor 27 | 28 | CGINCLUDE 29 | //#define UNITY_PASS_FORWARDADD 30 | #include "UnityCG.cginc" 31 | /* #define NO_UNIFORMS 32 | static float _2d_coef = 1.; 33 | uniform float _facing_coef; 34 | uniform float _lock2daxis_coef; 35 | uniform float _ztweak_coef;*/ 36 | 37 | uniform float4 _shadow_offset; 38 | uniform float4 _Color; 39 | #include "../Waifu2d/Waifu2d.cginc" 40 | 41 | struct VertexInput { 42 | float4 vertex : POSITION; 43 | float3 normal : NORMAL; 44 | float2 texcoord0 : TEXCOORD0; 45 | }; 46 | struct v2f_surf { 47 | float4 normalCameraNormW : TEXCOORD1; 48 | float3 worldPos : TEXCOORD0; 49 | float4 pos : SV_POSITION; 50 | float4 color : TEXCOORD2; 51 | }; 52 | v2f_surf vert (VertexInput v) { 53 | v2f_surf o = (v2f_surf)0; 54 | //float4 tmp = v.vertex; 55 | //v.vertex = waifu_preprocess(v.vertex, v.normal, tmp);// * 1.04; 56 | float3 worldNormal = UnityObjectToWorldNormal(v.normal); 57 | 58 | float3 bitang = myInvVMat._21_22_23; //normalize(posWorld - mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz); 59 | float3 tang = myInvVMat._11_12_13; //cross(bitang, normalize(posWorld - mul(unity_ObjectToWorld, float4(0,0,1,1)).xyz)); 60 | float3 norm = myInvVMat._31_32_33; //cross(tang, bitang); 61 | bitang = cross(norm, tang); 62 | tang = cross(bitang, norm); 63 | float normAlignment = (abs(dot(normalize(worldNormal), normalize(norm))));//1 - max(abs(dot(normalize(v.normal), tang)), abs(dot(normalize(v.normal), bitang))); 64 | //normAlignment = pow(normAlignment, 0.5); 65 | normAlignment = saturate(normAlignment * 1.3); 66 | normAlignment = pow(normAlignment, 1.25); 67 | 68 | float4 origWorldPos = mul(unity_ObjectToWorld, v.vertex); 69 | float4 actualObjectPos = waifu_computeVertexWorldPos(v.vertex); 70 | //float4 actualObjectPos2 = mul(unity_WorldToObject, actualObjectPos); 71 | float3 posWorld = actualObjectPos.xyz; 72 | float3 baseCamDist = (realCameraPos.xyz - origWorldPos.xyz); 73 | float3 projCamDist = (realCameraPos.xyz - posWorld.xyz); 74 | float3 realZPoint = posWorld - normalize(baseCamDist) * (100. * (0.00124 + 0.00006 * (1-normAlignment)));// * saturate(1. * length(baseCamDist - projCamDist)))); // (1. - color))); 75 | float4 projZPoint = UnityWorldToClipPos(float4(realZPoint.xyz, 1)); 76 | 77 | //actualObjectPos += float4(-0.03*bitang,0.); 78 | actualObjectPos += float4((_shadow_offset.z * norm + _shadow_offset.x * tang + _shadow_offset.y * bitang),0.);// * dot(approxEyeDir.xz, cameraToObj2D.xy), 0.); 79 | o.worldPos = actualObjectPos; //mul(unity_ObjectToWorld, actualObjectPos2); 80 | //o.worldPos += baseCamDist 81 | o.pos = UnityWorldToClipPos(actualObjectPos); 82 | o.pos.z = projZPoint.z * o.pos.w / projZPoint.w; 83 | o.normalCameraNormW = float4(v.normal, max(_shadow_offset.w, abs(dot(normalize(baseCamDist), norm)))); 84 | //fixed3 worldNormal = UnityObjectToWorldNormal( v.normal ); 85 | o.color = float4(_Color.rgb,normAlignment); 86 | return o; 87 | } 88 | 89 | float4 frag(v2f_surf i) : COLOR { 90 | //clip(1.3 - i.color.a); 91 | //i.color.a = lerp(i.color.a, i.color.a > 1.3 ? 0. : i.color.a, 1.); 92 | //clip(0.5 - i.color.a); 93 | //i.color.a = sqrt(i.color.a); 94 | return float4(i.color.rgb, _Color.a * saturate(sqrt(1.04 * i.color.a * sqrt(i.normalCameraNormW.w))));//saturate(2 * pow(saturate(i.color.a * i.normalCameraNormW.w), 0.8))); 95 | } 96 | ENDCG 97 | 98 | 99 | Pass 100 | { 101 | ColorMask 0 102 | ZWrite On 103 | ZTest LEqual 104 | CGPROGRAM 105 | #pragma vertex vert 106 | #pragma fragment frag 107 | 108 | #pragma shader_feature VR_ONLY_2D 109 | #define SHADOW_ZWRITE_PASS 110 | ENDCG 111 | } 112 | Pass 113 | { 114 | Blend SrcAlpha OneMinusSrcAlpha 115 | ZWrite Off 116 | ZTest Equal 117 | CGPROGRAM 118 | #pragma vertex vert 119 | #pragma fragment frag 120 | 121 | #pragma shader_feature VR_ONLY_2D 122 | #define SHADOW_RENDER_PASS 123 | ENDCG 124 | } 125 | 126 | } // subshader 127 | //CustomEditor "ASEMaterialInspector" 128 | } 129 | -------------------------------------------------------------------------------- /Materials/StarNestAvatar.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: StarNestAvatar 10 | m_Shader: {fileID: 4800000, guid: 606f23d576f7f470996da1eb03cb4dc5, type: 3} 11 | m_ShaderKeywords: DISABLE_OUTLINE 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BakedCube: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _BumpMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailAlbedoMap: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailMask: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _DetailNormalMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _EmissionMap: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _EmissiveTex: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _MaXinTex: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _MainTex: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | - _MetallicGlossMap: 58 | m_Texture: {fileID: 0} 59 | m_Scale: {x: 1, y: 1} 60 | m_Offset: {x: 0, y: 0} 61 | - _MetallicMap: 62 | m_Texture: {fileID: 0} 63 | m_Scale: {x: 1, y: 1} 64 | m_Offset: {x: 0, y: 0} 65 | - _Normal: 66 | m_Texture: {fileID: 0} 67 | m_Scale: {x: 1, y: 1} 68 | m_Offset: {x: 0, y: 0} 69 | - _OcclusionMap: 70 | m_Texture: {fileID: 0} 71 | m_Scale: {x: 1, y: 1} 72 | m_Offset: {x: 0, y: 0} 73 | - _ParallaxMap: 74 | m_Texture: {fileID: 0} 75 | m_Scale: {x: 1, y: 1} 76 | m_Offset: {x: 0, y: 0} 77 | - _RoughMap: 78 | m_Texture: {fileID: 0} 79 | m_Scale: {x: 1, y: 1} 80 | m_Offset: {x: 0, y: 0} 81 | - _ShadowRamp: 82 | m_Texture: {fileID: 2800000, guid: 638ce7c8d7c21e74eb4d9911ef39cbf4, type: 3} 83 | m_Scale: {x: 1, y: 1} 84 | m_Offset: {x: 0, y: 0} 85 | - _SpecularMap: 86 | m_Texture: {fileID: 0} 87 | m_Scale: {x: 1, y: 1} 88 | m_Offset: {x: 0, y: 0} 89 | - _SpecularPattern: 90 | m_Texture: {fileID: 0} 91 | m_Scale: {x: 1, y: 1} 92 | m_Offset: {x: 0, y: 0} 93 | - _texcoord: 94 | m_Texture: {fileID: 0} 95 | m_Scale: {x: 1, y: 1} 96 | m_Offset: {x: 0, y: 0} 97 | - _texcoord2: 98 | m_Texture: {fileID: 0} 99 | m_Scale: {x: 1, y: 1} 100 | m_Offset: {x: 0, y: 0} 101 | m_Floats: 102 | - _2d_coef: 0.99 103 | - _Brightness: 0.5 104 | - _BumpScale: 1 105 | - _CLAMPOUT: 0 106 | - _CamScroll: 0 107 | - _Culling: 0 108 | - _Cutoff: 0.1 109 | - _Darkmatter: 555 110 | - _DetailNormalMapScale: 1 111 | - _Distfading: 55 112 | - _DstBlend: 0 113 | - _Emissive: 0 114 | - _Formuparam: 572 115 | - _GlossMapScale: 1 116 | - _Glossiness: 0.5 117 | - _GlossyReflections: 1 118 | - _Iterations: 5 119 | - _MatcapStyle: 1 120 | - _Metallic: 0 121 | - _Mode: 0 122 | - _OcclusionStrength: 1 123 | - _Offset: 0 124 | - _Parallax: 0.02 125 | - _RampDir: 1 126 | - _ReadMask: 255 127 | - _ReflSmoothness: 1 128 | - _ReflType: 0 129 | - _RimIntensity: 0.8 130 | - _RimWidth: 0.2 131 | - _RimlightType: 1 132 | - _Saturation: 1 133 | - _ShadowIntensity: 0.3 134 | - _ShadowType: 1 135 | - _SmoothnessTextureChannel: 0 136 | - _SpecularArea: 25 137 | - _SpecularHighlights: 1 138 | - _SpecularIntensity: 5 139 | - _SrcBlend: 1 140 | - _Stencil: 0 141 | - _StencilComp: 0 142 | - _StencilFail: 0 143 | - _StencilOp: 0 144 | - _StencilZFail: 0 145 | - _StepSize: 355 146 | - _StylelizedIntensity: 1 147 | - _StylizedReflStyle: 0 148 | - _Tile: 700 149 | - _UVSec: 0 150 | - _UseOnlyBakedCube: 0 151 | - _UseReflections: 1 152 | - _UseUV2forNormalsSpecular: 0 153 | - _Volsteps: 6 154 | - _WriteMask: 255 155 | - _ZTest: 4 156 | - _ZWrite: 1 157 | - __dirty: 1 158 | - _advMode: 1 159 | - _colormask: 15 160 | - _dstblend: 0 161 | - _facing_coef: 0 162 | - _frustration_coef: 0 163 | - _local3d_coef: 1 164 | - _lock2daxis_coef: 0.8 165 | - _mode: 0 166 | - _srcblend: 1 167 | - _zcorrect_coef: 0.975 168 | - _ztweak_coef: 0 169 | m_Colors: 170 | - _Center: {r: 1, g: 0.3, b: 0.5, a: 0} 171 | - _Color: {r: 1, g: 1, b: 1, a: 1} 172 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 173 | - _EmissiveColor: {r: 0, g: 0, b: 0, a: 1} 174 | - _NormalTiling: {r: 1, g: 1, b: 0, a: 0} 175 | - _Rotation: {r: 0, g: 0, b: 0, a: 0.01} 176 | - _Scroll: {r: 1.3, g: 1, b: 0.6, a: 0.01} 177 | - _SimulatedLightDirection: {r: 0, g: 45, b: 90, a: 0} 178 | - _SpecularPatternTiling: {r: 20, g: 20, b: 0, a: 0} 179 | -------------------------------------------------------------------------------- /LyumaShader/DropShadowLiteVR2d.shader: -------------------------------------------------------------------------------- 1 | // Shader which uses Waifu2d.cginc to render a flat shadow behind an avatar. 2 | // Compatible with the same set of properties used in other flat shaders. 3 | // This shader was not Waifu2d Generated. 4 | Shader "LyumaShader/DropShadowLiteToonTransparentVR2d" 5 | { 6 | Properties 7 | { 8 | _2d_coef ("Twodimensionalness", Range(0, 1)) = 0.99 9 | _facing_coef ("Face in Profile", Range (-1, 1)) = 0.0 10 | _lock2daxis_coef ("Lock 2d Axis", Range (0, 1)) = 1.0 11 | //_local3d_coef ("See self in 3d", Range (0, 1)) = 0.0 12 | //_zcorrect_coef ("Squash Z (good=.975; 0=3d; 1=z-fight)", Float) = 0.975 13 | //_ztweak_coef ("Tweak z clip", Range (-1, 1)) = 0.0 14 | _shadow_offset ("Shadow Offset [W=hardness,0-100]", Vector) = (0.03,0.015,0,3) 15 | _Color ("Color", Color) = (0,0,0,1) 16 | _MainTex("Main Tex", 2D) = "transparent" {} 17 | [HideInInspector] _texcoord( "", 2D ) = "white" {} 18 | [HideInInspector] __dirty( "", Int ) = 1 19 | } 20 | 21 | SubShader 22 | { 23 | Tags{ "RenderType" = "Transparent" "Queue" = "Transparent+503" "IsEmissive" = "true" "IgnoreProjector"="True" } 24 | Cull Off 25 | ZWrite Off 26 | Blend One OneMinusSrcColor 27 | 28 | CGINCLUDE 29 | //#define UNITY_PASS_FORWARDADD 30 | #include "UnityCG.cginc" 31 | /* #define NO_UNIFORMS 32 | static float _2d_coef = 1.; 33 | uniform float _facing_coef; 34 | uniform float _lock2daxis_coef; 35 | uniform float _ztweak_coef;*/ 36 | 37 | uniform float4 _shadow_offset; 38 | uniform float4 _Color; 39 | #include "../Waifu2d/Waifu2d.cginc" 40 | 41 | struct VertexInput { 42 | float4 vertex : POSITION; 43 | float3 normal : NORMAL; 44 | float2 texcoord0 : TEXCOORD0; 45 | }; 46 | struct v2f_surf { 47 | float4 normalCameraNormW : TEXCOORD1; 48 | float3 worldPos : TEXCOORD0; 49 | float4 pos : SV_POSITION; 50 | float4 color : TEXCOORD2; 51 | }; 52 | v2f_surf vert (VertexInput v) { 53 | v2f_surf o = (v2f_surf)0; 54 | #if !defined(USING_STEREO_MATRICES) 55 | o.pos = float4(1,1,1,1); 56 | #else 57 | //float4 tmp = v.vertex; 58 | //v.vertex = waifu_preprocess(v.vertex, v.normal, tmp);// * 1.04; 59 | float3 worldNormal = UnityObjectToWorldNormal(v.normal); 60 | 61 | float3 bitang = myInvVMat._21_22_23; //normalize(posWorld - mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz); 62 | float3 tang = myInvVMat._11_12_13; //cross(bitang, normalize(posWorld - mul(unity_ObjectToWorld, float4(0,0,1,1)).xyz)); 63 | float3 norm = myInvVMat._31_32_33; //cross(tang, bitang); 64 | bitang = cross(norm, tang); 65 | tang = cross(bitang, norm); 66 | float normAlignment = (abs(dot(normalize(worldNormal), normalize(norm))));//1 - max(abs(dot(normalize(v.normal), tang)), abs(dot(normalize(v.normal), bitang))); 67 | //normAlignment = pow(normAlignment, 0.5); 68 | normAlignment = saturate(normAlignment * 1.3); 69 | normAlignment = pow(normAlignment, 1.25); 70 | 71 | float4 origWorldPos = mul(unity_ObjectToWorld, v.vertex); 72 | float4 actualObjectPos = waifu_computeVertexWorldPos(v.vertex); 73 | //float4 actualObjectPos2 = mul(unity_WorldToObject, actualObjectPos); 74 | float3 posWorld = actualObjectPos.xyz; 75 | float3 baseCamDist = (realCameraPos.xyz - origWorldPos.xyz); 76 | float3 projCamDist = (realCameraPos.xyz - posWorld.xyz); 77 | float3 realZPoint = posWorld - normalize(baseCamDist) * (100. * (0.00124 + 0.00006 * (1-normAlignment)));// * saturate(1. * length(baseCamDist - projCamDist)))); // (1. - color))); 78 | float4 projZPoint = UnityWorldToClipPos(float4(realZPoint.xyz, 1)); 79 | 80 | //actualObjectPos += float4(-0.03*bitang,0.); 81 | actualObjectPos += float4((_shadow_offset.z * norm + _shadow_offset.x * tang + _shadow_offset.y * bitang),0.);// * dot(approxEyeDir.xz, cameraToObj2D.xy), 0.); 82 | o.worldPos = actualObjectPos; //mul(unity_ObjectToWorld, actualObjectPos2); 83 | //o.worldPos += baseCamDist 84 | o.pos = UnityWorldToClipPos(actualObjectPos); 85 | o.pos.z = projZPoint.z * o.pos.w / projZPoint.w; 86 | o.normalCameraNormW = float4(v.normal, max(_shadow_offset.w, abs(dot(normalize(baseCamDist), norm)))); 87 | //fixed3 worldNormal = UnityObjectToWorldNormal( v.normal ); 88 | o.color = float4(_Color.rgb,normAlignment); 89 | #endif 90 | return o; 91 | } 92 | 93 | float4 frag(v2f_surf i) : COLOR { 94 | //clip(1.3 - i.color.a); 95 | //i.color.a = lerp(i.color.a, i.color.a > 1.3 ? 0. : i.color.a, 1.); 96 | //clip(0.5 - i.color.a); 97 | //i.color.a = sqrt(i.color.a); 98 | return float4(i.color.rgb, _Color.a * saturate(sqrt(1.04 * i.color.a * sqrt(i.normalCameraNormW.w))));//saturate(2 * pow(saturate(i.color.a * i.normalCameraNormW.w), 0.8))); 99 | } 100 | ENDCG 101 | 102 | 103 | Pass 104 | { 105 | ColorMask 0 106 | ZWrite On 107 | ZTest LEqual 108 | CGPROGRAM 109 | #pragma vertex vert 110 | #pragma fragment frag 111 | 112 | #pragma shader_feature VR_ONLY_2D 113 | #define SHADOW_ZWRITE_PASS 114 | ENDCG 115 | } 116 | Pass 117 | { 118 | Blend SrcAlpha OneMinusSrcAlpha 119 | ZWrite Off 120 | ZTest Equal 121 | CGPROGRAM 122 | #pragma vertex vert 123 | #pragma fragment frag 124 | 125 | #pragma shader_feature VR_ONLY_2D 126 | #define SHADOW_RENDER_PASS 127 | ENDCG 128 | } 129 | 130 | } // subshader 131 | //CustomEditor "ASEMaterialInspector" 132 | } 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lyuma's Shaders 2 | 3 | This is a collection of editor scripts and shaders for Unity or VRChat. Currently, the repository focuses on a 2d effect. More shaders and scripts will be coming. 4 | 5 | To download, expand the Releases link, and download the unitypackage... Or, click the green Code button and Download ZIP. Then extract into your unity Assets folder. 6 | 7 | # Waifu2d 8 | 9 | This feature, "Make 2d", will flatten any material onto a vertical plane, by modifying the shader. 10 | 11 | ![access Waifu2d from the Material context menu](Waifu2d/waifu2d_preview.png)\ 12 | *Featured: Amanatsu by komado showing Silent's Crosstone, Xiexe's XSToon 3.0.1 and Poiyomi Toon v7.1.53* 13 | 14 | To access, select all the materials you wish to convert, then use the gear menu to select **Make 2d** - to switch materials back to 3d mode, select **Revert to 3d**. It works well when combined with an extremely thick outline with solid color. 15 | 16 | ## How to configure and animate 2d effects 17 | 18 | The material inspector is disabled once you are in 2d mode. While in this mode, you can configure the plane to face one direction (Locked to a 2d axis determined by Facing direction), or billboarded to the player's camera for a sprite game feel. Feel free to revert to 3d to make more material changes, or edit the sliders directly. 19 | 20 | You can animate the _2d_coef and _lock_2d_axis material values for switching between 2d, billboard, and 3d modes. You must do this on every mesh to avoid clipping. You may want to also animate the outline width to be smaller when in 3d. 21 | 22 | Note that this shader cheats and produces falsified depth values to minimize Z-fighting. However, if you wish to mix parts in 2d and 3d, you can adjust the "Squash Z" value to some value usually around 0.95 or 0.975 so that they line up. 23 | 24 | ## Other notes about 2d 25 | 26 | This shader requires that *all* meshes have the same **Root Bone** slot set in the SkinnedMeshRenderer. Changing the Root Bone is mostly safe, but you must adjust the Mesh Bounds to compensate. If you have any meshes which are not skinned, they will not align to the same 2d plane and may look unusual. This is best fixed from within blender by combining meshes. 27 | 28 | "See self in 3d" has been removed. If you need this functionality use the Avatar 3.0 IsLocal parameter. 29 | 30 | Note that this includes a copy of the built-in Standard shader for metallic setup only. Specular setup is not implemented yet, but would be easy to add if requested. 31 | 32 | # LyumaMeshTools (LMT) 33 | 34 | The LyumaMeshTools editor script is located in LyumaShader/Editor. It contains a set of features in the gear or right click menu of Mesh Renderer and similar components. If you want to customize these, pick the closest one and edit the source code. 35 | 36 | - "**Vertex position to UV2 : LMT**" : records original vertex position for use with shading effects that deform properly with skinned meshes (similar to using Project From View in blender, but with all 3 axes) 37 | 38 | - "**Merge UV with UV2 : LMT**" puts UV2.xy as the .zw components of UV. Can be used similarly as vertex colors. This frees up the second UV for baked lightmaps. 39 | 40 | - "**Assetize Meshes : LMT**" properly duplicates the mesh out of an FBX file. 41 | 42 | - "**Add Shadow : LMT**" adds another material sharing vertices but with a face for every face in existing materials. Can be used for a stencil or with my shadow shader to make a shadow around your mesh. 43 | 44 | - "**Combine Same Material : LMT**" is an optimization tool to combine all copies of the same material into one. You can control this process by manually putting the same material into different slots before running this script. 45 | 46 | - "**Remove Null Mats : LMT**" removes any material in a mesh and the corresponding polygons for any unassigned (pink) material slots. NOTE: Does not remove unused vertices. 47 | 48 | - "**Combine Mesh Siblings : LMT**" Is an optimization tool to combine all skinned mesh renderers with the same parent into one skinned mesh renderer with multiple materials. It can also be useful to guarantee meshes are rendered in order.\ 49 | \ 50 | "Combine Mesh Siblings" now also merges blendshapes from sibling meshes. This way, you can pick any mesh to be the main Body mesh and not worry about losing blendshapes. 51 | 52 | - "**Make Skinned Parent+Child : LMT**" Builds skinned meshes out of non-skinned: See this tutorial:\ 53 | ![LyumaMeshTools tutorial](https://user-images.githubusercontent.com/39946030/122019045-41e18380-cd78-11eb-8fa0-28ec72adbbe9.mp4) 54 | 55 | - "**Keyframe Blend Shapes : LMT**" is a unique feature that edits a mesh with blendshapes named with a percent at the end like Blink_25% Blink_50% and merges them into a single blendshape at those percents. This tool can create instant blend shapes as well as any sort of custom mesh animation from a single gesture (or activation of multiple props from variable fist pressure). There is no way to my knowledge to import such blend shapes.\ 56 | \ 57 | Most of these things could be done in blender. Add Shadow is one of the more interesting tools: it is very efficient compared to duplicating vertices, duplicating meshes or even adding passes into multiple different shaders, and it allows you to make effectively a shader pass on a different queue. It's not trivial to do this in blender.\ 58 | \ 59 | Blend shape keyframing is probably by far the most interesting. The way to use it is you must import blendshapes named like this with _ or space and a percent.\ 60 | \ 61 | The following will generate a single blendshape called coolface that hits those keyframes on the way from 0 to 100. If you weight paint a prop to your main avatar mesh, this can allow for animations upon activating the prop from a gesture, without needing a whole animator setup 62 | > - coolface 10% 63 | > - coolface 30% 64 | > - coolface_50% 65 | > - coolface_100% 66 | 67 | You may need to run multiple tools depending on how your mesh is laid out, but Combine Mesh Siblings will get you most of the way. Make sure to disable the other meshes or delete them afterwards (will require Unpack Prefab). Also, Combine Same Material will help once you have merged meshes. 68 | 69 | 70 | # Other Contents 71 | 72 | * LyumaShader/DropShadowLite.shader: This renders a flat drop shadow behind the object. Usually used by making a duplicate of your material or mesh and applying this shader to the duplicate. It contains its own offset, so it is ok to apply to a SkinnedMeshRenderer of an existing armature. 73 | 74 | # Conclusion 75 | 76 | That's it for now. In the future, I may include screenshots, samples, etc. 77 | 78 | I also have a collection of GPU skinning examples in the `newshaderskin` branch. 79 | 80 | Also, check out my gists: https://gist.github.com/lyuma 81 | 82 | # Contact 83 | 84 | Feel free to contact me by opening an issue, Lyuma on Discord (#0781), or by email at xnlyuma@gmail.com 85 | -------------------------------------------------------------------------------- /Waifu2d/Waifu2d.cginc: -------------------------------------------------------------------------------- 1 | // Code to flatten an object to 2d. Original by Lyuma 2 | 3 | // Mathematicians beware! This file is littered with numerical stability hacks. 4 | // Be prepared to see lots of sign(X) * max(0.001, abs(X)) all over the place to avoid division by 0. 5 | 6 | #ifndef LYUMASHADER_WAIFU2D_CGINC_ 7 | #define LYUMASHADER_WAIFU2D_CGINC_ 8 | #include "UnityCG.cginc" 9 | 10 | #ifndef NO_UNIFORMS 11 | uniform float _2d_coef; 12 | uniform float _facing_coef; 13 | uniform float _lock2daxis_coef; 14 | uniform float _zcorrect_coef; 15 | #endif 16 | 17 | float nonzeroify(float inp) { 18 | return (step(0.0, inp) * 2. - 1.) * max(0.000001, abs(inp)); 19 | } 20 | 21 | 22 | #ifdef USING_STEREO_MATRICES 23 | static float3 realCameraPos = 0.5 * (unity_StereoWorldSpaceCameraPos[0] + unity_StereoWorldSpaceCameraPos[1]); //(mul(mvMat, float4(0., 0., 0., 1.))).xyz; //mvMat._14_24_34_44; 24 | static float3x3 cameraToWorld = 0.5 * (unity_StereoCameraToWorld[0] + unity_StereoCameraToWorld[1]); //(mul(mvMat, float4(0., 0., 0., 1.))).xyz; //mvMat._14_24_34_44; 25 | static float3 approxEyeDir = normalize((0.5 * mul(unity_StereoMatrixInvV[0], float4(0., 0., 1., 0.)) + 26 | 0.5 * mul(unity_StereoMatrixInvV[1], float4(0., 0., 1., 0.))).xyz); 27 | #else 28 | static float3 realCameraPos = _WorldSpaceCameraPos; //(mul(mvMat, float4(0., 0., 0., 1.))).xyz; //mvMat._14_24_34_44; 29 | static float3x3 cameraToWorld = (float3x3)unity_CameraToWorld; 30 | static float3 approxEyeDir = normalize(mul(UNITY_MATRIX_I_V, float4(0., 0., 1., 0.)).xyz); 31 | #endif 32 | static float3 objectPos = mul(unity_ObjectToWorld, float4(0., 0., 0., 1.)).xyz; 33 | 34 | static float3 cameraPosInObjectSpace = mul(unity_WorldToObject, float4(realCameraPos, 1)).xyz; 35 | static float3 targetCameraPosFacingVec = float3(sin(_facing_coef * 1.570796), 0, cos(_facing_coef * 1.570796)); 36 | static float3 targetCameraPos = mul(unity_ObjectToWorld, float4(targetCameraPosFacingVec * sign(dot(cameraPosInObjectSpace,targetCameraPosFacingVec)) * length(cameraPosInObjectSpace.xyz), 1)).xyz; 37 | // _plock_coef 38 | 39 | static float3 cameraPos = lerp(realCameraPos, targetCameraPos, min(_2d_coef * 4, 1) * _lock2daxis_coef); 40 | 41 | static float3 cameraToObj = (cameraPos - objectPos); // + float3(0., 0., 0.0001); 42 | //static float3 cameraToObj = float3(cameraToObjX.x, 0., nonzeroify(cameraToObjX.z)); 43 | static float2 cameraToObj2D = normalize(cameraToObj.xz); // FIXME: was normalize(cameraToObj).xz WHY? 44 | 45 | #if defined(VR_ONLY_2D) && !defined(USING_STEREO_MATRICES) 46 | static float desired_waifu_coef = 0.0; 47 | #else 48 | static float desired_waifu_coef = min(0.995, max(0.0, _2d_coef)); 49 | #endif 50 | static float waifu_coef = desired_waifu_coef; 51 | 52 | static float3 yAxis = float3(0,1,0); 53 | static float3 xAxis = float3(cameraToObj2D.y,0,cameraToObj2D.x); 54 | static float3 zAxis = float3(-cameraToObj2D.x,0,cameraToObj2D.y); 55 | 56 | // world in camera space: [xAxis yAxis zAxis cameraPos] 57 | static float4x4 myVMat = float4x4( 58 | xAxis.x, xAxis.y, xAxis.z, objectPos.x, 59 | yAxis.x, yAxis.y, yAxis.z, objectPos.y, 60 | zAxis.x, zAxis.y, zAxis.z, objectPos.z, 61 | 0., 0., 0., 1.); 62 | static float3x3 myInvVMat3x3 = float3x3( 63 | xAxis.x, yAxis.x, zAxis.x, 64 | xAxis.y, yAxis.y, zAxis.y, 65 | xAxis.z, yAxis.z, zAxis.z); 66 | 67 | static float3 invObjectPos = mul((float3x3)myInvVMat3x3, -objectPos); 68 | static float4x4 myInvVMat = float4x4( 69 | xAxis.x, yAxis.x, zAxis.x, invObjectPos.x, 70 | xAxis.y, yAxis.y, zAxis.y, invObjectPos.y, 71 | xAxis.z, yAxis.z, zAxis.z, invObjectPos.z, 72 | 0., 0., 0., 1.); 73 | 74 | //myInvVMat = inverse(myVMat); 75 | static float3 planeNormal = cross(xAxis, yAxis); 76 | static float approxAngle = atan2(planeNormal.z, planeNormal.x); 77 | static float discreteAngle = floor(approxAngle * 2.) / 2.; 78 | static float angleCorr = discreteAngle - approxAngle; 79 | 80 | static float3 approxEyeDirInObjectSpace = mul(unity_WorldToObject, float4(approxEyeDir, 0)).xyz; 81 | static float3 targetApproxEyeDir = mul(unity_ObjectToWorld, float4(0, 0, length(approxEyeDirInObjectSpace.xyz), 0)).xyz; 82 | static float3 approxCameraDir = float4((cameraPos.xz - objectPos.xz), 0., 1.).xzy; 83 | // was approxEyeDir not approxCameraDir but this changes rotation as you rotate... 84 | static float3 facingApproxEyeDir = normalize(lerp(approxCameraDir, targetApproxEyeDir, min(_lock2daxis_coef, _2d_coef))); 85 | 86 | static float2 eyeFacing = lerp(float2(1,0), facingApproxEyeDir.xz, _facing_coef); 87 | 88 | float4 waifu_computeWorldFlatWorldPos(float4 objToWorld) { 89 | float3 oPos = UnityWorldToViewPos(objToWorld.xyz).xyz; 90 | float4 unprojectedPos = mul(myInvVMat, objToWorld); 91 | float4 semiProjectedPos = float4(unprojectedPos.xyz, 1.); 92 | semiProjectedPos.z = 0.; 93 | float4 actualObjectPos = mul(myVMat, semiProjectedPos); 94 | actualObjectPos.y = objToWorld.y; /// MAD HAX - doesn't fix the problem :-p 95 | return actualObjectPos; 96 | } 97 | 98 | // inVertex: original model space vertex; 99 | float4 waifu_computeVertexWorldPos(float4 inVertex) { 100 | // START CRAZY PER VERTEX 101 | float4 objToWorld = mul(unity_ObjectToWorld, inVertex); 102 | float4 actualObjectPos = waifu_computeWorldFlatWorldPos(objToWorld); 103 | return waifu_coef * actualObjectPos + (1. - waifu_coef) * objToWorld; 104 | } 105 | 106 | float4 waifu_computeVertexLocalPos(float4 inVertex) { 107 | return mul(unity_WorldToObject, waifu_computeVertexWorldPos(inVertex)); 108 | } 109 | 110 | float4 waifu_projectVertex2(float4 vertexWorldPos, float4 origPos) { 111 | float4 oPos = UnityObjectToClipPos(origPos); 112 | if (waifu_coef <= 1.0e-6) { 113 | return oPos; 114 | } 115 | float4 newViewPos = mul(UNITY_MATRIX_V, vertexWorldPos); 116 | float4 newPos = mul(UNITY_MATRIX_P, newViewPos); 117 | newPos.z = lerp(sign(oPos.w * oPos.z * newPos.w) * max(0.00001, abs(oPos.z)) * max(0.00001, abs(newPos.w)) / max(0.00001, abs(oPos.w)), newPos.z, _zcorrect_coef); 118 | return newPos; 119 | // END CRAZY PER VERTEX 120 | } 121 | 122 | // Helper function. 123 | // inVertex: original model space vertex; 124 | // oPos: result of UnityObjectToClipPos(vertexWorldPos) 125 | 126 | float4 waifu_projectVertexWorldPos(float4 inVertex) { 127 | return waifu_projectVertex2(waifu_computeVertexWorldPos(inVertex), inVertex); 128 | } 129 | 130 | float4 waifu_projectVertexWorldPos(float3 inVertex) { 131 | return waifu_projectVertex2(waifu_computeVertexWorldPos(float4(inVertex, 1)), float4(inVertex, 1)); 132 | } 133 | 134 | float4 waifu_projectVertexFromWorldPos(float3 inVertex) { 135 | inVertex = mul(unity_WorldToObject, float4(inVertex, 1)).xyz; 136 | return waifu_projectVertex2(waifu_computeVertexWorldPos(float4(inVertex, 1)), float4(inVertex, 1)); 137 | } 138 | 139 | #ifdef LYUMA2D_HOTPATCH 140 | #define UnityObjectToClipPos waifu_projectVertexWorldPos 141 | #define UnityWorldToClipPos waifu_projectVertexFromWorldPos 142 | #undef TRANSFER_SHADOW_CASTER_NOPOS_LEGACY 143 | #undef TRANSFER_SHADOW_CASTER_NOPOS 144 | 145 | float4 waifu_ClipSpaceShadowCasterPos(float4 v, float3 n) { 146 | return UnityClipSpaceShadowCasterPos(waifu_computeVertexLocalPos(v), n); 147 | } 148 | float4 waifu_ClipSpaceShadowCasterPos(float3 v, float3 n) { 149 | return UnityClipSpaceShadowCasterPos(waifu_computeVertexLocalPos(float4(v, 1.0)), n); 150 | } 151 | #define UnityClipSpaceShadowCasterPos waifu_ClipSpaceShadowCasterPos 152 | 153 | #if defined(SHADOWS_CUBE) && !defined(SHADOWS_CUBE_IN_DEPTH_TEX) 154 | #define TRANSFER_SHADOW_CASTER_NOPOS_LEGACY(o,opos) float4 actualWorldPos = waifu_computeVertexWorldPos(v.vertex); o.vec = actualWorldPos.xyz - _LightPositionRange.xyz; opos = UnityWorldToClipPos(actualWorldPos); 155 | #define TRANSFER_SHADOW_CASTER_NOPOS(o,opos) TRANSFER_SHADOW_CASTER_NOPOS_LEGACY(o,opos) 156 | #else 157 | #define TRANSFER_SHADOW_CASTER_NOPOS_LEGACY(o,opos) \ 158 | opos = UnityObjectToClipPos(waifu_computeVertexLocalPos(v.vertex)); \ 159 | opos = UnityApplyLinearShadowBias(opos); 160 | #define TRANSFER_SHADOW_CASTER_NOPOS(o,opos) \ 161 | opos = waifu_ClipSpaceShadowCasterPos(v.vertex, v.normal); \ 162 | opos = UnityApplyLinearShadowBias(opos); 163 | #endif 164 | #endif 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /LyumaShader/StarNestAvatar.shader: -------------------------------------------------------------------------------- 1 | //Star Nest algorithm by Pablo Román Andrioli 2 | //Unity 5.x shader by Jonathan Cohen 3 | //Slightly degraded for performance and converted to world space by Lyuma. 4 | //This content is under the MIT License. 5 | // 6 | //Original Shader: 7 | //https://www.shadertoy.com/view/XlfGRj 8 | // 9 | //This shader uses the same algorithm in 3d space to render a skybox. 10 | 11 | Shader "LyumaShader/StarNestAvatar" { 12 | Properties { 13 | _Color ("Main Color", Color) = (1,1,1,1) 14 | 15 | [Toggle(CLAMPOUT)] _CLAMPOUT("Clamp Output with Main Color", Float) = 0 16 | 17 | //Scrolls in this direction over time. Set 'w' to zero to stop scrolling. 18 | _Scroll ("Scrolling direction (x,y,z) * w * time", Vector) = (1.3, 1, .6, .01) 19 | 20 | //Center position in space and time. 21 | _Center ("Center Position (x, y, z, time)", Vector) = (1, .3, .5, 0) 22 | 23 | //How much does camera position cause the effect to scroll? 24 | _CamScroll ("Camera Scroll", Float) = 0 25 | 26 | //Does rotation apply? 27 | _Rotation ("Rotation axis (x,y,z) * w * time", Vector) = (0, 0, 0, .01) 28 | 29 | //Iterations of inner loop. 30 | //The higher this is, the more distant objects get rendered. 31 | _Iterations ("Iterations", Range(1, 30)) = 5 32 | 33 | //Volumetric rendering steps. Each 'step' renders more objects at all distances. 34 | //This has a higher performance hit than iterations. 35 | _Volsteps ("Volumetric Steps", Range(1,20)) = 6 36 | 37 | //Magic number. Best values are around 400-600. 38 | _Formuparam ("Formuparam", Float) = 572 39 | 40 | //How much farther each volumestep goes 41 | _StepSize ("Step Size", Float) = 355 // 574 also good 42 | 43 | //Fractal repeating rate 44 | //Low numbers are busy and give lots of repititio 45 | //High numbers are very sparce 46 | _Tile ("Tile", Float) = 700 47 | 48 | //Brightness scale. 49 | _Brightness ("Brightness", Float) = .5 50 | //Abundance of Dark matter (in the distance). 51 | //Visible with Volsteps >= 8 (at 7 its really, really hard to see) 52 | _Darkmatter ("Dark Matter", Float) = 555 53 | //Brightness of distant objects (or dim) are distant objects 54 | //Ironically, Also affets brightness of 'darkmatter' 55 | _Distfading ("Distance Fading", Float) = 55 56 | //How much color is present? 57 | _Saturation ("Saturation", Float) = 77 58 | 59 | _MainTex("MainTex", 2D) = "white" {} 60 | } 61 | 62 | SubShader { 63 | Tags { "Queue"="Geometry" "RenderType"="Transparent" } 64 | Cull Off 65 | Blend SrcAlpha OneMinusSrcAlpha 66 | //ZWrite Off 67 | 68 | Pass { 69 | CGPROGRAM 70 | #pragma vertex vert 71 | #pragma fragment frag 72 | #pragma multi_compile __ CLAMPOUT 73 | #include "UnityCG.cginc" 74 | 75 | static const float kInnerRadius = 1.0; 76 | static const float kCameraHeight = 0.0001; 77 | 78 | fixed4 _Color; 79 | 80 | int _Volsteps; 81 | int _Iterations; 82 | 83 | float4 _Scroll; 84 | float4 _Center; 85 | float _CamScroll; 86 | float4 _Rotation; 87 | 88 | float _Formuparam; 89 | float _StepSize; 90 | 91 | float _Tile; 92 | 93 | float _Brightness; 94 | float _Darkmatter; 95 | float _Distfading; 96 | float _Saturation; 97 | 98 | sampler2D _MainTex; 99 | 100 | struct appdata_t { 101 | float4 vertex : POSITION; 102 | float4 uv0 : TEXCOORD0; 103 | }; 104 | struct v2f { 105 | float4 pos : SV_POSITION; 106 | float3 rayDir : TEXCOORD0; // Vector for incoming ray, normalized ( == -eyeRay ) 107 | float3 posWorld : TEXCOORD1; // Vector for incoming ray, normalized ( == -eyeRay ) 108 | float4 uv0 : TEXCOORD2; 109 | }; 110 | 111 | v2f vert(appdata_t v) { 112 | v2f OUT; 113 | OUT.posWorld = mul(unity_ObjectToWorld, v.vertex).xyz; 114 | OUT.pos = UnityObjectToClipPos(v.vertex); 115 | OUT.uv0 = v.uv0; 116 | float3 cameraPos = float3(0,kInnerRadius + kCameraHeight,0); // The camera's current position 117 | 118 | // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere) 119 | //float3 eyeRay = normalize(mul((float3x3)unity_ObjectToWorld, v.vertex.xyz)); 120 | ///////OUT.rayDir = half3(eyeRay); 121 | 122 | #if defined(USING_STEREO_MATRICES) 123 | OUT.rayDir = -(_WorldSpaceCameraPos.xyz - OUT.posWorld.xyz); 124 | #else 125 | OUT.rayDir = (_WorldSpaceCameraPos.xyz - OUT.posWorld.xyz); 126 | #endif 127 | //OUT.rayDir = mul(UNITY_MATRIX_I_V, float4(-1,1,1,0)*mul(UNITY_MATRIX_V, float4(_WorldSpaceCameraPos.xyz - OUT.posWorld.xyz, 0))).xyz; 128 | // = mul(UNITY_MATRIX_MV,float4(v.vertex.xyz, 0)); 129 | 130 | return OUT; 131 | } 132 | 133 | half4 frag (v2f IN) : SV_Target { 134 | half3 col = half3(0, 0, 0); 135 | float4 pos = IN.pos; 136 | float3 dir = normalize(IN.rayDir); // For some reason this has some imperfections... 137 | //float3 dir = normalize(_WorldSpaceCameraPos.xyz - IN.posWorld.xyz); 138 | //return half4(dir,1.); 139 | 140 | 141 | float time = _Center.w + 25 * _Time.x; 142 | 143 | //Un-scale parameters (source parameters for these are mostly in 0...1 range) 144 | //Scaling them up makes it much easier to fine-tune shader in the inspector. 145 | float brightness = _Brightness / 1000; 146 | float stepSize = _StepSize / 1000; 147 | float3 tile = abs(float3(_Tile, _Tile, _Tile)) / 1000; 148 | float formparam = _Formuparam / 1000; 149 | 150 | float darkmatter = _Darkmatter / 100; 151 | float distFade = _Distfading / 100 * (1.1+0.5*sin(_Time.x)); 152 | 153 | float3 from = _Center.xyz; 154 | 155 | //scroll over time 156 | from += _Scroll.xyz * _Scroll.w * time; 157 | //scroll from camera position 158 | from += _WorldSpaceCameraPos * _CamScroll * .00001; 159 | 160 | 161 | //Apply rotation if enabled 162 | float3 rot = _Rotation.xyz * _Rotation.w * time * .1; 163 | if (length(rot) > 0) { 164 | float2x2 rx = float2x2(cos(rot.x), sin(rot.x), -sin(rot.x), cos(rot.x)); 165 | float2x2 ry = float2x2(cos(rot.y), sin(rot.y), -sin(rot.y), cos(rot.y)); 166 | float2x2 rz = float2x2(cos(rot.z), sin(rot.z), -sin(rot.z), cos(rot.z)); 167 | 168 | dir.xy = mul(rz, dir.xy); 169 | dir.xz = mul(ry, dir.xz); 170 | dir.yz = mul(rx, dir.yz); 171 | from.xy = mul(rz, from.xy); 172 | from.xz = mul(ry, from.xz); 173 | from.yz = mul(rx, from.yz); 174 | } 175 | 176 | 177 | //volumetric rendering 178 | float s = 0.1, fade = 1.0*distFade*distFade; 179 | float3 v = float3(0, 0, 0)+1.+distFade+fade; 180 | for (int r = 3; r < _Volsteps; r++) { 181 | float3 p = abs(from + s * dir * .5); 182 | 183 | p = abs(float3(tile - fmod(p, tile*2))); 184 | float pa,a = pa = 0.; 185 | for (int i = 0; i < _Iterations; i++) { 186 | for (int j = 0; j < 3; j++) { 187 | p = abs(p) / dot(p, p) - formparam; 188 | a += abs(length(p) - pa); 189 | pa = length(p); 190 | } 191 | } 192 | //Dark matter 193 | float dm = max(0., darkmatter - a * a * .001); 194 | if (r > 6) { fade *= 1. - dm; } // Render distant darkmatter 195 | a *= a * a; //add contrast 196 | 197 | v += fade; 198 | 199 | // coloring based on distance 200 | v += float3(s, s*s, s*s*s*s) * a * brightness * fade; 201 | 202 | // distance fading 203 | fade *= distFade; 204 | s += stepSize; 205 | } 206 | 207 | float4 diffuse = tex2D(_MainTex, IN.uv0); 208 | return float4(v * 0.0025* (float3(0.5,.5,.5) + 0.5 * diffuse.xyz), diffuse.a);// * 0.03; 209 | 210 | float len = length(v); 211 | //Quick saturate 212 | v = lerp(float3(len, len, len), v, _Saturation / 100); 213 | v.xyz *= _Color.xyz * .01; 214 | 215 | #ifdef CLAMPOUT 216 | v = clamp(v, float3(0,0,0), _Color.xyz); 217 | #endif 218 | } 219 | 220 | 221 | 222 | 223 | ENDCG 224 | } 225 | 226 | 227 | } 228 | 229 | Fallback Off 230 | } 231 | -------------------------------------------------------------------------------- /Waifu2d/StandardSimple.shader: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | Shader "LyumaShader/StandardSimple" 4 | { 5 | Properties 6 | { 7 | _Color("Color", Color) = (1,1,1,1) 8 | _MainTex("Albedo", 2D) = "white" {} 9 | 10 | _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 11 | 12 | _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5 13 | _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 14 | [Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0 15 | 16 | [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 17 | _MetallicGlossMap("Metallic", 2D) = "white" {} 18 | 19 | [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 20 | [ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0 21 | 22 | _BumpScale("Scale", Float) = 1.0 23 | _BumpMap("Normal Map", 2D) = "bump" {} 24 | 25 | _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02 26 | _ParallaxMap ("Height Map", 2D) = "black" {} 27 | 28 | _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 29 | _OcclusionMap("Occlusion", 2D) = "white" {} 30 | 31 | _EmissionColor("Color", Color) = (0,0,0) 32 | _EmissionMap("Emission", 2D) = "white" {} 33 | 34 | _DetailMask("Detail Mask", 2D) = "white" {} 35 | 36 | _DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {} 37 | _DetailNormalMapScale("Scale", Float) = 1.0 38 | _DetailNormalMap("Normal Map", 2D) = "bump" {} 39 | 40 | [Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0 41 | 42 | 43 | // Blending state 44 | [HideInInspector] _Mode ("__mode", Float) = 0.0 45 | [HideInInspector] _SrcBlend ("__src", Float) = 1.0 46 | [HideInInspector] _DstBlend ("__dst", Float) = 0.0 47 | [HideInInspector] _ZWrite ("__zw", Float) = 1.0 48 | } 49 | 50 | CGINCLUDE 51 | #define UNITY_SETUP_BRDF_INPUT MetallicSetup 52 | ENDCG 53 | 54 | SubShader 55 | { 56 | Tags { "RenderType"="Opaque" "PerformanceChecks"="False" } 57 | LOD 300 58 | 59 | 60 | // ------------------------------------------------------------------ 61 | // Base forward pass (directional light, emission, lightmaps, ...) 62 | Pass 63 | { 64 | Name "FORWARD" 65 | Tags { "LightMode" = "ForwardBase" } 66 | 67 | Blend [_SrcBlend] [_DstBlend] 68 | ZWrite [_ZWrite] 69 | 70 | Cull Back 71 | 72 | CGPROGRAM 73 | #pragma target 3.0 74 | 75 | // ------------------------------------- 76 | 77 | #pragma shader_feature _NORMALMAP 78 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 79 | #pragma shader_feature _EMISSION 80 | #pragma shader_feature _METALLICGLOSSMAP 81 | #pragma shader_feature ___ _DETAIL_MULX2 82 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 83 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 84 | #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF 85 | #pragma shader_feature _PARALLAXMAP 86 | 87 | #pragma multi_compile_fwdbase 88 | #pragma multi_compile_fog 89 | #pragma multi_compile_instancing 90 | 91 | #pragma vertex vertBase 92 | #pragma fragment fragBase 93 | #include "UnityStandardCoreForward.cginc" 94 | 95 | ENDCG 96 | } 97 | // ------------------------------------------------------------------ 98 | // Additive forward pass (one light per pass) 99 | Pass 100 | { 101 | Name "FORWARD_DELTA" 102 | Tags { "LightMode" = "ForwardAdd" } 103 | Blend [_SrcBlend] One 104 | Fog { Color (0,0,0,0) } // in additive pass fog should be black 105 | ZWrite Off 106 | ZTest LEqual 107 | Cull Back 108 | 109 | CGPROGRAM 110 | #pragma target 3.0 111 | 112 | // ------------------------------------- 113 | 114 | 115 | #pragma shader_feature _NORMALMAP 116 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 117 | #pragma shader_feature _METALLICGLOSSMAP 118 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 119 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 120 | #pragma shader_feature ___ _DETAIL_MULX2 121 | #pragma shader_feature _PARALLAXMAP 122 | 123 | #pragma multi_compile_fwdadd_fullshadows 124 | #pragma multi_compile_fog 125 | 126 | #pragma vertex vertAdd 127 | #pragma fragment fragAdd 128 | #include "UnityStandardCoreForward.cginc" 129 | 130 | ENDCG 131 | } 132 | // ------------------------------------------------------------------ 133 | // Shadow rendering pass 134 | Pass { 135 | Name "ShadowCaster" 136 | Tags { "LightMode" = "ShadowCaster" } 137 | 138 | ZWrite On ZTest LEqual 139 | 140 | CGPROGRAM 141 | #pragma target 3.0 142 | 143 | // ------------------------------------- 144 | 145 | 146 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 147 | #pragma shader_feature _METALLICGLOSSMAP 148 | #pragma shader_feature _PARALLAXMAP 149 | #pragma multi_compile_shadowcaster 150 | #pragma multi_compile_instancing 151 | 152 | #pragma vertex vertShadowCaster 153 | #pragma fragment fragShadowCaster 154 | 155 | #include "UnityStandardShadow.cginc" 156 | 157 | ENDCG 158 | } 159 | // ------------------------------------------------------------------ 160 | // Deferred pass 161 | Pass 162 | { 163 | Name "DEFERRED" 164 | Tags { "LightMode" = "Deferred" } 165 | 166 | CGPROGRAM 167 | #pragma target 3.0 168 | #pragma exclude_renderers nomrt 169 | 170 | 171 | // ------------------------------------- 172 | 173 | #pragma shader_feature _NORMALMAP 174 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 175 | #pragma shader_feature _EMISSION 176 | #pragma shader_feature _METALLICGLOSSMAP 177 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 178 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 179 | #pragma shader_feature ___ _DETAIL_MULX2 180 | #pragma shader_feature _PARALLAXMAP 181 | 182 | #pragma multi_compile_prepassfinal 183 | #pragma multi_compile_instancing 184 | 185 | #pragma vertex vertDeferred 186 | #pragma fragment fragDeferred 187 | 188 | #include "UnityStandardCore.cginc" 189 | 190 | ENDCG 191 | } 192 | 193 | // ------------------------------------------------------------------ 194 | // Extracts information for lightmapping, GI (emission, albedo, ...) 195 | // This pass it not used during regular rendering. 196 | Pass 197 | { 198 | Name "META" 199 | Tags { "LightMode"="Meta" } 200 | 201 | Cull Back 202 | 203 | CGPROGRAM 204 | #pragma vertex vert_meta 205 | #pragma fragment frag_meta 206 | 207 | #pragma shader_feature _EMISSION 208 | #pragma shader_feature _METALLICGLOSSMAP 209 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 210 | #pragma shader_feature ___ _DETAIL_MULX2 211 | #pragma shader_feature EDITOR_VISUALIZATION 212 | 213 | #include "UnityStandardMeta.cginc" 214 | ENDCG 215 | } 216 | } 217 | 218 | SubShader 219 | { 220 | Tags { "RenderType"="Opaque" "PerformanceChecks"="False" } 221 | LOD 150 222 | 223 | // ------------------------------------------------------------------ 224 | // Base forward pass (directional light, emission, lightmaps, ...) 225 | Pass 226 | { 227 | Name "FORWARD" 228 | Tags { "LightMode" = "ForwardBase" } 229 | 230 | Blend [_SrcBlend] [_DstBlend] 231 | ZWrite [_ZWrite] 232 | Cull Back 233 | 234 | CGPROGRAM 235 | #pragma target 2.0 236 | 237 | #pragma shader_feature _NORMALMAP 238 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 239 | #pragma shader_feature _EMISSION 240 | #pragma shader_feature _METALLICGLOSSMAP 241 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 242 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 243 | #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF 244 | // SM2.0: NOT SUPPORTED shader_feature ___ _DETAIL_MULX2 245 | // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP 246 | 247 | #pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED 248 | 249 | #pragma multi_compile_fwdbase 250 | #pragma multi_compile_fog 251 | 252 | #pragma vertex vertBase 253 | #pragma fragment fragBase 254 | #include "UnityStandardCoreForward.cginc" 255 | 256 | ENDCG 257 | } 258 | // ------------------------------------------------------------------ 259 | // Additive forward pass (one light per pass) 260 | Pass 261 | { 262 | Name "FORWARD_DELTA" 263 | Tags { "LightMode" = "ForwardAdd" } 264 | Blend [_SrcBlend] One 265 | Fog { Color (0,0,0,0) } // in additive pass fog should be black 266 | ZWrite Off 267 | ZTest LEqual 268 | Cull Back 269 | 270 | CGPROGRAM 271 | #pragma target 2.0 272 | 273 | #pragma shader_feature _NORMALMAP 274 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 275 | #pragma shader_feature _METALLICGLOSSMAP 276 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 277 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 278 | #pragma shader_feature ___ _DETAIL_MULX2 279 | // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP 280 | #pragma skip_variants SHADOWS_SOFT 281 | 282 | #pragma multi_compile_fwdadd_fullshadows 283 | #pragma multi_compile_fog 284 | 285 | #pragma vertex vertAdd 286 | #pragma fragment fragAdd 287 | #include "UnityStandardCoreForward.cginc" 288 | 289 | ENDCG 290 | } 291 | // ------------------------------------------------------------------ 292 | // Shadow rendering pass 293 | Pass { 294 | Name "ShadowCaster" 295 | Tags { "LightMode" = "ShadowCaster" } 296 | 297 | ZWrite On ZTest LEqual 298 | 299 | CGPROGRAM 300 | #pragma target 2.0 301 | 302 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 303 | #pragma shader_feature _METALLICGLOSSMAP 304 | #pragma skip_variants SHADOWS_SOFT 305 | #pragma multi_compile_shadowcaster 306 | 307 | #pragma vertex vertShadowCaster 308 | #pragma fragment fragShadowCaster 309 | 310 | #include "UnityStandardShadow.cginc" 311 | 312 | ENDCG 313 | } 314 | 315 | // ------------------------------------------------------------------ 316 | // Extracts information for lightmapping, GI (emission, albedo, ...) 317 | // This pass it not used during regular rendering. 318 | Pass 319 | { 320 | Name "META" 321 | Tags { "LightMode"="Meta" } 322 | 323 | Cull Back 324 | 325 | CGPROGRAM 326 | #pragma vertex vert_meta 327 | #pragma fragment frag_meta 328 | 329 | #pragma shader_feature _EMISSION 330 | #pragma shader_feature _METALLICGLOSSMAP 331 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 332 | #pragma shader_feature ___ _DETAIL_MULX2 333 | #pragma shader_feature EDITOR_VISUALIZATION 334 | 335 | #include "UnityStandardMeta.cginc" 336 | ENDCG 337 | } 338 | } 339 | 340 | 341 | FallBack "VertexLit" 342 | CustomEditor "StandardShaderGUI" 343 | } 344 | -------------------------------------------------------------------------------- /Waifu2d/StandardSimple_2d.shader: -------------------------------------------------------------------------------- 1 | // AUTOGENERATED by LyumaShader Waifu2DGenerator at 2018-10-10T08:38:19! 2 | // Original source file: Assets/LyumaShader/Waifu2d/StandardSimple.shader 3 | // This shader will not update automatically. Please regenerate if you change the original. 4 | // WARNING: this shader uses relative includes. Unity might not recompile if Waifu2d.cginc changes. 5 | // If editing Waifu2d.cginc, force a recompile by adding a space in here or regenerating. 6 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 7 | 8 | Shader "LyumaShader/StandardSimple_2d" 9 | { 10 | Properties 11 | { 12 | // Waifu2d Properties: 13 | _2d_coef ("Twodimensionalness", Range(0, 1)) = 0.99 14 | _facing_coef ("Face in Profile", Range (-1, 1)) = 0.0 15 | _lock2daxis_coef ("Lock 2d Axis", Range (0, 1)) = 1.0 16 | _zcorrect_coef ("Squash Z (good=.975; 0=3d; 1=z-fight)", Float) = 0.975 17 | 18 | _Color("Color", Color) = (1,1,1,1) 19 | _MainTex("Albedo", 2D) = "white" {} 20 | 21 | _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 22 | 23 | _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5 24 | _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 25 | [Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0 26 | 27 | [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 28 | _MetallicGlossMap("Metallic", 2D) = "white" {} 29 | 30 | [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 31 | [ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0 32 | 33 | _BumpScale("Scale", Float) = 1.0 34 | _BumpMap("Normal Map", 2D) = "bump" {} 35 | 36 | _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02 37 | _ParallaxMap ("Height Map", 2D) = "black" {} 38 | 39 | _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 40 | _OcclusionMap("Occlusion", 2D) = "white" {} 41 | 42 | _EmissionColor("Color", Color) = (0,0,0) 43 | _EmissionMap("Emission", 2D) = "white" {} 44 | 45 | _DetailMask("Detail Mask", 2D) = "white" {} 46 | 47 | _DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {} 48 | _DetailNormalMapScale("Scale", Float) = 1.0 49 | _DetailNormalMap("Normal Map", 2D) = "bump" {} 50 | 51 | [Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0 52 | 53 | 54 | // Blending state 55 | [HideInInspector] _Mode ("__mode", Float) = 0.0 56 | [HideInInspector] _SrcBlend ("__src", Float) = 1.0 57 | [HideInInspector] _DstBlend ("__dst", Float) = 0.0 58 | [HideInInspector] _ZWrite ("__zw", Float) = 1.0 59 | } 60 | 61 | CGINCLUDE 62 | //Waifu2d Generated 63 | #define LYUMA2D_HOTPATCH 64 | #include "Waifu2d.cginc" 65 | #define UNITY_SETUP_BRDF_INPUT MetallicSetup 66 | ENDCG 67 | 68 | SubShader 69 | { 70 | Tags { "RenderType"="Opaque" "PerformanceChecks"="False" } 71 | LOD 300 72 | 73 | 74 | // ------------------------------------------------------------------ 75 | // Base forward pass (directional light, emission, lightmaps, ...) 76 | Pass 77 | { 78 | Name "FORWARD" 79 | Tags { "LightMode" = "ForwardBase" } 80 | 81 | Blend [_SrcBlend] [_DstBlend] 82 | ZWrite [_ZWrite] 83 | 84 | Cull Back 85 | 86 | CGPROGRAM 87 | #pragma target 3.0 88 | 89 | // ------------------------------------- 90 | 91 | #pragma shader_feature _NORMALMAP 92 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 93 | #pragma shader_feature _EMISSION 94 | #pragma shader_feature _METALLICGLOSSMAP 95 | #pragma shader_feature ___ _DETAIL_MULX2 96 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 97 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 98 | #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF 99 | #pragma shader_feature _PARALLAXMAP 100 | 101 | #pragma multi_compile_fwdbase 102 | #pragma multi_compile_fog 103 | #pragma multi_compile_instancing 104 | 105 | #pragma vertex vertBase 106 | #pragma fragment fragBase 107 | #include "UnityStandardCoreForward.cginc" 108 | 109 | ENDCG 110 | } 111 | // ------------------------------------------------------------------ 112 | // Additive forward pass (one light per pass) 113 | Pass 114 | { 115 | Name "FORWARD_DELTA" 116 | Tags { "LightMode" = "ForwardAdd" } 117 | Blend [_SrcBlend] One 118 | Fog { Color (0,0,0,0) } // in additive pass fog should be black 119 | ZWrite Off 120 | ZTest LEqual 121 | Cull Back 122 | 123 | CGPROGRAM 124 | #pragma target 3.0 125 | 126 | // ------------------------------------- 127 | 128 | 129 | #pragma shader_feature _NORMALMAP 130 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 131 | #pragma shader_feature _METALLICGLOSSMAP 132 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 133 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 134 | #pragma shader_feature ___ _DETAIL_MULX2 135 | #pragma shader_feature _PARALLAXMAP 136 | 137 | #pragma multi_compile_fwdadd_fullshadows 138 | #pragma multi_compile_fog 139 | 140 | #pragma vertex vertAdd 141 | #pragma fragment fragAdd 142 | #include "UnityStandardCoreForward.cginc" 143 | 144 | ENDCG 145 | } 146 | // ------------------------------------------------------------------ 147 | // Shadow rendering pass 148 | Pass { 149 | Name "ShadowCaster" 150 | Tags { "LightMode" = "ShadowCaster" } 151 | 152 | ZWrite On ZTest LEqual 153 | 154 | CGPROGRAM 155 | #pragma target 3.0 156 | 157 | // ------------------------------------- 158 | 159 | 160 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 161 | #pragma shader_feature _METALLICGLOSSMAP 162 | #pragma shader_feature _PARALLAXMAP 163 | #pragma multi_compile_shadowcaster 164 | #pragma multi_compile_instancing 165 | 166 | #pragma vertex vertShadowCaster 167 | #pragma fragment fragShadowCaster 168 | 169 | #include "UnityStandardShadow.cginc" 170 | 171 | ENDCG 172 | } 173 | // ------------------------------------------------------------------ 174 | // Deferred pass 175 | Pass 176 | { 177 | Name "DEFERRED" 178 | Tags { "LightMode" = "Deferred" } 179 | 180 | CGPROGRAM 181 | #pragma target 3.0 182 | #pragma exclude_renderers nomrt 183 | 184 | 185 | // ------------------------------------- 186 | 187 | #pragma shader_feature _NORMALMAP 188 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 189 | #pragma shader_feature _EMISSION 190 | #pragma shader_feature _METALLICGLOSSMAP 191 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 192 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 193 | #pragma shader_feature ___ _DETAIL_MULX2 194 | #pragma shader_feature _PARALLAXMAP 195 | 196 | #pragma multi_compile_prepassfinal 197 | #pragma multi_compile_instancing 198 | 199 | #pragma vertex vertDeferred 200 | #pragma fragment fragDeferred 201 | 202 | #include "UnityStandardCore.cginc" 203 | 204 | ENDCG 205 | } 206 | 207 | // ------------------------------------------------------------------ 208 | // Extracts information for lightmapping, GI (emission, albedo, ...) 209 | // This pass it not used during regular rendering. 210 | Pass 211 | { 212 | Name "META" 213 | Tags { "LightMode"="Meta" } 214 | 215 | Cull Back 216 | 217 | CGPROGRAM 218 | #pragma vertex vert_meta 219 | #pragma fragment frag_meta 220 | 221 | #pragma shader_feature _EMISSION 222 | #pragma shader_feature _METALLICGLOSSMAP 223 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 224 | #pragma shader_feature ___ _DETAIL_MULX2 225 | #pragma shader_feature EDITOR_VISUALIZATION 226 | 227 | #include "UnityStandardMeta.cginc" 228 | ENDCG 229 | } 230 | } 231 | 232 | SubShader 233 | { 234 | Tags { "RenderType"="Opaque" "PerformanceChecks"="False" } 235 | LOD 150 236 | 237 | // ------------------------------------------------------------------ 238 | // Base forward pass (directional light, emission, lightmaps, ...) 239 | Pass 240 | { 241 | Name "FORWARD" 242 | Tags { "LightMode" = "ForwardBase" } 243 | 244 | Blend [_SrcBlend] [_DstBlend] 245 | ZWrite [_ZWrite] 246 | Cull Back 247 | 248 | CGPROGRAM 249 | #pragma target 2.0 250 | 251 | #pragma shader_feature _NORMALMAP 252 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 253 | #pragma shader_feature _EMISSION 254 | #pragma shader_feature _METALLICGLOSSMAP 255 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 256 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 257 | #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF 258 | // SM2.0: NOT SUPPORTED shader_feature ___ _DETAIL_MULX2 259 | // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP 260 | 261 | #pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED 262 | 263 | #pragma multi_compile_fwdbase 264 | #pragma multi_compile_fog 265 | 266 | #pragma vertex vertBase 267 | #pragma fragment fragBase 268 | #include "UnityStandardCoreForward.cginc" 269 | 270 | ENDCG 271 | } 272 | // ------------------------------------------------------------------ 273 | // Additive forward pass (one light per pass) 274 | Pass 275 | { 276 | Name "FORWARD_DELTA" 277 | Tags { "LightMode" = "ForwardAdd" } 278 | Blend [_SrcBlend] One 279 | Fog { Color (0,0,0,0) } // in additive pass fog should be black 280 | ZWrite Off 281 | ZTest LEqual 282 | Cull Back 283 | 284 | CGPROGRAM 285 | #pragma target 2.0 286 | 287 | #pragma shader_feature _NORMALMAP 288 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 289 | #pragma shader_feature _METALLICGLOSSMAP 290 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 291 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 292 | #pragma shader_feature ___ _DETAIL_MULX2 293 | // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP 294 | #pragma skip_variants SHADOWS_SOFT 295 | 296 | #pragma multi_compile_fwdadd_fullshadows 297 | #pragma multi_compile_fog 298 | 299 | #pragma vertex vertAdd 300 | #pragma fragment fragAdd 301 | #include "UnityStandardCoreForward.cginc" 302 | 303 | ENDCG 304 | } 305 | // ------------------------------------------------------------------ 306 | // Shadow rendering pass 307 | Pass { 308 | Name "ShadowCaster" 309 | Tags { "LightMode" = "ShadowCaster" } 310 | 311 | ZWrite On ZTest LEqual 312 | 313 | CGPROGRAM 314 | #pragma target 2.0 315 | 316 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 317 | #pragma shader_feature _METALLICGLOSSMAP 318 | #pragma skip_variants SHADOWS_SOFT 319 | #pragma multi_compile_shadowcaster 320 | 321 | #pragma vertex vertShadowCaster 322 | #pragma fragment fragShadowCaster 323 | 324 | #include "UnityStandardShadow.cginc" 325 | 326 | ENDCG 327 | } 328 | 329 | // ------------------------------------------------------------------ 330 | // Extracts information for lightmapping, GI (emission, albedo, ...) 331 | // This pass it not used during regular rendering. 332 | Pass 333 | { 334 | Name "META" 335 | Tags { "LightMode"="Meta" } 336 | 337 | Cull Back 338 | 339 | CGPROGRAM 340 | #pragma vertex vert_meta 341 | #pragma fragment frag_meta 342 | 343 | #pragma shader_feature _EMISSION 344 | #pragma shader_feature _METALLICGLOSSMAP 345 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 346 | #pragma shader_feature ___ _DETAIL_MULX2 347 | #pragma shader_feature EDITOR_VISUALIZATION 348 | 349 | #include "UnityStandardMeta.cginc" 350 | ENDCG 351 | } 352 | } 353 | 354 | 355 | FallBack "VertexLit" 356 | // CustomEditor "StandardShaderGUI" 357 | } 358 | -------------------------------------------------------------------------------- /Waifu2d/Editor/Waifu2dGenerator.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.IO; 4 | using System; 5 | 6 | namespace LyumaShader { 7 | public class Waifu2dGenerator : ScriptableObject { 8 | // Use a #include instead of pasting in code. 9 | const bool USE_INCLUDE = false; 10 | 11 | //[MenuItem ("Tools/Lyuma Waifu2d")] 12 | //MenuItem("GameObject/Create Mesh") 13 | [MenuItem ("CONTEXT/Material/Make 2d (Lyuma Waifu2d)")] 14 | static void Waifu2dMaterial (MenuCommand command) 15 | { 16 | Material m = command.context as Material; 17 | Shader newShader = Waifu2d (m.shader, false); 18 | if (newShader != null) { 19 | Undo.RecordObject(m, "Waifu2d: Switch Shader to 2d"); 20 | m.shader = newShader; 21 | } 22 | } 23 | 24 | [MenuItem ("CONTEXT/Shader/Generate 2d waifu (Lyuma Waifu2d)")] 25 | static void Waifu2dShader (MenuCommand command) 26 | { 27 | Shader s = command.context as Shader; 28 | Shader newS = Waifu2d (s, false); 29 | EditorGUIUtility.PingObject (newS); 30 | } 31 | 32 | [MenuItem ("CONTEXT/Material/Revert to 3d (Lyuma Waifu2d)")] 33 | static void WaifuRevert2dMaterial (MenuCommand command) 34 | { 35 | Material m = command.context as Material; 36 | string path = AssetDatabase.GetAssetPath (m.shader); 37 | if (path.StartsWith ("Resources/unity_builtin_extra", StringComparison.CurrentCulture)) { 38 | return; 39 | } 40 | string shaderName = m.shader.name; 41 | string [] shaderData = File.ReadAllLines (path); 42 | string origPath = ""; 43 | foreach (string xline in shaderData) { 44 | string line = xline; 45 | if (line.IndexOf("Original source file:") != -1 && origPath.Length == 0) { 46 | origPath = line.Substring(line.IndexOf(":") + 1).Trim(); 47 | } 48 | if (line.IndexOf ("Waifu2d Generated", StringComparison.CurrentCulture) != -1) { 49 | if (origPath.Length == 0) { 50 | origPath = path.Replace ("_vr2d.shader", ".shader").Replace ("_2d.shader", ".shader"); 51 | } 52 | String origShaderName = shaderName.Replace ("_vr2d", "").Replace("_2d", ""); 53 | Shader origShader = AssetDatabase.LoadAssetAtPath(origPath); 54 | if (origShader == null) { 55 | origShader = Shader.Find(origShaderName); 56 | } 57 | if (origShader == null) { 58 | EditorUtility.DisplayDialog ("Waifu2d", "Cannot find the original shader " + origShaderName + " at " + origPath, "OK", ""); 59 | } else { 60 | Undo.RecordObject(m, "Waifu2d: Revert Shader to 3d"); 61 | Debug.Log("original shader " + origShaderName + " at " + origPath, origShader); 62 | m.shader = origShader; 63 | } 64 | break; 65 | } 66 | } 67 | } 68 | 69 | static Shader Waifu2d (Shader s, bool vr2d) 70 | { 71 | string shaderName = s.name; 72 | string path = AssetDatabase.GetAssetPath (s); 73 | Debug.Log ("Starting to work on shader " + shaderName); 74 | Debug.Log ("Original path: " + path); 75 | if (path.StartsWith ("Resources/unity_builtin_extra", StringComparison.CurrentCulture) && "Standard".Equals (s.name)) { 76 | string [] tmpassets = AssetDatabase.FindAssets ("StandardSimple"); 77 | foreach (string guid in tmpassets) { 78 | path = AssetDatabase.GUIDToAssetPath (guid); 79 | if (path.IndexOf (".shader", StringComparison.CurrentCulture) != -1) { 80 | break; 81 | } 82 | } 83 | } 84 | return Waifu2dPath (path, shaderName, vr2d, vr2d ? "_vr2d" : "_2d"); 85 | } 86 | 87 | static Shader Waifu2dPath(string path, string shaderName, bool vr2d, string shaderSuffix) { 88 | string [] shaderData = File.ReadAllLines (path); 89 | int state = 0; 90 | int comment = 0; 91 | int braceLevel = 0; 92 | int lineNum = -1; 93 | int beginPropertiesLineNum = -1; 94 | int beginPropertiesSkip = -1; 95 | int endPropertiesLineNum = -1; 96 | int endPropertiesSkip = -1; 97 | bool foundCgInclude = false; 98 | bool foundNoCgInclude = false; 99 | int cgIncludeLineNum = -1; 100 | int cgIncludeSkip = -1; 101 | int editShaderNameLineNum = -1; 102 | int editShaderNameSkip = -1; 103 | bool isOpenQuote = false; 104 | bool CisOpenQuote = false; 105 | foreach (string xline in shaderData) { 106 | string line = xline; 107 | if (line.IndexOf ("Waifu2d Generated", StringComparison.CurrentCulture) != -1) { 108 | String origPath = path.Replace ("_vr2d.shader", ".shader").Replace ("_2d.shader", ".shader"); 109 | String origShaderName = shaderName.Replace ("_vr2d", "").Replace("_2d", ""); 110 | if (EditorUtility.DisplayDialog ("Waifu2d", "Detected an existing Waifu2d comment: Regenrate from " + origShaderName + "?", "Regenerate", "Cancel")) { 111 | if (path.Equals(origPath) || shaderName.Equals(origShaderName)) { 112 | EditorUtility.DisplayDialog ("Waifu2d", "Unable to find name of original shader for " + shaderName, "OK", ""); 113 | return null; 114 | } 115 | return Waifu2dPath (origPath, origShaderName, vr2d, shaderSuffix); 116 | } else { 117 | return null; 118 | } 119 | } 120 | lineNum++; 121 | int lineSkip = 0; 122 | while (true) { 123 | //Debug.Log ("Looking for comment " + lineNum); 124 | int commentIdx; 125 | if (comment == 1) { 126 | commentIdx = line.IndexOf ("*/", lineSkip, StringComparison.CurrentCulture); 127 | if (commentIdx != -1) { 128 | lineSkip = commentIdx + 2; 129 | comment = 0; 130 | } else { 131 | line = ""; 132 | break; 133 | } 134 | } 135 | int openQuote = line.IndexOf ("\"", lineSkip, StringComparison.CurrentCulture); 136 | if (CisOpenQuote) { 137 | if (openQuote == -1) { 138 | //Debug.Log("C-Open quote ignore " + lineSkip); 139 | break; 140 | } else { 141 | lineSkip = openQuote + 1; 142 | CisOpenQuote = false; 143 | } 144 | //Debug.Log("C-Open quote end " + lineSkip); 145 | continue; 146 | } 147 | commentIdx = line.IndexOf ("//", lineSkip, StringComparison.CurrentCulture); 148 | int commentIdx2 = line.IndexOf ("/*", lineSkip, StringComparison.CurrentCulture); 149 | if (openQuote != -1 && (openQuote < commentIdx || commentIdx == -1) && (openQuote < commentIdx2 || commentIdx2 == -1)) { 150 | CisOpenQuote = true; 151 | lineSkip = openQuote + 1; 152 | //Debug.Log("C-Open quote start " + lineSkip); 153 | continue; 154 | } 155 | if (commentIdx != -1) { 156 | line = line.Substring (0, commentIdx); 157 | break; 158 | } 159 | commentIdx = commentIdx2; 160 | if (commentIdx != -1) { 161 | int endCommentIdx = line.IndexOf ("*/", lineSkip, StringComparison.CurrentCulture); 162 | if (endCommentIdx != -1) { 163 | line = line.Substring (0, commentIdx) + new String (' ', (endCommentIdx + 2 - commentIdx)) + line.Substring (endCommentIdx + 2); 164 | lineSkip = endCommentIdx + 2; 165 | } else { 166 | line = line.Substring (0, commentIdx); 167 | comment = 1; 168 | break; 169 | } 170 | } else { 171 | break; 172 | } 173 | } 174 | lineSkip = 0; 175 | bool fallThrough = true; 176 | while (fallThrough) { 177 | //Debug.Log ("Looking for state " + state + " on line " + lineNum); 178 | fallThrough = false; 179 | switch (state) { 180 | case 0: { 181 | int shaderOff = line.IndexOf ("Shader", lineSkip, StringComparison.CurrentCulture); 182 | if (shaderOff != -1) { 183 | int firstQuote = line.IndexOf ('\"', shaderOff); 184 | int secondQuote = line.IndexOf ('\"', firstQuote + 1); 185 | if (firstQuote != -1 && secondQuote != -1) { 186 | editShaderNameLineNum = lineNum; 187 | editShaderNameSkip = secondQuote; 188 | state = 1; 189 | } 190 | } 191 | } 192 | break; 193 | case 1: { 194 | // Find beginning of Properties block 195 | int shaderOff = line.IndexOf ("Properties", lineSkip, StringComparison.CurrentCulture); 196 | if (shaderOff != -1) { 197 | state = 2; 198 | lineSkip = shaderOff; 199 | fallThrough = true; 200 | } 201 | } 202 | break; 203 | case 2: { 204 | // Find end of Properties block 205 | while (lineSkip < line.Length) { 206 | int openQuote = line.IndexOf ("\"", lineSkip, StringComparison.CurrentCulture); 207 | if (isOpenQuote) { 208 | if (openQuote == -1) { 209 | //Debug.Log("Open quote ignore " + lineSkip); 210 | break; 211 | } else { 212 | lineSkip = openQuote + 1; 213 | isOpenQuote = false; 214 | } 215 | //Debug.Log("Open quote end " + lineSkip); 216 | continue; 217 | } 218 | int openBrace = line.IndexOf ("{", lineSkip, StringComparison.CurrentCulture); 219 | int closeBrace = line.IndexOf ("}", lineSkip, StringComparison.CurrentCulture); 220 | if (openQuote != -1 && (openQuote < openBrace || openBrace == -1) && (openQuote < closeBrace || closeBrace == -1)) { 221 | isOpenQuote = true; 222 | lineSkip = openQuote + 1; 223 | //Debug.Log("Open quote start " + lineSkip); 224 | continue; 225 | } 226 | //Debug.Log ("Looking for braces state " + state + " on line " + lineNum + "/" + lineSkip + " {}" + braceLevel + " open:" + openBrace + "/ close:" + closeBrace + "/ quote:" + openQuote); 227 | if (closeBrace != -1 && (openBrace > closeBrace || openBrace == -1)) { 228 | braceLevel--; 229 | if (braceLevel == 0) { 230 | endPropertiesLineNum = lineNum; 231 | endPropertiesSkip = closeBrace; 232 | state = 3; 233 | fallThrough = true; 234 | } 235 | lineSkip = closeBrace + 1; 236 | } else if (openBrace != -1 && (openBrace < closeBrace || closeBrace == -1)) { 237 | if (braceLevel == 0) { 238 | beginPropertiesLineNum = lineNum; 239 | beginPropertiesSkip = openBrace + 1; 240 | } 241 | braceLevel++; 242 | lineSkip = openBrace + 1; 243 | } else { 244 | break; 245 | } 246 | } 247 | } 248 | break; 249 | case 3: { 250 | // Find beginning of CGINCLUDE block, or beginning of a Pass or CGPROGRAM 251 | int cgInclude = line.IndexOf ("CGINCLUDE", lineSkip, StringComparison.CurrentCulture); 252 | int cgProgram = line.IndexOf ("CGPROGRAM", lineSkip, StringComparison.CurrentCulture); 253 | int passBlock = line.IndexOf ("GrabPass", lineSkip, StringComparison.CurrentCulture); 254 | int grabPassBlock = line.IndexOf ("Pass", lineSkip, StringComparison.CurrentCulture); 255 | if (cgInclude != -1) { 256 | foundCgInclude = true; 257 | } else if (cgProgram != -1) { 258 | foundNoCgInclude = true; 259 | } else if (grabPassBlock != -1) { 260 | foundNoCgInclude = true; 261 | } else if (passBlock != -1) { 262 | if (passBlock == lineSkip || char.IsWhiteSpace (line [passBlock - 1])) { 263 | if (passBlock + 4 == line.Length || char.IsWhiteSpace (line [passBlock + 4])) { 264 | foundNoCgInclude = true; 265 | } 266 | } 267 | } 268 | if (foundCgInclude) { 269 | state = 4; 270 | cgIncludeLineNum = lineNum + 1; 271 | cgIncludeSkip = 0; 272 | } else if (foundNoCgInclude) { 273 | state = 4; 274 | cgIncludeLineNum = lineNum; 275 | cgIncludeSkip = lineSkip; 276 | } 277 | } 278 | break; 279 | case 4: 280 | // Look for modified tag, or end of shader, or custom editor. 281 | break; 282 | } 283 | } 284 | if (state == 5) { 285 | break; 286 | } 287 | } 288 | Debug.Log ("Done with hard work"); 289 | if (editShaderNameLineNum == -1) { 290 | EditorUtility.DisplayDialog ("Waifu2d", "In " + shaderName + ": failed to find Shader \"...\" block.", "OK", ""); 291 | // Failed to parse shader; 292 | return null; 293 | } 294 | if (endPropertiesLineNum == -1) { 295 | EditorUtility.DisplayDialog ("Waifu2d", "In " + shaderName + ": failed to find end of Properties block.", "OK", ""); 296 | // Failed to parse shader; 297 | return null; 298 | } 299 | if (cgIncludeLineNum == -1) { 300 | EditorUtility.DisplayDialog ("Waifu2d", "In " + shaderName + ": failed to find CGINCLUDE or appropriate insertion point.", "OK", ""); 301 | // Failed to parse shader; 302 | return null; 303 | } 304 | 305 | string [] shader2dassets = AssetDatabase.FindAssets ("Waifu2d.cginc"); 306 | string includePath = "LyumaShader/Waifu2d/Waifu2d.cginc"; 307 | foreach (string guid in shader2dassets) { 308 | Debug.Log ("testI: " + AssetDatabase.GUIDToAssetPath (guid)); 309 | includePath = AssetDatabase.GUIDToAssetPath (guid); 310 | if (!includePath.Contains ("Waifu2d.cginc")) { 311 | continue; 312 | } 313 | if (!includePath.StartsWith ("Assets/", StringComparison.CurrentCulture)) { 314 | EditorUtility.DisplayDialog ("Waifu2d", "This script at path " + includePath + " must be in Assets!", "OK", ""); 315 | return null; 316 | } 317 | includePath = includePath.Substring (7); 318 | break; 319 | } 320 | Debug.Log("Including code from " + includePath); 321 | string cgincCode = File.ReadAllText("Assets/" + includePath); 322 | int numSlashes = 0; 323 | if (!path.StartsWith ("Assets/", StringComparison.CurrentCulture)) { 324 | EditorUtility.DisplayDialog ("Waifu2d", "Shader " + shaderName + " at path " + path + " must be in Assets!", "OK", ""); 325 | return null; 326 | } 327 | string includePrefix = ""; 328 | Debug.Log("path is " + path); 329 | foreach (char c in path.Substring (7)) { 330 | if (c == '/') { 331 | numSlashes++; 332 | includePrefix += "../"; 333 | } 334 | } 335 | includePath = includePrefix + includePath; 336 | if (foundCgInclude) { 337 | string cgIncludeLine = shaderData [cgIncludeLineNum]; 338 | string cgIncludeAdd = "//Waifu2d Generated\n#define LYUMA2D_HOTPATCH\n"; 339 | if (vr2d) { 340 | cgIncludeAdd += "#define VR_ONLY_2D 1\n"; 341 | } 342 | if (USE_INCLUDE) { 343 | cgIncludeAdd += "#include \"" + includePath + "\"\n"; 344 | } else { 345 | cgIncludeAdd += cgincCode.Replace("\r\n", "\n"); 346 | } 347 | shaderData [cgIncludeLineNum] = cgIncludeAdd + cgIncludeLine; 348 | } else { 349 | string cgIncludeLine = shaderData [cgIncludeLineNum]; 350 | string cgIncludeAdd = "\nCGINCLUDE\n//Waifu2d Generated Block\n#define LYUMA2D_HOTPATCH\n"; 351 | if (vr2d) { 352 | cgIncludeAdd += "#define VR_ONLY_2D 1\n"; 353 | } 354 | if (USE_INCLUDE) { 355 | cgIncludeAdd += "# include \"" + includePath + "\"\n"; 356 | } else { 357 | cgIncludeAdd += cgincCode.Replace("\r\n", "\n"); 358 | } 359 | cgIncludeAdd += "ENDCG\n"; 360 | shaderData [cgIncludeLineNum] = cgIncludeLine.Substring (0, cgIncludeSkip) + cgIncludeAdd + cgIncludeLine.Substring (cgIncludeSkip); 361 | } 362 | 363 | string epLine = shaderData [beginPropertiesLineNum]; 364 | string propertiesAdd = "\n" + 365 | " // Waifu2d Properties::\n" + 366 | " _2d_coef (\"Twodimensionalness\", Range(0, 1)) = 0.99\n" + 367 | " _facing_coef (\"Face in Profile\", Range (-1, 1)) = 0.0\n" + 368 | " _lock2daxis_coef (\"Lock 2d Axis\", Range (0, 1)) = " + (vr2d ? "0.0" : "1.0") + "\n" + 369 | " _zcorrect_coef (\"Squash Z (good=.975; 0=3d; 1=z-fight)\", Float) = " + (vr2d ? "0.0" : "0.975") + "\n"; 370 | epLine = epLine.Substring (0, beginPropertiesSkip) + propertiesAdd + epLine.Substring (beginPropertiesSkip); 371 | shaderData [beginPropertiesLineNum] = epLine; 372 | 373 | string shaderLine = shaderData [editShaderNameLineNum]; 374 | shaderLine = shaderLine.Substring (0, editShaderNameSkip) + shaderSuffix + shaderLine.Substring (editShaderNameSkip); 375 | shaderData [editShaderNameLineNum] = shaderLine; 376 | 377 | String dest = path.Replace (".shader", shaderSuffix + ".txt"); 378 | String finalDest = path.Replace (".shader", shaderSuffix + ".shader"); 379 | if (dest.Equals (path)) { 380 | EditorUtility.DisplayDialog ("Waifu2d", "Shader " + shaderName + " at path " + path + " does not have .shader!", "OK", ""); 381 | return null; 382 | } 383 | Debug.Log ("Writing shader " + dest); 384 | Debug.Log ("Shader name" + shaderName + shaderSuffix); 385 | Debug.Log ("Original path " + path + " name " + shaderName); 386 | StreamWriter writer = new StreamWriter (dest, false); 387 | writer.NewLine = "\n"; 388 | writer.WriteLine ("// AUTOGENERATED by LyumaShader Waifu2DGenerator at " + DateTime.UtcNow.ToString ("s") + "!"); 389 | writer.WriteLine ("// Original source file: " + path); 390 | writer.WriteLine ("// This shader will not update automatically. Please regenerate if you change the original."); 391 | writer.WriteLine ("// WARNING: this shader uses relative includes. Unity might not recompile if Waifu2d.cginc changes."); 392 | writer.WriteLine ("// If editing Waifu2d.cginc, force a recompile by adding a space in here or regenerating."); 393 | for (int i = 0; i < shaderData.Length; i++) { 394 | if (shaderData [i].IndexOf ("CustomEditor", StringComparison.CurrentCulture) != -1) { 395 | writer.WriteLine ("//" + shaderData [i]); 396 | } else { 397 | writer.WriteLine (shaderData [i]); 398 | } 399 | } 400 | writer.Close (); 401 | FileUtil.ReplaceFile (dest, finalDest); 402 | try { 403 | FileUtil.DeleteFileOrDirectory (dest); 404 | } catch (Exception e) { 405 | } 406 | //FileUtil.MoveFileOrDirectory (dest, finalDest); 407 | AssetDatabase.ImportAsset (finalDest); 408 | return (Shader)AssetDatabase.LoadAssetAtPath (finalDest, typeof (Shader)); 409 | } 410 | } 411 | } 412 | -------------------------------------------------------------------------------- /LyumaShader/Editor/LyumaMeshTools.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | #if UNITY_EDITOR 8 | public class LyumaMeshTools : EditorWindow { 9 | 10 | [MenuItem ("CONTEXT/Mesh/\u2014\u2014LyumaMeshTools\u2014\u2014", true)] 11 | [MenuItem ("CONTEXT/MeshFilter/\u2014\u2014LyumaMeshTools\u2014\u2014", true)] 12 | [MenuItem ("CONTEXT/MeshRenderer/\u2014\u2014LyumaMeshTools\u2014\u2014", true)] 13 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/\u2014\u2014LyumaMeshTools\u2014\u2014", true)] 14 | public static bool LyumaMeshToolsVal (MenuCommand command) { 15 | return false; 16 | } 17 | 18 | [MenuItem ("CONTEXT/Mesh/\u2014\u2014LyumaMeshTools\u2014\u2014", false, 130)] 19 | [MenuItem ("CONTEXT/MeshFilter/\u2014\u2014LyumaMeshTools\u2014\u2014", false, 130)] 20 | [MenuItem ("CONTEXT/MeshRenderer/\u2014\u2014LyumaMeshTools\u2014\u2014", false, 130)] 21 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/\u2014\u2014LyumaMeshTools\u2014\u2014", false, 130)] 22 | public static void LyumaMeshToolsAct (MenuCommand command) {} 23 | 24 | 25 | [MenuItem ("CONTEXT/Mesh/Vertex position to UV2 : LMT", false, 131)] 26 | [MenuItem ("CONTEXT/MeshFilter/Vertex position to UV2 : LMT", false, 131)] 27 | [MenuItem ("CONTEXT/MeshRenderer/Vertex position to UV2 : LMT", false, 131)] 28 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Vertex position to UV2 : LMT", false, 131)] 29 | public static void RunBakeWorldPos (MenuCommand command) 30 | { 31 | Mesh sourcePositionMesh; 32 | Mesh sourceMesh; 33 | SkinnedMeshRenderer smr = null; 34 | MeshRenderer mr = null; 35 | MeshFilter mf = null; 36 | if (command.context is SkinnedMeshRenderer) { 37 | smr = command.context as SkinnedMeshRenderer; 38 | sourceMesh = smr.sharedMesh; 39 | sourcePositionMesh = new Mesh(); 40 | smr.BakeMesh(sourcePositionMesh); 41 | } else if (command.context is MeshRenderer) { 42 | mr = command.context as MeshRenderer; 43 | mf = mr.transform.GetComponent (); 44 | sourceMesh = mf.sharedMesh; 45 | sourcePositionMesh = sourceMesh; 46 | } else if (command.context is MeshFilter) { 47 | mf = command.context as MeshFilter; 48 | sourceMesh = mf.sharedMesh; 49 | sourcePositionMesh = sourceMesh; 50 | } else if (command.context is Mesh) { 51 | sourceMesh = command.context as Mesh; 52 | sourcePositionMesh = sourceMesh; 53 | } else { 54 | EditorUtility.DisplayDialog ("MergeUVs", "Unknkown context type " + command.context.GetType ().FullName, "OK", ""); 55 | throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName); 56 | } 57 | Mesh newMesh = new Mesh (); 58 | int size = sourceMesh.vertices.Length; 59 | List srcUV = new List(); 60 | List srcUV3 = new List(); 61 | List srcUV4 = new List(); 62 | sourceMesh.GetUVs (0, srcUV); 63 | sourceMesh.GetUVs (2, srcUV3); 64 | sourceMesh.GetUVs (3, srcUV4); 65 | Vector3 [] srcPosVertices = sourcePositionMesh.vertices; 66 | Vector3 [] srcVertices = sourceMesh.vertices; 67 | Color [] srcColors = sourceMesh.colors; // FIXME: Should use colors? 68 | Vector3 [] srcNormals = sourceMesh.normals; 69 | Vector4 [] srcTangents = sourceMesh.tangents; 70 | Matrix4x4 [] srcBindposes = sourceMesh.bindposes; 71 | BoneWeight [] srcBoneWeights = sourceMesh.boneWeights; 72 | var newUV2 = new Vector4[size]; 73 | for (int i = 0; i < size; i++) { 74 | newUV2 [i] = new Vector4 (srcPosVertices[i].x, srcPosVertices[i].y, srcPosVertices[i].z, 0); 75 | } 76 | newMesh.vertices = srcVertices; 77 | if (srcNormals != null && srcNormals.Length > 0) { 78 | newMesh.normals = srcNormals; 79 | } 80 | if (srcTangents != null && srcTangents.Length > 0) { 81 | newMesh.tangents = srcTangents; 82 | } 83 | if (srcBoneWeights != null && srcBoneWeights.Length > 0) { 84 | newMesh.boneWeights = srcBoneWeights; 85 | } 86 | if (srcColors != null && srcColors.Length > 0) { 87 | newMesh.colors = srcColors; 88 | } 89 | if (srcUV.Count > 0) { 90 | newMesh.SetUVs (0, srcUV); 91 | } 92 | newMesh.SetUVs(1, new List(newUV2)); 93 | if (srcUV3.Count > 0) { 94 | newMesh.SetUVs (2, srcUV3); 95 | } 96 | if (srcUV4.Count > 0) { 97 | newMesh.SetUVs (3, srcUV4); 98 | } 99 | newMesh.subMeshCount = sourceMesh.subMeshCount; 100 | for (int i = 0; i < sourceMesh.subMeshCount; i++) { 101 | var curIndices = sourceMesh.GetIndices (i); 102 | newMesh.SetIndices (curIndices, sourceMesh.GetTopology(i), i); 103 | } 104 | newMesh.bounds = sourceMesh.bounds; 105 | if (srcBindposes != null && srcBindposes.Length > 0) { 106 | newMesh.bindposes = sourceMesh.bindposes; 107 | } 108 | for (int i = 0; i < sourceMesh.blendShapeCount; i++) { 109 | var blendShapeName = sourceMesh.GetBlendShapeName (i); 110 | var blendShapeFrameCount = sourceMesh.GetBlendShapeFrameCount (i); 111 | for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 112 | float weight = sourceMesh.GetBlendShapeFrameWeight(i, frameIndex); 113 | Vector3 [] deltaVertices = new Vector3 [size]; 114 | Vector3 [] deltaNormals = new Vector3 [size]; 115 | Vector3 [] deltaTangents = new Vector3 [size]; 116 | sourceMesh.GetBlendShapeFrameVertices (i, frameIndex, deltaVertices, deltaNormals, deltaTangents); 117 | newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents); 118 | } 119 | } 120 | newMesh.name = sourceMesh.name + "_uvmerged"; 121 | Mesh meshAfterUpdate = newMesh; 122 | if (smr != null) { 123 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to merged UVs"); 124 | smr.sharedMesh = newMesh; 125 | meshAfterUpdate = smr.sharedMesh; 126 | // No need to change smr.bones: should use same bone indices and blendshapes. 127 | } 128 | if (mf != null) { 129 | Undo.RecordObject (mf, "Switched MeshFilter to merged UVs"); 130 | mf.sharedMesh = newMesh; 131 | meshAfterUpdate = mf.sharedMesh; 132 | } 133 | string pathToGenerated = "Assets" + "/Generated"; 134 | if (!Directory.Exists (pathToGenerated)) { 135 | Directory.CreateDirectory (pathToGenerated); 136 | } 137 | string fileName = pathToGenerated + "/ZZmergeuvs_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 138 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 139 | AssetDatabase.SaveAssets (); 140 | } 141 | 142 | 143 | [MenuItem ("CONTEXT/Mesh/Merge UV and UV2 : LMT", false, 131)] 144 | [MenuItem ("CONTEXT/MeshFilter/Merge UV and UV2 : LMT", false, 131)] 145 | [MenuItem ("CONTEXT/MeshRenderer/Merge UV and UV2 : LMT", false, 131)] 146 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Merge UV and UV2 : LMT", false, 131)] 147 | public static void RunMergeUVs (MenuCommand command) 148 | { 149 | Mesh sourceMesh; 150 | SkinnedMeshRenderer smr = null; 151 | MeshRenderer mr = null; 152 | MeshFilter mf = null; 153 | if (command.context is SkinnedMeshRenderer) { 154 | smr = command.context as SkinnedMeshRenderer; 155 | sourceMesh = smr.sharedMesh; 156 | } else if (command.context is MeshRenderer) { 157 | mr = command.context as MeshRenderer; 158 | mf = mr.transform.GetComponent (); 159 | sourceMesh = mf.sharedMesh; 160 | } else if (command.context is MeshFilter) { 161 | mf = command.context as MeshFilter; 162 | sourceMesh = mf.sharedMesh; 163 | } else if (command.context is Mesh) { 164 | sourceMesh = command.context as Mesh; 165 | } else { 166 | EditorUtility.DisplayDialog ("MergeUVs", "Unknkown context type " + command.context.GetType ().FullName, "OK", ""); 167 | throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName); 168 | } 169 | Mesh newMesh = new Mesh (); 170 | int size = sourceMesh.vertices.Length; 171 | List srcUV = new List(); // will discard zw 172 | List srcUV2 = new List(); // will discard zw 173 | List srcUV3 = new List(); 174 | List srcUV4 = new List(); 175 | sourceMesh.GetUVs (0, srcUV); 176 | sourceMesh.GetUVs (1, srcUV2); 177 | sourceMesh.GetUVs (2, srcUV3); 178 | sourceMesh.GetUVs (3, srcUV4); 179 | if (srcUV.Count == 0) { 180 | EditorUtility.DisplayDialog ("MergeUVs", "Source mesh has no UV!", "OK", ""); 181 | return; 182 | } 183 | if (srcUV2.Count == 0) { 184 | EditorUtility.DisplayDialog ("MergeUVs", "Source mesh has no UV2!", "OK", ""); 185 | return; 186 | } 187 | Vector3 [] srcVertices = sourceMesh.vertices; 188 | Color [] srcColors = sourceMesh.colors; // FIXME: Should use colors? 189 | Vector3 [] srcNormals = sourceMesh.normals; 190 | Vector4 [] srcTangents = sourceMesh.tangents; 191 | Matrix4x4 [] srcBindposes = sourceMesh.bindposes; 192 | BoneWeight [] srcBoneWeights = sourceMesh.boneWeights; 193 | var newUV1 = new Vector4[size]; 194 | for (int i = 0; i < size; i++) { 195 | Vector2 uv1 = srcUV [i]; 196 | Vector2 uv2 = srcUV2 [i]; 197 | newUV1 [i] = new Vector4 (uv1.x, uv1.y, uv2.x, uv2.y); 198 | } 199 | newMesh.vertices = srcVertices; 200 | if (srcNormals != null && srcNormals.Length > 0) { 201 | newMesh.normals = srcNormals; 202 | } 203 | if (srcTangents != null && srcTangents.Length > 0) { 204 | newMesh.tangents = srcTangents; 205 | } 206 | if (srcBoneWeights != null && srcBoneWeights.Length > 0) { 207 | newMesh.boneWeights = srcBoneWeights; 208 | } 209 | if (srcColors != null && srcColors.Length > 0) { 210 | newMesh.colors = srcColors; 211 | } 212 | newMesh.SetUVs(0, new List(newUV1)); 213 | if (srcUV3.Count > 0) { 214 | newMesh.SetUVs (2, srcUV3); 215 | } 216 | if (srcUV4.Count > 0) { 217 | newMesh.SetUVs (3, srcUV4); 218 | } 219 | newMesh.subMeshCount = sourceMesh.subMeshCount; 220 | for (int i = 0; i < sourceMesh.subMeshCount; i++) { 221 | var curIndices = sourceMesh.GetIndices (i); 222 | newMesh.SetIndices (curIndices, sourceMesh.GetTopology(i), i); 223 | } 224 | newMesh.bounds = sourceMesh.bounds; 225 | if (srcBindposes != null && srcBindposes.Length > 0) { 226 | newMesh.bindposes = sourceMesh.bindposes; 227 | } 228 | for (int i = 0; i < sourceMesh.blendShapeCount; i++) { 229 | var blendShapeName = sourceMesh.GetBlendShapeName (i); 230 | var blendShapeFrameCount = sourceMesh.GetBlendShapeFrameCount (i); 231 | for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 232 | float weight = sourceMesh.GetBlendShapeFrameWeight(i, frameIndex); 233 | Vector3 [] deltaVertices = new Vector3 [size]; 234 | Vector3 [] deltaNormals = new Vector3 [size]; 235 | Vector3 [] deltaTangents = new Vector3 [size]; 236 | sourceMesh.GetBlendShapeFrameVertices (i, frameIndex, deltaVertices, deltaNormals, deltaTangents); 237 | newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents); 238 | } 239 | } 240 | newMesh.name = sourceMesh.name + "_uvmerged"; 241 | Mesh meshAfterUpdate = newMesh; 242 | if (smr != null) { 243 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to merged UVs"); 244 | smr.sharedMesh = newMesh; 245 | meshAfterUpdate = smr.sharedMesh; 246 | // No need to change smr.bones: should use same bone indices and blendshapes. 247 | } 248 | if (mf != null) { 249 | Undo.RecordObject (mf, "Switched MeshFilter to merged UVs"); 250 | mf.sharedMesh = newMesh; 251 | meshAfterUpdate = mf.sharedMesh; 252 | } 253 | string pathToGenerated = "Assets" + "/Generated"; 254 | if (!Directory.Exists (pathToGenerated)) { 255 | Directory.CreateDirectory (pathToGenerated); 256 | } 257 | string fileName = pathToGenerated + "/ZZmergeuvs_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 258 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 259 | AssetDatabase.SaveAssets (); 260 | } 261 | [MenuItem ("CONTEXT/Mesh/Assetize Meshes : LMT", false, 131)] 262 | [MenuItem ("CONTEXT/MeshFilter/Assetize Meshes : LMT", false, 131)] 263 | [MenuItem ("CONTEXT/MeshRenderer/Assetize Meshes : LMT", false, 131)] 264 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Assetize Meshes : LMT", false, 131)] 265 | public static void RunAssetizeMeshes (MenuCommand command) 266 | { 267 | Mesh sourceMesh; 268 | SkinnedMeshRenderer smr = null; 269 | MeshRenderer mr = null; 270 | MeshFilter mf = null; 271 | Transform trans = null; 272 | string parentName = ""; 273 | if (command.context is SkinnedMeshRenderer) { 274 | smr = command.context as SkinnedMeshRenderer; 275 | trans = smr.transform; 276 | sourceMesh = smr.sharedMesh; 277 | } else if (command.context is MeshRenderer) { 278 | mr = command.context as MeshRenderer; 279 | mf = mr.transform.GetComponent (); 280 | trans = mr.transform; 281 | sourceMesh = mf.sharedMesh; 282 | } else if (command.context is MeshFilter) { 283 | mf = command.context as MeshFilter; 284 | trans = mf.transform; 285 | sourceMesh = mf.sharedMesh; 286 | } else if (command.context is Mesh) { 287 | sourceMesh = command.context as Mesh; 288 | } else { 289 | EditorUtility.DisplayDialog ("MergeUVs", "Unknkown context type " + command.context.GetType ().FullName, "OK", ""); 290 | throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName); 291 | } 292 | if (trans != null) { 293 | // Get name of top-most object this mesh is attached to 294 | while (trans.parent != null) { 295 | trans = trans.parent; 296 | } 297 | parentName = trans.name + "_"; 298 | } 299 | parentName += sourceMesh.name; 300 | Mesh newMesh = new Mesh (); 301 | int size = sourceMesh.vertices.Length; 302 | List srcUV = new List(); 303 | List srcUV2 = new List(); 304 | List srcUV3 = new List(); 305 | List srcUV4 = new List(); 306 | sourceMesh.GetUVs (0, srcUV); 307 | sourceMesh.GetUVs (1, srcUV2); 308 | sourceMesh.GetUVs (2, srcUV3); 309 | sourceMesh.GetUVs (3, srcUV4); 310 | Vector3 [] srcVertices = sourceMesh.vertices; 311 | Color [] srcColors = sourceMesh.colors; // Forces to half precision? 312 | Vector3 [] srcNormals = sourceMesh.normals; 313 | Vector4 [] srcTangents = sourceMesh.tangents; 314 | Matrix4x4 [] srcBindposes = sourceMesh.bindposes; 315 | BoneWeight [] srcBoneWeights = sourceMesh.boneWeights; 316 | newMesh.vertices = srcVertices; 317 | if (srcNormals != null && srcNormals.Length > 0) { 318 | newMesh.normals = srcNormals; 319 | } 320 | if (srcTangents != null && srcTangents.Length > 0) { 321 | newMesh.tangents = srcTangents; 322 | } 323 | if (srcBoneWeights != null && srcBoneWeights.Length > 0) { 324 | newMesh.boneWeights = srcBoneWeights; 325 | } 326 | if (srcColors != null && srcColors.Length > 0) { 327 | newMesh.colors = srcColors; 328 | } 329 | if (srcUV.Count > 0) { 330 | newMesh.SetUVs (0, srcUV); 331 | } 332 | if (srcUV2.Count > 0) { 333 | newMesh.SetUVs (1, srcUV2); 334 | } 335 | if (srcUV3.Count > 0) { 336 | newMesh.SetUVs (2, srcUV3); 337 | } 338 | if (srcUV4.Count > 0) { 339 | newMesh.SetUVs (3, srcUV4); 340 | } 341 | newMesh.subMeshCount = sourceMesh.subMeshCount; 342 | for (int i = 0; i < sourceMesh.subMeshCount; i++) { 343 | var curIndices = sourceMesh.GetIndices (i); 344 | newMesh.SetIndices (curIndices, sourceMesh.GetTopology(i), i); 345 | } 346 | newMesh.bounds = sourceMesh.bounds; 347 | if (srcBindposes != null && srcBindposes.Length > 0) { 348 | newMesh.bindposes = sourceMesh.bindposes; 349 | } 350 | for (int i = 0; i < sourceMesh.blendShapeCount; i++) { 351 | var blendShapeName = sourceMesh.GetBlendShapeName (i); 352 | var blendShapeFrameCount = sourceMesh.GetBlendShapeFrameCount (i); 353 | for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 354 | float weight = sourceMesh.GetBlendShapeFrameWeight(i, frameIndex); 355 | Vector3 [] deltaVertices = new Vector3 [size]; 356 | Vector3 [] deltaNormals = new Vector3 [size]; 357 | Vector3 [] deltaTangents = new Vector3 [size]; 358 | sourceMesh.GetBlendShapeFrameVertices (i, frameIndex, deltaVertices, deltaNormals, deltaTangents); 359 | newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents); 360 | } 361 | } 362 | newMesh.name = sourceMesh.name + "_uvmerged"; 363 | Mesh meshAfterUpdate = newMesh; 364 | if (smr != null) { 365 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to merged UVs"); 366 | smr.sharedMesh = newMesh; 367 | meshAfterUpdate = smr.sharedMesh; 368 | // No need to change smr.bones: should use same bone indices and blendshapes. 369 | } 370 | if (mf != null) { 371 | Undo.RecordObject (mf, "Switched MeshFilter to merged UVs"); 372 | mf.sharedMesh = newMesh; 373 | meshAfterUpdate = mf.sharedMesh; 374 | } 375 | string pathToGenerated = "Assets" + "/Generated"; 376 | if (!Directory.Exists (pathToGenerated)) { 377 | Directory.CreateDirectory (pathToGenerated); 378 | } 379 | int lastSlash = parentName.LastIndexOf ('/'); 380 | string outFileName = lastSlash == -1 ? parentName : parentName.Substring (lastSlash + 1); 381 | outFileName = outFileName.Split ('.') [0]; 382 | string fileName = pathToGenerated + "/" + outFileName + "_assetized_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 383 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 384 | AssetDatabase.SaveAssets (); 385 | if (smr == null && mf == null) { 386 | EditorGUIUtility.PingObject (meshAfterUpdate); 387 | } 388 | } 389 | 390 | [MenuItem ("CONTEXT/Mesh/Add Shadow : LMT", false, 131)] 391 | [MenuItem ("CONTEXT/MeshFilter/Add Shadow : LMT", false, 131)] 392 | [MenuItem ("CONTEXT/MeshRenderer/Add Shadow : LMT", false, 131)] 393 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Add Shadow : LMT", false, 131)] 394 | public static void RunAddShadow (MenuCommand command) 395 | { 396 | Mesh sourceMesh; 397 | SkinnedMeshRenderer smr = null; 398 | MeshRenderer mr = null; 399 | MeshFilter mf = null; 400 | Transform trans = null; 401 | string parentName = ""; 402 | if (command.context is SkinnedMeshRenderer) { 403 | smr = command.context as SkinnedMeshRenderer; 404 | trans = smr.transform; 405 | sourceMesh = smr.sharedMesh; 406 | } else if (command.context is MeshRenderer) { 407 | mr = command.context as MeshRenderer; 408 | mf = mr.transform.GetComponent (); 409 | trans = mr.transform; 410 | sourceMesh = mf.sharedMesh; 411 | } else if (command.context is MeshFilter) { 412 | mf = command.context as MeshFilter; 413 | trans = mf.transform; 414 | sourceMesh = mf.sharedMesh; 415 | } else if (command.context is Mesh) { 416 | sourceMesh = command.context as Mesh; 417 | } else { 418 | EditorUtility.DisplayDialog ("MergeUVs", "Unknkown context type " + command.context.GetType ().FullName, "OK", ""); 419 | throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName); 420 | } 421 | if (trans != null) { 422 | // Get name of top-most object this mesh is attached to 423 | while (trans.parent != null) { 424 | trans = trans.parent; 425 | } 426 | parentName = trans.name + "_"; 427 | } 428 | parentName += sourceMesh.name; 429 | Mesh newMesh = new Mesh (); 430 | int size = sourceMesh.vertices.Length; 431 | List srcUV = new List (); // will discard zw 432 | List srcUV2 = new List (); // will discard zw 433 | List srcUV3 = new List (); 434 | List srcUV4 = new List (); 435 | sourceMesh.GetUVs (0, srcUV); 436 | sourceMesh.GetUVs (1, srcUV2); 437 | sourceMesh.GetUVs (2, srcUV3); 438 | sourceMesh.GetUVs (3, srcUV4); 439 | Vector3 [] srcVertices = sourceMesh.vertices; 440 | Color [] srcColors = sourceMesh.colors; // Forces to half precision? 441 | Vector3 [] srcNormals = sourceMesh.normals; 442 | Vector4 [] srcTangents = sourceMesh.tangents; 443 | Matrix4x4 [] srcBindposes = sourceMesh.bindposes; 444 | BoneWeight [] srcBoneWeights = sourceMesh.boneWeights; 445 | newMesh.vertices = srcVertices; 446 | if (srcNormals != null && srcNormals.Length > 0) { 447 | newMesh.normals = srcNormals; 448 | } 449 | if (srcTangents != null && srcTangents.Length > 0) { 450 | newMesh.tangents = srcTangents; 451 | } 452 | if (srcBoneWeights != null && srcBoneWeights.Length > 0) { 453 | newMesh.boneWeights = srcBoneWeights; 454 | } 455 | if (srcColors != null && srcColors.Length > 0) { 456 | newMesh.colors = srcColors; 457 | } 458 | if (srcUV.Count > 0) { 459 | newMesh.SetUVs (0, srcUV); 460 | } 461 | if (srcUV2.Count > 0) { 462 | newMesh.SetUVs (1, srcUV2); 463 | } 464 | if (srcUV3.Count > 0) { 465 | newMesh.SetUVs (2, srcUV3); 466 | } 467 | if (srcUV4.Count > 0) { 468 | newMesh.SetUVs (3, srcUV4); 469 | } 470 | newMesh.subMeshCount = sourceMesh.subMeshCount + 1; 471 | List allIndices = new List (); 472 | for (int i = 0; i < sourceMesh.subMeshCount; i++) { 473 | var curIndices = sourceMesh.GetIndices (i); 474 | if (sourceMesh.GetTopology (i) == MeshTopology.Triangles) { 475 | allIndices.AddRange (curIndices); 476 | } 477 | newMesh.SetIndices (curIndices, sourceMesh.GetTopology (i), i); 478 | } 479 | newMesh.SetIndices (allIndices.ToArray(), MeshTopology.Triangles, sourceMesh.subMeshCount); 480 | newMesh.bounds = sourceMesh.bounds; 481 | if (srcBindposes != null && srcBindposes.Length > 0) { 482 | newMesh.bindposes = sourceMesh.bindposes; 483 | } 484 | for (int i = 0; i < sourceMesh.blendShapeCount; i++) { 485 | var blendShapeName = sourceMesh.GetBlendShapeName (i); 486 | var blendShapeFrameCount = sourceMesh.GetBlendShapeFrameCount (i); 487 | for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 488 | float weight = sourceMesh.GetBlendShapeFrameWeight (i, frameIndex); 489 | Vector3 [] deltaVertices = new Vector3 [size]; 490 | Vector3 [] deltaNormals = new Vector3 [size]; 491 | Vector3 [] deltaTangents = new Vector3 [size]; 492 | sourceMesh.GetBlendShapeFrameVertices (i, frameIndex, deltaVertices, deltaNormals, deltaTangents); 493 | newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents); 494 | } 495 | } 496 | newMesh.name = sourceMesh.name + "_shadow"; 497 | Mesh meshAfterUpdate = newMesh; 498 | if (smr != null) { 499 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to shadow"); 500 | smr.sharedMesh = newMesh; 501 | meshAfterUpdate = smr.sharedMesh; 502 | // No need to change smr.bones: should use same bone indices and blendshapes. 503 | } 504 | if (mf != null) { 505 | Undo.RecordObject (mf, "Switched MeshFilter to shadow"); 506 | mf.sharedMesh = newMesh; 507 | meshAfterUpdate = mf.sharedMesh; 508 | } 509 | string pathToGenerated = "Assets" + "/Generated"; 510 | if (!Directory.Exists (pathToGenerated)) { 511 | Directory.CreateDirectory (pathToGenerated); 512 | } 513 | int lastSlash = parentName.LastIndexOf ('/'); 514 | string outFileName = lastSlash == -1 ? parentName : parentName.Substring (lastSlash + 1); 515 | outFileName = outFileName.Split ('.') [0]; 516 | string fileName = pathToGenerated + "/" + outFileName + "_shadow_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 517 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 518 | AssetDatabase.SaveAssets (); 519 | if (smr == null && mf == null) { 520 | EditorGUIUtility.PingObject (meshAfterUpdate); 521 | } 522 | } 523 | 524 | [MenuItem ("CONTEXT/Mesh/Combine same material : LMT [Requires renderer]", true)] 525 | [MenuItem ("CONTEXT/MeshFilter/Combine same material : LMT [Requires renderer]", true)] 526 | public static bool RunCombineSameMaterialVal (MenuCommand command) { 527 | return false; 528 | } 529 | 530 | [MenuItem ("CONTEXT/Mesh/Combine same material : LMT [Requires renderer]", false, 131)] 531 | [MenuItem ("CONTEXT/MeshFilter/Combine same material : LMT [Requires renderer]", false, 131)] 532 | [MenuItem ("CONTEXT/MeshRenderer/Combine same material : LMT", false, 131)] 533 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Combine same material : LMT", false, 131)] 534 | public static void RunCombineSameMaterial (MenuCommand command) 535 | { 536 | Mesh sourceMesh; 537 | SkinnedMeshRenderer smr = null; 538 | MeshRenderer mr = null; 539 | MeshFilter mf = null; 540 | Transform trans = null; 541 | string parentName = ""; 542 | if (command.context is SkinnedMeshRenderer) { 543 | smr = command.context as SkinnedMeshRenderer; 544 | trans = smr.transform; 545 | sourceMesh = smr.sharedMesh; 546 | } else if (command.context is MeshRenderer) { 547 | mr = command.context as MeshRenderer; 548 | mf = mr.transform.GetComponent (); 549 | trans = mr.transform; 550 | sourceMesh = mf.sharedMesh; 551 | } else { 552 | EditorUtility.DisplayDialog ("CombineSameMaterial", "Must have a renderer", "OK", ""); 553 | throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName); 554 | } 555 | if (trans != null) { 556 | // Get name of top-most object this mesh is attached to 557 | while (trans.parent != null) { 558 | trans = trans.parent; 559 | } 560 | parentName = trans.name + "_"; 561 | } 562 | Dictionary materialToIndex = new Dictionary (); 563 | List finalMaterials = new List(); 564 | Dictionary> materialToSubmesh = new Dictionary> (); 565 | int subi = 0; 566 | foreach (Material mat in mr == null ? smr.sharedMaterials : mr.sharedMaterials) { 567 | if (!materialToIndex.ContainsKey(mat)) { 568 | materialToIndex [mat] = finalMaterials.Count; 569 | finalMaterials.Add (mat); 570 | materialToSubmesh.Add (mat, new List ()); 571 | } 572 | materialToSubmesh [mat].Add (subi); 573 | subi++; 574 | } 575 | parentName += sourceMesh.name; 576 | Mesh newMesh = new Mesh (); 577 | int size = sourceMesh.vertices.Length; 578 | newMesh.indexFormat = sourceMesh.indexFormat == UnityEngine.Rendering.IndexFormat.UInt32 || size > 65535 ? UnityEngine.Rendering.IndexFormat.UInt32 : UnityEngine.Rendering.IndexFormat.UInt16; 579 | List srcUV = new List (); // will discard zw 580 | List srcUV2 = new List (); // will discard zw 581 | List srcUV3 = new List (); 582 | List srcUV4 = new List (); 583 | sourceMesh.GetUVs (0, srcUV); 584 | sourceMesh.GetUVs (1, srcUV2); 585 | sourceMesh.GetUVs (2, srcUV3); 586 | sourceMesh.GetUVs (3, srcUV4); 587 | Vector3 [] srcVertices = sourceMesh.vertices; 588 | Color [] srcColors = sourceMesh.colors; // Forces to half precision? 589 | Vector3 [] srcNormals = sourceMesh.normals; 590 | Vector4 [] srcTangents = sourceMesh.tangents; 591 | Matrix4x4 [] srcBindposes = sourceMesh.bindposes; 592 | BoneWeight [] srcBoneWeights = sourceMesh.boneWeights; 593 | 594 | newMesh.vertices = srcVertices; 595 | if (srcNormals != null && srcNormals.Length > 0) { 596 | newMesh.normals = srcNormals; 597 | } 598 | if (srcTangents != null && srcTangents.Length > 0) { 599 | newMesh.tangents = srcTangents; 600 | } 601 | if (srcBoneWeights != null && srcBoneWeights.Length > 0) { 602 | newMesh.boneWeights = srcBoneWeights; 603 | } 604 | if (srcColors != null && srcColors.Length > 0) { 605 | newMesh.colors = srcColors; 606 | } 607 | if (srcUV.Count > 0) { 608 | newMesh.SetUVs (0, srcUV); 609 | } 610 | if (srcUV2.Count > 0) { 611 | newMesh.SetUVs (1, srcUV2); 612 | } 613 | if (srcUV3.Count > 0) { 614 | newMesh.SetUVs (2, srcUV3); 615 | } 616 | if (srcUV4.Count > 0) { 617 | newMesh.SetUVs (3, srcUV4); 618 | } 619 | newMesh.subMeshCount = finalMaterials.Count; 620 | for (int i = 0; i < newMesh.subMeshCount; i++) { 621 | List curIndices = new List (); 622 | MeshTopology topo = sourceMesh.GetTopology(materialToSubmesh[finalMaterials[i]][0]); 623 | int minidx = -1; 624 | foreach (int thisIndex in materialToSubmesh [finalMaterials[i]]) { 625 | if (sourceMesh.GetTopology (thisIndex) == topo) { 626 | int[] newind = sourceMesh.GetIndices (thisIndex); 627 | /* 628 | uint offset = sourceMesh.GetBaseVertex(thisIndex); 629 | for (int idx = 0; idx < newind.Length; idx++) { 630 | newind[idx] += (int)offset; 631 | if (newind[idx] < minidx || minidx == -1) { 632 | minidx = newind[idx]; 633 | } 634 | } 635 | */ 636 | curIndices.AddRange (newind); 637 | } 638 | } 639 | /* 640 | int curl = curIndices.Count; 641 | int maxidx = 0; 642 | for (int idx = 0; idx < curl; idx++) { 643 | curIndices[idx] -= minidx; 644 | if (curIndices[idx] > maxidx) { 645 | maxidx = curIndices[idx]; 646 | } 647 | } 648 | if (maxidx > 32767 && newMesh.indexFormat != UnityEngine.Rendering.IndexFormat.UInt32) { 649 | GetIndices = UnityEngine.Rendering.IndexFormat.UInt32; 650 | } 651 | */ 652 | newMesh.SetIndices (curIndices.ToArray(), topo, i, true); 653 | } 654 | newMesh.bounds = sourceMesh.bounds; 655 | if (srcBindposes != null && srcBindposes.Length > 0) { 656 | newMesh.bindposes = sourceMesh.bindposes; 657 | } 658 | for (int i = 0; i < sourceMesh.blendShapeCount; i++) { 659 | var blendShapeName = sourceMesh.GetBlendShapeName (i); 660 | var blendShapeFrameCount = sourceMesh.GetBlendShapeFrameCount (i); 661 | for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 662 | float weight = sourceMesh.GetBlendShapeFrameWeight (i, frameIndex); 663 | Vector3 [] deltaVertices = new Vector3 [size]; 664 | Vector3 [] deltaNormals = new Vector3 [size]; 665 | Vector3 [] deltaTangents = new Vector3 [size]; 666 | sourceMesh.GetBlendShapeFrameVertices (i, frameIndex, deltaVertices, deltaNormals, deltaTangents); 667 | newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents); 668 | } 669 | } 670 | newMesh.name = sourceMesh.name + "_combinemat"; 671 | Mesh meshAfterUpdate = newMesh; 672 | if (smr != null) { 673 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to shadow"); 674 | smr.sharedMesh = newMesh; 675 | smr.sharedMaterials = finalMaterials.ToArray(); 676 | meshAfterUpdate = smr.sharedMesh; 677 | // No need to change smr.bones: should use same bone indices and blendshapes. 678 | } 679 | if (mf != null) { 680 | Undo.RecordObject (mf, "Switched MeshFilter to combinemat"); 681 | mf.sharedMesh = newMesh; 682 | meshAfterUpdate = mf.sharedMesh; 683 | } 684 | string pathToGenerated = "Assets" + "/Generated"; 685 | if (!Directory.Exists (pathToGenerated)) { 686 | Directory.CreateDirectory (pathToGenerated); 687 | } 688 | int lastSlash = parentName.LastIndexOf ('/'); 689 | string outFileName = lastSlash == -1 ? parentName : parentName.Substring (lastSlash + 1); 690 | outFileName = outFileName.Split ('.') [0]; 691 | string fileName = pathToGenerated + "/" + outFileName + "_combinemat_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 692 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 693 | AssetDatabase.SaveAssets (); 694 | if (smr == null && mf == null) { 695 | EditorGUIUtility.PingObject (meshAfterUpdate); 696 | } 697 | } 698 | 699 | static float uvOffset = 0; 700 | 701 | [MenuItem ("CONTEXT/Mesh/Make Skinned Parent+Child : LMT", true)] 702 | [MenuItem ("CONTEXT/MeshRenderer/Make Skinned : LMT [use MeshFilter]", true)] 703 | public static bool RunMakeSkinnedVal (MenuCommand command) { 704 | return false; 705 | } 706 | 707 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Make Skinned Parent+Child : LMT", false, 131)] 708 | [MenuItem ("CONTEXT/Mesh/Make Skinned Parent+Child : LMT", false, 131)] 709 | [MenuItem ("CONTEXT/MeshFilter/Make Skinned Parent+Child : LMT", false, 131)] 710 | [MenuItem ("CONTEXT/MeshRenderer/Make Skinned : LMT [use MeshFilter]", false, 131)] 711 | public static void RunMakeSkinned (MenuCommand command) 712 | { 713 | SkinnedMeshRenderer smr; 714 | Material[] materialList = null; 715 | if (command.context is MeshFilter) { 716 | MeshFilter mf = command.context as MeshFilter; 717 | GameObject go = mf.gameObject; 718 | 719 | if (go.GetComponent() == null) { 720 | EditorUtility.DisplayDialog ("LyumaMeshTools", "object must have a MeshRenderer.", "OK", ""); 721 | return; 722 | } 723 | materialList = go.GetComponent().sharedMaterials; 724 | //Undo.RecordObject (go, "Switched SkinnedMeshRenderer to bone"); 725 | smr = Undo.AddComponent(go); 726 | smr.rootBone = go.transform.parent; 727 | } else { 728 | smr = command.context as SkinnedMeshRenderer; 729 | } 730 | Transform trans = smr.transform; 731 | Mesh sourceMesh = smr.sharedMesh; 732 | string parentName = ""; 733 | Transform child = null; 734 | if (trans.childCount == 1) { 735 | child = trans.GetChild (0); 736 | } else { 737 | EditorUtility.DisplayDialog ("LyumaMeshTools", "Skinned mesh Must have a single child.", "OK", ""); 738 | return; 739 | } 740 | if (smr.rootBone == null) { 741 | EditorUtility.DisplayDialog ("LyumaMeshTools", "Skinned mesh Must have a root bone assigned.", "OK", ""); 742 | return; 743 | } 744 | if (smr.rootBone.transform == smr.transform) { 745 | if (!EditorUtility.DisplayDialog ("LyumaMeshTools", "Skinned mesh should have a different transform set as root bone.", "Continue", "Cancel")) { 746 | return; 747 | } 748 | } 749 | parentName = trans.name + "_"; 750 | bool staticNormal = trans.name.Contains("NONORMAL"); 751 | bool relativeNormal = trans.name.Contains("NORMALREL"); 752 | bool staticPosition = trans.name.Contains("NOPOSITION"); 753 | bool relativePosition = trans.name.Contains("POSITIONREL"); 754 | Mesh newMesh = new Mesh (); 755 | int size = sourceMesh.vertices.Length; 756 | List srcUV = new List (); 757 | List srcUV2 = new List (); 758 | List srcUV3 = new List (); 759 | List srcUV4 = new List (); 760 | sourceMesh.GetUVs (0, srcUV); 761 | sourceMesh.GetUVs (1, srcUV2); 762 | sourceMesh.GetUVs (2, srcUV3); 763 | sourceMesh.GetUVs (3, srcUV4); 764 | Vector3 [] srcVertices = sourceMesh.vertices; 765 | Color [] srcColors = sourceMesh.colors; // Forces to half precision? 766 | Vector3 [] srcNormals = sourceMesh.normals; 767 | Vector4 [] srcTangents = sourceMesh.tangents; 768 | Matrix4x4 [] srcBindposes = sourceMesh.bindposes; 769 | BoneWeight [] srcBoneWeights = sourceMesh.boneWeights; 770 | Matrix4x4 invchildmatrix4 = smr.transform.worldToLocalMatrix * child.localToWorldMatrix; 771 | if (srcUV.Count > 0) { 772 | bool resetCount = EditorUtility.DisplayDialog ("Make Skinned", "Reset uv.z value? (Currently " + uvOffset + ")", "No UV / Reset to 0", "Use " + uvOffset); 773 | if (resetCount) { 774 | uvOffset = 0; 775 | } 776 | if (!resetCount || staticPosition) { 777 | for (int i = 0; i < srcUV.Count; i++) { 778 | Vector4 origI = srcUV [i]; 779 | if (staticPosition) { 780 | origI.x = srcVertices[i].x; 781 | origI.y = srcVertices[i].y; 782 | origI.w = srcVertices[i].z; 783 | } 784 | origI.z = uvOffset; 785 | srcUV [i] = origI; 786 | } 787 | } 788 | uvOffset++; 789 | } 790 | for (int i = 0; i < srcVertices.Length; i++) { 791 | if (staticPosition) { 792 | srcVertices [i] = new Vector3(0, 0, 0); 793 | } 794 | if (!relativePosition) { 795 | srcVertices [i] = invchildmatrix4.MultiplyPoint3x4 (srcVertices [i]); 796 | } 797 | } 798 | newMesh.vertices = srcVertices; 799 | if (srcNormals != null && srcNormals.Length > 0) { 800 | for (int i = 0; i < srcNormals.Length; i++) { 801 | if (staticNormal) { 802 | srcNormals [i] = new Vector3(0, 0, 1); 803 | } 804 | if (!relativeNormal) { 805 | srcNormals [i] = invchildmatrix4.MultiplyVector (srcNormals [i]); 806 | } 807 | } 808 | newMesh.normals = srcNormals; 809 | } 810 | if (srcTangents != null && srcTangents.Length > 0) { 811 | for (int i = 0; i < srcTangents.Length; i++) { 812 | if (staticNormal) { 813 | srcTangents [i] = new Vector4 (1, 0, 0, 1); 814 | } 815 | if (!relativeNormal) { 816 | Vector3 mulout = invchildmatrix4.MultiplyVector ((Vector3)srcTangents [i]); 817 | srcTangents [i] = new Vector4(mulout.x, mulout.y, mulout.z, srcTangents[i].w); 818 | } 819 | } 820 | newMesh.tangents = srcTangents; 821 | } 822 | { 823 | BoneWeight [] newBoneWeights = new BoneWeight [srcVertices.Length]; 824 | for (int i = 0; i < srcVertices.Length; i++) { 825 | BoneWeight bw = new BoneWeight (); 826 | if (child == null) { 827 | bw.boneIndex1 = 0; 828 | bw.weight1 = 1.0f; 829 | } else { 830 | bw.boneIndex0 = 1; 831 | bw.weight0 = 1.0f; // 0.99999f 832 | bw.boneIndex1 = 0; 833 | bw.weight1 = 0.00f; 834 | } 835 | newBoneWeights [i] = bw; 836 | } 837 | newMesh.boneWeights = newBoneWeights; 838 | } 839 | if (srcColors != null && srcColors.Length > 0) { 840 | newMesh.colors = srcColors; 841 | } 842 | if (srcUV.Count > 0) { 843 | newMesh.SetUVs (0, srcUV); 844 | } 845 | if (srcUV2.Count > 0) { 846 | newMesh.SetUVs (1, srcUV2); 847 | } 848 | if (srcUV3.Count > 0) { 849 | newMesh.SetUVs (2, srcUV3); 850 | } 851 | if (srcUV4.Count > 0) { 852 | newMesh.SetUVs (3, srcUV4); 853 | } 854 | newMesh.subMeshCount = sourceMesh.subMeshCount; 855 | for (int i = 0; i < sourceMesh.subMeshCount; i++) { 856 | var curIndices = sourceMesh.GetIndices (i); 857 | newMesh.SetIndices (curIndices, sourceMesh.GetTopology (i), i); 858 | } 859 | newMesh.bounds = sourceMesh.bounds; 860 | if (child == null) { 861 | Matrix4x4 rootmatrix = smr.rootBone.worldToLocalMatrix * smr.transform.localToWorldMatrix; 862 | newMesh.bindposes = new Matrix4x4 [] { rootmatrix }; 863 | } else { 864 | Matrix4x4 childmatrix4 = child.worldToLocalMatrix * smr.transform.localToWorldMatrix; 865 | Matrix4x4 rootmatrix = smr.rootBone.worldToLocalMatrix * smr.transform.localToWorldMatrix; 866 | newMesh.bindposes = new Matrix4x4[] { rootmatrix, childmatrix4 }; 867 | } 868 | for (int i = 0; i < sourceMesh.blendShapeCount; i++) { 869 | var blendShapeName = sourceMesh.GetBlendShapeName (i); 870 | var blendShapeFrameCount = sourceMesh.GetBlendShapeFrameCount (i); 871 | for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 872 | float weight = sourceMesh.GetBlendShapeFrameWeight (i, frameIndex); 873 | Vector3 [] deltaVertices = new Vector3 [size]; 874 | Vector3 [] deltaNormals = new Vector3 [size]; 875 | Vector3 [] deltaTangents = new Vector3 [size]; 876 | sourceMesh.GetBlendShapeFrameVertices (i, frameIndex, deltaVertices, deltaNormals, deltaTangents); 877 | newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents); 878 | } 879 | } 880 | newMesh.name = sourceMesh.name + "_uvmerged"; 881 | Mesh meshAfterUpdate = newMesh; 882 | if (smr != null) { 883 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to bone"); 884 | if (child == null) { 885 | smr.bones = new Transform [] { smr.transform.parent }; //smr.transform }; 886 | } else { 887 | smr.bones = new Transform [] { smr.transform.parent, child }; //smr.transform }; 888 | } 889 | smr.sharedMesh = newMesh; 890 | if (materialList != null) { 891 | smr.sharedMaterials = materialList; 892 | } 893 | meshAfterUpdate = smr.sharedMesh; 894 | // No need to change smr.bones: should use same bone indices and blendshapes. 895 | } 896 | string pathToGenerated = "Assets" + "/Generated"; 897 | if (!Directory.Exists (pathToGenerated)) { 898 | Directory.CreateDirectory (pathToGenerated); 899 | } 900 | int lastSlash = parentName.LastIndexOf ('/'); 901 | string outFileName = lastSlash == -1 ? parentName : parentName.Substring (lastSlash + 1); 902 | outFileName = outFileName.Split ('.') [0]; 903 | string fileName = pathToGenerated + "/" + outFileName + "_boned_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 904 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 905 | AssetDatabase.SaveAssets (); 906 | //if (smr == null && mf == null) { 907 | // EditorGUIUtility.PingObject (meshAfterUpdate); 908 | //} 909 | } 910 | 911 | [MenuItem ("CONTEXT/MeshRenderer/Keyframe Blend shapes : LMT [Requires skin]", true)] 912 | [MenuItem ("CONTEXT/MeshFilter/Keyframe Blend shapes : LMT [Requires skin]", true)] 913 | public static bool RunKeyframeBlendShapesVal (MenuCommand command) { 914 | return false; 915 | } 916 | 917 | [MenuItem ("CONTEXT/MeshRenderer/Keyframe Blend shapes : LMT [Requires skin]", false, 131)] 918 | [MenuItem ("CONTEXT/MeshFilter/Keyframe Blend shapes : LMT [Requires skin]", false, 131)] 919 | [MenuItem ("CONTEXT/Mesh/Keyframe Blend shapes : LMT", false, 131)] 920 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Keyframe Blend shapes : LMT", false, 131)] 921 | public static void RunKeyframeBlendShapes (MenuCommand command) 922 | { 923 | Mesh sourceMesh; 924 | SkinnedMeshRenderer smr = null; 925 | Transform trans = null; 926 | string parentName = ""; 927 | if (command.context is SkinnedMeshRenderer) { 928 | smr = command.context as SkinnedMeshRenderer; 929 | trans = smr.transform; 930 | sourceMesh = smr.sharedMesh; 931 | } else if (command.context is Mesh) { 932 | sourceMesh = command.context as Mesh; 933 | } else { 934 | EditorUtility.DisplayDialog ("RunKeyframeBlendShapes", "Unknkown context type " + command.context.GetType ().FullName, "OK", ""); 935 | throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName); 936 | } 937 | if (trans != null) { 938 | // Get name of top-most object this mesh is attached to 939 | while (trans.parent != null) { 940 | trans = trans.parent; 941 | } 942 | parentName = trans.name + "_"; 943 | } 944 | parentName += sourceMesh.name; 945 | Mesh newMesh = new Mesh (); 946 | int size = sourceMesh.vertices.Length; 947 | List srcUV = new List (); // will discard zw 948 | List srcUV2 = new List (); // will discard zw 949 | List srcUV3 = new List (); 950 | List srcUV4 = new List (); 951 | sourceMesh.GetUVs (0, srcUV); 952 | sourceMesh.GetUVs (1, srcUV2); 953 | sourceMesh.GetUVs (2, srcUV3); 954 | sourceMesh.GetUVs (3, srcUV4); 955 | Vector3 [] srcVertices = sourceMesh.vertices; 956 | Color [] srcColors = sourceMesh.colors; // Forces to half precision? 957 | Vector3 [] srcNormals = sourceMesh.normals; 958 | Vector4 [] srcTangents = sourceMesh.tangents; 959 | Matrix4x4 [] srcBindposes = sourceMesh.bindposes; 960 | BoneWeight [] srcBoneWeights = sourceMesh.boneWeights; 961 | 962 | newMesh.vertices = srcVertices; 963 | if (srcNormals != null && srcNormals.Length > 0) { 964 | newMesh.normals = srcNormals; 965 | } 966 | if (srcTangents != null && srcTangents.Length > 0) { 967 | newMesh.tangents = srcTangents; 968 | } 969 | if (srcBoneWeights != null && srcBoneWeights.Length > 0) { 970 | newMesh.boneWeights = srcBoneWeights; 971 | } 972 | if (srcColors != null && srcColors.Length > 0) { 973 | newMesh.colors = srcColors; 974 | } 975 | if (srcUV.Count > 0) { 976 | newMesh.SetUVs (0, srcUV); 977 | } 978 | if (srcUV2.Count > 0) { 979 | newMesh.SetUVs (1, srcUV2); 980 | } 981 | if (srcUV3.Count > 0) { 982 | newMesh.SetUVs (2, srcUV3); 983 | } 984 | if (srcUV4.Count > 0) { 985 | newMesh.SetUVs (3, srcUV4); 986 | } 987 | newMesh.bounds = sourceMesh.bounds; 988 | if (srcBindposes != null && srcBindposes.Length > 0) { 989 | newMesh.bindposes = sourceMesh.bindposes; 990 | } 991 | List blendShapeIndices = new List(); 992 | Dictionary> outBlendShapes = new Dictionary> (); 993 | char [] separators = {'_',' '}; 994 | for (int i = 0; i < sourceMesh.blendShapeCount; i++) { 995 | var blendShapeName = sourceMesh.GetBlendShapeName (i); 996 | int outIndex = -1; 997 | if (blendShapeName.StartsWith("#", StringComparison.CurrentCulture)) { 998 | int firstUs = blendShapeName.IndexOfAny (separators); 999 | if (firstUs == -1) { 1000 | Debug.Log ("Failed to parse blend shape " + blendShapeName); 1001 | } else { 1002 | if (!int.TryParse (blendShapeName.Substring (1, firstUs - 1), out outIndex)) { 1003 | Debug.Log ("Failed to parse blend shape " + blendShapeName); 1004 | } else { 1005 | blendShapeName = blendShapeName.Substring (firstUs + 1); 1006 | } 1007 | } 1008 | } 1009 | int lastUs = blendShapeName.LastIndexOfAny (separators); 1010 | float fullpct = 100; 1011 | if (lastUs != -1 && blendShapeName.EndsWith("%", StringComparison.CurrentCulture)) { 1012 | if (!float.TryParse(blendShapeName.Substring(lastUs + 1, blendShapeName.Length - lastUs - 2), out fullpct)) { 1013 | Debug.Log ("Failed to parse percent " + blendShapeName); 1014 | } else { 1015 | blendShapeName = blendShapeName.Substring (0, lastUs); 1016 | } 1017 | } 1018 | var blendShapeFrameCount = sourceMesh.GetBlendShapeFrameCount (i); 1019 | if (!outBlendShapes.ContainsKey(blendShapeName)) { 1020 | outBlendShapes.Add (blendShapeName, new SortedDictionary ()); 1021 | int thisIndex = blendShapeIndices.Count; 1022 | blendShapeIndices.Add (blendShapeName); 1023 | if (outIndex != -1 && outIndex < blendShapeIndices.Count) { 1024 | Debug.Log ("Blend shape " + blendShapeName + " index " + outIndex + " swapped with " + thisIndex); 1025 | string tmp = blendShapeIndices[outIndex]; 1026 | blendShapeIndices [outIndex] = blendShapeIndices [thisIndex]; 1027 | blendShapeIndices [thisIndex] = tmp; 1028 | } else { 1029 | Debug.Log ("Blend shape " + blendShapeName + " index " + thisIndex); 1030 | } 1031 | } 1032 | for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 1033 | float weight = sourceMesh.GetBlendShapeFrameWeight (i, frameIndex); 1034 | Debug.Log ("Blend shape " + blendShapeName + " weight " + (weight * fullpct / 100) + " source:" + i + "/" + frameIndex); 1035 | outBlendShapes [blendShapeName].Add (weight * fullpct / 100, new Vector2Int (i, frameIndex)); 1036 | } 1037 | } 1038 | for (int i = 0; i < blendShapeIndices.Count; i++) { 1039 | var blendShapeName = blendShapeIndices[i]; 1040 | //var blendShapeFrameCount = outBlendShapes[blendShapeName].Count; 1041 | foreach (KeyValuePair entry in outBlendShapes [blendShapeName]) { 1042 | //for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 1043 | float weight = entry.Key; 1044 | Vector3 [] deltaVertices = new Vector3 [size]; 1045 | Vector3 [] deltaNormals = new Vector3 [size]; 1046 | Vector3 [] deltaTangents = new Vector3 [size]; 1047 | sourceMesh.GetBlendShapeFrameVertices (entry.Value.x, entry.Value.y, deltaVertices, deltaNormals, deltaTangents); 1048 | newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents); 1049 | } 1050 | } 1051 | newMesh.subMeshCount = sourceMesh.subMeshCount; 1052 | for (int i = 0; i < sourceMesh.subMeshCount; i++) { 1053 | var curIndices = sourceMesh.GetIndices (i); 1054 | newMesh.SetIndices (curIndices, sourceMesh.GetTopology (i), i); 1055 | } 1056 | newMesh.name = sourceMesh.name + "_blendmerge"; 1057 | Mesh meshAfterUpdate = newMesh; 1058 | if (smr != null) { 1059 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to blendmerge"); 1060 | smr.sharedMesh = newMesh; 1061 | meshAfterUpdate = smr.sharedMesh; 1062 | // No need to change smr.bones: should use same bone indices and blendshapes. 1063 | } 1064 | string pathToGenerated = "Assets" + "/Generated"; 1065 | if (!Directory.Exists (pathToGenerated)) { 1066 | Directory.CreateDirectory (pathToGenerated); 1067 | } 1068 | int lastSlash = parentName.LastIndexOf ('/'); 1069 | string outFileName = lastSlash == -1 ? parentName : parentName.Substring (lastSlash + 1); 1070 | outFileName = outFileName.Split ('.') [0]; 1071 | string fileName = pathToGenerated + "/" + outFileName + "_blendmerge_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 1072 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 1073 | AssetDatabase.SaveAssets (); 1074 | if (smr == null) { 1075 | EditorGUIUtility.PingObject (meshAfterUpdate); 1076 | } 1077 | } 1078 | 1079 | [MenuItem ("CONTEXT/Mesh/Remove First Mat : LMT", false, 131)] 1080 | [MenuItem ("CONTEXT/MeshFilter/Remove First Mat : LMT", false, 131)] 1081 | [MenuItem ("CONTEXT/MeshRenderer/Remove Null Mats : LMT", false, 131)] 1082 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Remove Null Mats : LMT", false, 131)] 1083 | public static void RunRemoveFirstMat (MenuCommand command) 1084 | { 1085 | Mesh sourceMesh; 1086 | SkinnedMeshRenderer smr = null; 1087 | MeshRenderer mr = null; 1088 | MeshFilter mf = null; 1089 | Transform trans = null; 1090 | string parentName = ""; 1091 | Material[] materials = null; 1092 | if (command.context is SkinnedMeshRenderer) { 1093 | smr = command.context as SkinnedMeshRenderer; 1094 | trans = smr.transform; 1095 | sourceMesh = smr.sharedMesh; 1096 | materials = smr.sharedMaterials; 1097 | } else if (command.context is MeshRenderer) { 1098 | mr = command.context as MeshRenderer; 1099 | mf = mr.transform.GetComponent (); 1100 | trans = mr.transform; 1101 | sourceMesh = mf.sharedMesh; 1102 | materials = mr.sharedMaterials; 1103 | } else if (command.context is MeshFilter) { 1104 | mf = command.context as MeshFilter; 1105 | trans = mf.transform; 1106 | sourceMesh = mf.sharedMesh; 1107 | } else if (command.context is Mesh) { 1108 | sourceMesh = command.context as Mesh; 1109 | } else { 1110 | EditorUtility.DisplayDialog ("MergeUVs", "Unknkown context type " + command.context.GetType ().FullName, "OK", ""); 1111 | throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName); 1112 | } 1113 | if (trans != null) { 1114 | // Get name of top-most object this mesh is attached to 1115 | while (trans.parent != null) { 1116 | trans = trans.parent; 1117 | } 1118 | parentName = trans.name + "_"; 1119 | } 1120 | parentName += sourceMesh.name; 1121 | Mesh newMesh = new Mesh (); 1122 | int size = sourceMesh.vertices.Length; 1123 | List srcUV = new List (); // will discard zw 1124 | List srcUV2 = new List (); // will discard zw 1125 | List srcUV3 = new List (); 1126 | List srcUV4 = new List (); 1127 | sourceMesh.GetUVs (0, srcUV); 1128 | sourceMesh.GetUVs (1, srcUV2); 1129 | sourceMesh.GetUVs (2, srcUV3); 1130 | sourceMesh.GetUVs (3, srcUV4); 1131 | Vector3 [] srcVertices = sourceMesh.vertices; 1132 | Color [] srcColors = sourceMesh.colors; // Forces to half precision? 1133 | Vector3 [] srcNormals = sourceMesh.normals; 1134 | Vector4 [] srcTangents = sourceMesh.tangents; 1135 | Matrix4x4 [] srcBindposes = sourceMesh.bindposes; 1136 | BoneWeight [] srcBoneWeights = sourceMesh.boneWeights; 1137 | newMesh.vertices = srcVertices; 1138 | if (srcNormals != null && srcNormals.Length > 0) { 1139 | newMesh.normals = srcNormals; 1140 | } 1141 | if (srcTangents != null && srcTangents.Length > 0) { 1142 | newMesh.tangents = srcTangents; 1143 | } 1144 | if (srcBoneWeights != null && srcBoneWeights.Length > 0) { 1145 | newMesh.boneWeights = srcBoneWeights; 1146 | } 1147 | if (srcColors != null && srcColors.Length > 0) { 1148 | newMesh.colors = srcColors; 1149 | } 1150 | if (srcUV.Count > 0) { 1151 | newMesh.SetUVs (0, srcUV); 1152 | } 1153 | if (srcUV2.Count > 0) { 1154 | newMesh.SetUVs (1, srcUV2); 1155 | } 1156 | if (srcUV3.Count > 0) { 1157 | newMesh.SetUVs (2, srcUV3); 1158 | } 1159 | if (srcUV4.Count > 0) { 1160 | newMesh.SetUVs (3, srcUV4); 1161 | } 1162 | int newSubmeshCount = 0;//materials 1163 | for (int i = 0; i < sourceMesh.subMeshCount; i++) { 1164 | if ((materials == null && i > 0) || (materials != null && i < materials.Length && materials[i] != null)) { 1165 | newSubmeshCount++; 1166 | } 1167 | } 1168 | Material[] newMaterials = new Material[newSubmeshCount]; 1169 | newMesh.subMeshCount = newSubmeshCount; 1170 | int outSubmesh = 0; 1171 | for (int i = 0; i < sourceMesh.subMeshCount; i++) { 1172 | if ((materials == null && i > 0) || (materials != null && i < materials.Length && materials[i] != null)) { 1173 | if (materials != null) { 1174 | newMaterials[outSubmesh] = materials[i]; 1175 | } 1176 | var curIndices = sourceMesh.GetIndices (i); 1177 | /*if (i == 2) { 1178 | int[] newIndices = new int[curIndices.Length - 46 * 3]; 1179 | Array.Copy(curIndices , newIndices , newIndices.Length); 1180 | curIndices = newIndices; 1181 | }*/ 1182 | newMesh.SetIndices (curIndices, sourceMesh.GetTopology (i), outSubmesh); 1183 | outSubmesh++; 1184 | } 1185 | } 1186 | newMesh.bounds = sourceMesh.bounds; 1187 | if (srcBindposes != null && srcBindposes.Length > 0) { 1188 | newMesh.bindposes = sourceMesh.bindposes; 1189 | } 1190 | for (int i = 0; i < sourceMesh.blendShapeCount; i++) { 1191 | var blendShapeName = sourceMesh.GetBlendShapeName (i); 1192 | var blendShapeFrameCount = sourceMesh.GetBlendShapeFrameCount (i); 1193 | for (int frameIndex = 0; frameIndex < blendShapeFrameCount; frameIndex++) { 1194 | float weight = sourceMesh.GetBlendShapeFrameWeight (i, frameIndex); 1195 | Vector3 [] deltaVertices = new Vector3 [size]; 1196 | Vector3 [] deltaNormals = new Vector3 [size]; 1197 | Vector3 [] deltaTangents = new Vector3 [size]; 1198 | sourceMesh.GetBlendShapeFrameVertices (i, frameIndex, deltaVertices, deltaNormals, deltaTangents); 1199 | newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents); 1200 | } 1201 | } 1202 | newMesh.name = sourceMesh.name + "_shadow"; 1203 | Mesh meshAfterUpdate = newMesh; 1204 | if (smr != null) { 1205 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to Remove Null Mats"); 1206 | smr.sharedMesh = newMesh; 1207 | smr.sharedMaterials = newMaterials; 1208 | meshAfterUpdate = smr.sharedMesh; 1209 | // No need to change smr.bones: should use same bone indices and blendshapes. 1210 | } 1211 | if (mr != null) { 1212 | mr.sharedMaterials = newMaterials; 1213 | } 1214 | if (mf != null) { 1215 | Undo.RecordObject (mf, "Switched MeshFilter to Remove First Mat"); 1216 | mf.sharedMesh = newMesh; 1217 | meshAfterUpdate = mf.sharedMesh; 1218 | } 1219 | string pathToGenerated = "Assets" + "/Generated"; 1220 | if (!Directory.Exists (pathToGenerated)) { 1221 | Directory.CreateDirectory (pathToGenerated); 1222 | } 1223 | int lastSlash = parentName.LastIndexOf ('/'); 1224 | string outFileName = lastSlash == -1 ? parentName : parentName.Substring (lastSlash + 1); 1225 | outFileName = outFileName.Split ('.') [0]; 1226 | string fileName = pathToGenerated + "/" + outFileName + "_test_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 1227 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 1228 | AssetDatabase.SaveAssets (); 1229 | if (smr == null && mf == null) { 1230 | EditorGUIUtility.PingObject (meshAfterUpdate); 1231 | } 1232 | } 1233 | 1234 | 1235 | [MenuItem ("CONTEXT/Mesh/Combine Mesh Siblings : LMT [Requires GameObject]", true)] 1236 | public static bool RunCombineSiblingMeshesVal (MenuCommand command) { 1237 | return false; 1238 | } 1239 | 1240 | [MenuItem ("CONTEXT/Mesh/Combine Mesh Siblings : LMT [Requires GameObject]", false, 131)] 1241 | [MenuItem ("CONTEXT/MeshFilter/Combine Mesh Siblings : LMT", false, 131)] 1242 | [MenuItem ("CONTEXT/MeshRenderer/Combine Mesh Siblings : LMT", false, 131)] 1243 | [MenuItem ("CONTEXT/SkinnedMeshRenderer/Combine Mesh Siblings : LMT", false, 131)] 1244 | public static void RunCombineSiblingMeshes (MenuCommand command) 1245 | { 1246 | Mesh sourceMesh; 1247 | SkinnedMeshRenderer smr = null; 1248 | MeshRenderer mr = null; 1249 | MeshFilter mf = null; 1250 | Transform trans = null; 1251 | string parentName = ""; 1252 | if (command.context is SkinnedMeshRenderer) { 1253 | smr = command.context as SkinnedMeshRenderer; 1254 | trans = smr.transform; 1255 | sourceMesh = smr.sharedMesh; 1256 | } else if (command.context is MeshRenderer) { 1257 | mr = command.context as MeshRenderer; 1258 | mf = mr.transform.GetComponent (); 1259 | trans = mr.transform; 1260 | sourceMesh = mf.sharedMesh; 1261 | } else if (command.context is MeshFilter) { 1262 | mf = command.context as MeshFilter; 1263 | trans = mf.transform; 1264 | sourceMesh = mf.sharedMesh; 1265 | } else if (command.context is Mesh) { 1266 | sourceMesh = command.context as Mesh; 1267 | } else { 1268 | EditorUtility.DisplayDialog ("MergeUVs", "Unknkown context type " + command.context.GetType ().FullName, "OK", ""); 1269 | throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName); 1270 | } 1271 | 1272 | List bindposes = sourceMesh.bindposes.ToList(); 1273 | List boneTransforms = new List (); 1274 | Dictionary boneTransToIndex = new Dictionary (); 1275 | SkinnedMeshRenderer [] renderers = null; 1276 | 1277 | List siblingRelativeMatrices = null; 1278 | List siblingMeshes = new List (); 1279 | List addMaterials = new List (); 1280 | List addSubMeshCount = new List(); 1281 | List baseVertex = new List (); 1282 | int addVertices = 0; 1283 | int addSubMeshes = 0; 1284 | UnityEngine.Rendering.IndexFormat indexFormat = UnityEngine.Rendering.IndexFormat.UInt16; 1285 | if (smr != null) { 1286 | renderers = trans.parent.GetComponentsInChildren (false); 1287 | int x = Array.IndexOf (renderers, smr); 1288 | SkinnedMeshRenderer tmp = renderers [0]; 1289 | renderers [0] = smr; 1290 | renderers [x] = tmp; 1291 | bindposes = new List (); 1292 | foreach (SkinnedMeshRenderer s in renderers) { 1293 | //if (s.rootBone != smr.rootBone) { 1294 | // continue; 1295 | //} 1296 | int i = 0; 1297 | foreach (Transform t in s.bones) { 1298 | if (t == null && !boneTransToIndex.ContainsKey(smr.rootBone)) { 1299 | boneTransToIndex.Add (smr.rootBone, boneTransforms.Count); 1300 | bindposes.Add (s.sharedMesh.bindposes [i]); 1301 | boneTransforms.Add (smr.rootBone); 1302 | } else if (t != null && !boneTransToIndex.ContainsKey(t)) { 1303 | boneTransToIndex.Add (t, boneTransforms.Count); 1304 | bindposes.Add (s.sharedMesh.bindposes [i]); 1305 | boneTransforms.Add (t); 1306 | } 1307 | i++; 1308 | } 1309 | int materialsToCopy = Math.Min (s.sharedMaterials.Length, s.sharedMesh.subMeshCount); 1310 | Debug.Log ("mesh " + s.sharedMesh.name + " : boneweight length=" + s.sharedMesh.boneWeights.Length + "/ bindpose length=" + s.sharedMesh.bindposes.Length + " / bones length=" + s.bones.Length + " / root bone=" + s.rootBone.name); 1311 | addSubMeshCount.Add (materialsToCopy); 1312 | addSubMeshes += materialsToCopy; 1313 | for (i = 0; i < materialsToCopy; i++) { 1314 | addMaterials.Add (s.sharedMaterials[i]); 1315 | } 1316 | siblingMeshes.Add(s.sharedMesh); 1317 | baseVertex.Add (addVertices); 1318 | if (s.sharedMesh.vertices.Length > 65535) { 1319 | indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; 1320 | } 1321 | addVertices += s.sharedMesh.vertices.Length; 1322 | } 1323 | } 1324 | if (mf != null) { 1325 | MeshFilter [] filters = trans.parent.GetComponentsInChildren (false); 1326 | int x = Array.IndexOf (filters, mf); 1327 | MeshFilter tmp = filters [0]; 1328 | filters [0] = mf; 1329 | filters [x] = tmp; 1330 | siblingRelativeMatrices = new List(); 1331 | foreach (MeshFilter s in filters) { 1332 | MeshRenderer thismr = s.GetComponent (); 1333 | if (mr != null && thismr != null) { 1334 | int materialsToCopy = Math.Min (thismr.sharedMaterials.Length, s.sharedMesh.subMeshCount); 1335 | addSubMeshCount.Add (materialsToCopy); 1336 | addSubMeshes += materialsToCopy; 1337 | for (int i = 0; i < materialsToCopy; i++) { 1338 | addMaterials.Add (thismr.sharedMaterials [i]); 1339 | } 1340 | } else if (mr != null && thismr == null) { 1341 | continue; 1342 | } else { 1343 | addSubMeshCount.Add (s.sharedMesh.subMeshCount); 1344 | addSubMeshes += s.sharedMesh.subMeshCount; 1345 | } 1346 | siblingRelativeMatrices.Add ( mf.transform.worldToLocalMatrix * thismr.transform.localToWorldMatrix ); 1347 | siblingMeshes.Add (s.sharedMesh); 1348 | baseVertex.Add (addVertices); 1349 | if (s.sharedMesh.vertices.Length > 65535) { 1350 | indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; 1351 | } 1352 | addVertices += s.sharedMesh.vertices.Length; 1353 | } 1354 | } 1355 | if (trans != null) { 1356 | // Get name of top-most object this mesh is attached to 1357 | while (trans.parent != null) { 1358 | trans = trans.parent; 1359 | } 1360 | parentName = trans.name + "_"; 1361 | } 1362 | parentName += sourceMesh.name; 1363 | Mesh newMesh = new Mesh (); 1364 | Matrix4x4 [] srcBindposes = bindposes.ToArray (); 1365 | int size = sourceMesh.vertices.Length; 1366 | List finalUV = new List (); 1367 | List finalUV2 = new List (); 1368 | List finalUV3 = new List (); 1369 | List finalUV4 = new List (); 1370 | List finalVertices = new List (); 1371 | List finalColors = new List (); 1372 | List finalNormals = new List (); 1373 | List finalTangents = new List (); 1374 | List finalBoneWeights = new List (); 1375 | int[] meshesVertexCount = new int[siblingMeshes.Count]; 1376 | int[] meshesVertexOffset = new int[siblingMeshes.Count]; 1377 | int subi = 0; 1378 | foreach (Mesh thisMesh in siblingMeshes) { 1379 | List srcUV = new List (); 1380 | List srcUV2 = new List (); 1381 | List srcUV3 = new List (); 1382 | List srcUV4 = new List (); 1383 | List srcVertices = new List (); 1384 | List srcColors = new List (); 1385 | List srcNormals = new List (); 1386 | List srcTangents = new List (); 1387 | List srcBoneWeights = new List (); 1388 | thisMesh.GetUVs (0, srcUV); 1389 | thisMesh.GetUVs (1, srcUV2); 1390 | thisMesh.GetUVs (2, srcUV3); 1391 | thisMesh.GetUVs (3, srcUV4); 1392 | thisMesh.GetVertices (srcVertices); 1393 | if (siblingRelativeMatrices != null) { 1394 | for (int i = 0; i < srcVertices.Count; i++) { 1395 | srcVertices[i] = siblingRelativeMatrices[subi].MultiplyPoint(srcVertices[i]); 1396 | } 1397 | } 1398 | meshesVertexCount[subi] = srcVertices.Count; 1399 | meshesVertexOffset[subi] = finalVertices.Count; 1400 | 1401 | thisMesh.GetColors (srcColors); 1402 | thisMesh.GetNormals (srcNormals); 1403 | if (siblingRelativeMatrices != null) { 1404 | for (int i = 0; i < srcNormals.Count; i++) { 1405 | srcNormals[i] = siblingRelativeMatrices[subi].MultiplyVector(srcNormals[i]); 1406 | } 1407 | } 1408 | thisMesh.GetTangents (srcTangents); 1409 | if (siblingRelativeMatrices != null) { 1410 | for (int i = 0; i < srcTangents.Count; i++) { 1411 | srcTangents[i] = siblingRelativeMatrices[subi].MultiplyVector(srcTangents[i]); 1412 | } 1413 | } 1414 | thisMesh.GetBoneWeights (srcBoneWeights); 1415 | if (srcUV.Count > 0) { 1416 | finalUV.AddRange (Enumerable.Repeat (new Vector4 (0, 0, 0, 0), finalVertices.Count - finalUV.Count)); 1417 | finalUV.AddRange (srcUV); 1418 | } 1419 | if (srcUV2.Count > 0) { 1420 | finalUV2.AddRange (Enumerable.Repeat (new Vector4 (0, 0, 0, 0), finalVertices.Count - finalUV2.Count)); 1421 | finalUV2.AddRange (srcUV2); 1422 | } 1423 | if (srcUV3.Count > 0) { 1424 | finalUV3.AddRange (Enumerable.Repeat (new Vector4 (0, 0, 0, 0), finalVertices.Count - finalUV3.Count)); 1425 | finalUV3.AddRange (srcUV3); 1426 | } 1427 | if (srcUV4.Count > 0) { 1428 | finalUV4.AddRange (Enumerable.Repeat (new Vector4 (0, 0, 0, 0), finalVertices.Count - finalUV4.Count)); 1429 | finalUV4.AddRange (srcUV4); 1430 | } 1431 | if (srcColors.Count > 0) { 1432 | finalColors.AddRange (Enumerable.Repeat (new Color (0, 0, 0, 1), finalVertices.Count - finalColors.Count)); 1433 | finalColors.AddRange (srcColors); 1434 | } 1435 | if (srcNormals.Count > 0) { 1436 | finalNormals.AddRange (Enumerable.Repeat (new Vector3 (0, 0, 1), finalVertices.Count - finalNormals.Count)); 1437 | finalNormals.AddRange (srcNormals); 1438 | } 1439 | if (srcTangents.Count > 0) { 1440 | finalTangents.AddRange (Enumerable.Repeat(new Vector4(1,0,0,1), finalVertices.Count - finalTangents.Count)); 1441 | finalTangents.AddRange (srcTangents); 1442 | } 1443 | if (srcBoneWeights.Count > 0) { 1444 | finalBoneWeights.AddRange (Enumerable.Repeat (new BoneWeight(), finalVertices.Count - finalBoneWeights.Count)); 1445 | Transform [] thisbones = renderers [subi].bones; 1446 | int[] indexMapping = new int [thisbones.Length]; 1447 | for (int i = 0; i < thisbones.Length; i++) { 1448 | if (thisbones[i] == null) { 1449 | indexMapping [i] = boneTransToIndex [smr.rootBone]; 1450 | continue; 1451 | } 1452 | indexMapping [i] = boneTransToIndex [thisbones [i]]; 1453 | } 1454 | for (int i = 0; i < srcBoneWeights.Count; i++) { 1455 | BoneWeight src = srcBoneWeights [i]; 1456 | BoneWeight newbw = new BoneWeight (); 1457 | newbw.weight0 = src.weight0; 1458 | newbw.weight1 = src.weight1; 1459 | newbw.weight2 = src.weight2; 1460 | newbw.weight3 = src.weight3; 1461 | newbw.boneIndex0 = indexMapping[src.boneIndex0]; 1462 | newbw.boneIndex1 = indexMapping [src.boneIndex1]; 1463 | newbw.boneIndex2 = indexMapping [src.boneIndex2]; 1464 | newbw.boneIndex3 = indexMapping [src.boneIndex3]; 1465 | srcBoneWeights [i] = newbw; 1466 | } 1467 | finalBoneWeights.AddRange (srcBoneWeights); 1468 | } 1469 | finalVertices.AddRange (srcVertices); 1470 | subi++; 1471 | } 1472 | if (finalUV.Count > 0) { 1473 | finalUV.AddRange (Enumerable.Repeat (new Vector4 (0, 0, 0, 0), finalVertices.Count - finalUV.Count)); 1474 | } 1475 | if (finalUV2.Count > 0) { 1476 | finalUV2.AddRange (Enumerable.Repeat (new Vector4 (0, 0, 0, 0), finalVertices.Count - finalUV2.Count)); 1477 | } 1478 | if (finalUV3.Count > 0) { 1479 | finalUV3.AddRange (Enumerable.Repeat (new Vector4 (0, 0, 0, 0), finalVertices.Count - finalUV3.Count)); 1480 | } 1481 | if (finalUV4.Count > 0) { 1482 | finalUV4.AddRange (Enumerable.Repeat (new Vector4 (0, 0, 0, 0), finalVertices.Count - finalUV4.Count)); 1483 | } 1484 | if (finalColors.Count > 0) { 1485 | finalColors.AddRange (Enumerable.Repeat (new Color (0, 0, 0, 1), finalVertices.Count - finalColors.Count)); 1486 | } 1487 | if (finalNormals.Count > 0) { 1488 | finalNormals.AddRange (Enumerable.Repeat (new Vector3 (0, 0, 1), finalVertices.Count - finalNormals.Count)); 1489 | } 1490 | if (finalTangents.Count > 0) { 1491 | finalTangents.AddRange (Enumerable.Repeat (new Vector4 (1, 0, 0, 1), finalVertices.Count - finalTangents.Count)); 1492 | } 1493 | if (finalBoneWeights.Count > 0) { 1494 | finalBoneWeights.AddRange (Enumerable.Repeat (new BoneWeight (), finalVertices.Count - finalBoneWeights.Count)); 1495 | } 1496 | if (srcBindposes != null && srcBindposes.Length > 0) { 1497 | newMesh.bindposes = srcBindposes; 1498 | // FIXME: We do not adjust relative matrices of bindposes... is this necessary? 1499 | } 1500 | newMesh.SetVertices(finalVertices); 1501 | if (finalNormals != null && finalNormals.Count > 0) { 1502 | newMesh.SetNormals(finalNormals); 1503 | } 1504 | if (finalTangents != null && finalTangents.Count > 0) { 1505 | newMesh.SetTangents(finalTangents); 1506 | } 1507 | if (finalBoneWeights != null && finalBoneWeights.Count > 0) { 1508 | newMesh.boneWeights = finalBoneWeights.ToArray(); 1509 | } 1510 | if (finalColors != null && finalColors.Count > 0) { 1511 | newMesh.SetColors(finalColors); 1512 | } 1513 | if (finalUV.Count > 0) { 1514 | newMesh.SetUVs (0, finalUV); 1515 | } 1516 | if (finalUV2.Count > 0) { 1517 | newMesh.SetUVs (1, finalUV2); 1518 | } 1519 | if (finalUV3.Count > 0) { 1520 | newMesh.SetUVs (2, finalUV3); 1521 | } 1522 | if (finalUV4.Count > 0) { 1523 | newMesh.SetUVs (3, finalUV4); 1524 | } 1525 | 1526 | newMesh.subMeshCount = addSubMeshes; 1527 | newMesh.bounds = sourceMesh.bounds; 1528 | newMesh.indexFormat = indexFormat; 1529 | int whichSubMesh = 0; 1530 | for (subi = 0; subi < siblingMeshes.Count; subi++) { 1531 | for (int i = 0; i < addSubMeshCount[subi]; i++) { 1532 | var curIndices = siblingMeshes[subi].GetIndices (i); 1533 | newMesh.SetIndices (curIndices, siblingMeshes [subi].GetTopology (i), whichSubMesh, false, baseVertex[subi]); 1534 | whichSubMesh++; 1535 | } 1536 | newMesh.bounds = new Bounds(sourceMesh.bounds.center, sourceMesh.bounds.extents); 1537 | newMesh.bounds.Encapsulate (siblingMeshes [subi].bounds); 1538 | } 1539 | 1540 | Dictionary blendShapeToIndexOne = new Dictionary(); 1541 | List blendShapeList = new List(); 1542 | for (subi = 0; subi < siblingMeshes.Count; subi++) { 1543 | for (int i = 0; i < siblingMeshes[subi].blendShapeCount; i++) { 1544 | var blendShapeName = siblingMeshes[subi].GetBlendShapeName (i); 1545 | if (!blendShapeToIndexOne.ContainsKey(blendShapeName)) { 1546 | blendShapeToIndexOne[blendShapeName] = new int[siblingMeshes.Count]; 1547 | blendShapeList.Add(blendShapeName); 1548 | } 1549 | blendShapeToIndexOne[blendShapeName][subi] = i + 1; 1550 | } 1551 | } 1552 | 1553 | for (int outerbsindex = 0; outerbsindex < blendShapeList.Count; outerbsindex++) { 1554 | string blendShapeName = blendShapeList[outerbsindex]; 1555 | int totalFrameCount = 0; 1556 | for (subi = 0; subi < siblingMeshes.Count; subi++) { 1557 | int blendIndex = blendShapeToIndexOne[blendShapeName][subi] - 1; 1558 | if (blendIndex < 0) { 1559 | continue; 1560 | } 1561 | totalFrameCount = Math.Max(totalFrameCount, siblingMeshes[subi].GetBlendShapeFrameCount (blendIndex)); 1562 | } 1563 | for (int frameIndex = 0; frameIndex < totalFrameCount; frameIndex++) { 1564 | Vector3 [] newDeltaVertices = new Vector3 [finalVertices.Count]; 1565 | Vector3 [] newDeltaNormals = new Vector3 [finalVertices.Count]; 1566 | Vector3 [] newDeltaTangents = new Vector3 [finalVertices.Count]; 1567 | float weight = 100.0f; 1568 | for (subi = 0; subi < siblingMeshes.Count; subi++) { 1569 | int blendIndex = blendShapeToIndexOne[blendShapeName][subi] - 1; 1570 | if (blendIndex < 0) { 1571 | continue; 1572 | } 1573 | int thisFrameCount = siblingMeshes[subi].GetBlendShapeFrameCount (blendIndex); 1574 | if (frameIndex >= thisFrameCount) { 1575 | continue; 1576 | } 1577 | Vector3 [] deltaVertices = new Vector3 [meshesVertexCount[subi]]; 1578 | Vector3 [] deltaNormals = new Vector3 [meshesVertexCount[subi]]; 1579 | Vector3 [] deltaTangents = new Vector3 [meshesVertexCount[subi]]; 1580 | weight = Math.Min(weight, siblingMeshes[subi].GetBlendShapeFrameWeight (blendIndex, frameIndex)); 1581 | siblingMeshes[subi].GetBlendShapeFrameVertices (blendIndex, frameIndex, deltaVertices, deltaNormals, deltaTangents); 1582 | Array.Copy (deltaVertices, 0, newDeltaVertices, meshesVertexOffset[subi], meshesVertexCount[subi]); 1583 | Array.Copy (deltaNormals, 0, newDeltaNormals, meshesVertexOffset[subi], meshesVertexCount[subi]); 1584 | Array.Copy (deltaTangents, 0, newDeltaTangents, meshesVertexOffset[subi], meshesVertexCount[subi]); 1585 | // FIXME: We do not adjust blendshapes based on relative bindpose matrices. 1586 | // NOTE(Lyuma): Do we actually need to do this? I think it should just work 1587 | } 1588 | newMesh.AddBlendShapeFrame (blendShapeName, weight, newDeltaVertices, newDeltaNormals, newDeltaTangents); 1589 | } 1590 | } 1591 | newMesh.name = sourceMesh.name + "_merged"; 1592 | Mesh meshAfterUpdate = newMesh; 1593 | if (smr != null) { 1594 | Undo.RecordObject (smr, "Switched SkinnedMeshRenderer to merged"); 1595 | smr.sharedMesh = newMesh; 1596 | smr.sharedMaterials = addMaterials.ToArray (); 1597 | smr.bones = boneTransforms.ToArray (); 1598 | meshAfterUpdate = smr.sharedMesh; 1599 | // No need to change smr.bones: should use same bone indices and blendshapes. 1600 | } 1601 | if (mf != null) { 1602 | Undo.RecordObject (mf, "Switched MeshFilter to merged"); 1603 | mf.sharedMesh = newMesh; 1604 | if (mr != null) { 1605 | mr.sharedMaterials = addMaterials.ToArray (); 1606 | } 1607 | meshAfterUpdate = mf.sharedMesh; 1608 | } 1609 | string pathToGenerated = "Assets" + "/Generated"; 1610 | if (!Directory.Exists (pathToGenerated)) { 1611 | Directory.CreateDirectory (pathToGenerated); 1612 | } 1613 | int lastSlash = parentName.LastIndexOf ('/'); 1614 | string outFileName = lastSlash == -1 ? parentName : parentName.Substring (lastSlash + 1); 1615 | outFileName = outFileName.Split ('.') [0]; 1616 | string fileName = pathToGenerated + "/" + outFileName + "_assetized_" + DateTime.UtcNow.ToString ("s").Replace (':', '_') + ".asset"; 1617 | AssetDatabase.CreateAsset (meshAfterUpdate, fileName); 1618 | AssetDatabase.SaveAssets (); 1619 | if (smr == null && mf == null) { 1620 | EditorGUIUtility.PingObject (meshAfterUpdate); 1621 | } 1622 | } 1623 | } 1624 | #endif --------------------------------------------------------------------------------