diff options
| -rwxr-xr-x | 3ner.cginc | 24 | ||||
| -rwxr-xr-x | 3ner.shader | 31 | ||||
| -rwxr-xr-x | Scripts/Impostors.cs | 649 | ||||
| -rwxr-xr-x | brdf.cginc | 7 | ||||
| -rwxr-xr-x | features.cginc | 12 | ||||
| -rwxr-xr-x | globals.cginc | 25 | ||||
| -rwxr-xr-x | impostor.cginc | 326 | ||||
| -rwxr-xr-x | interpolators.cginc | 3 | ||||
| -rwxr-xr-x | lighting.cginc | 2 | ||||
| -rw-r--r-- | matcap.cginc | 26 | ||||
| -rwxr-xr-x | math.cginc | 5 | ||||
| -rwxr-xr-x | pbr.cginc | 28 | ||||
| -rw-r--r-- | poi.cginc | 5 |
13 files changed, 73 insertions, 1070 deletions
@@ -18,7 +18,6 @@ #include "instancing.cginc" #include "ray_marching.cginc" #include "vertex.cginc" -#include "impostor.cginc" #include "matcap.cginc" v2f vert(appdata v) { @@ -35,8 +34,6 @@ v2f vert(appdata v) { UNITY_TRANSFER_INSTANCE_ID(v, o); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); - impostor_vert(v.vertex.xyz); - #if defined(OUTLINES_PASS) && defined(_OUTLINES) float thickness = _Outlines_Thickness.SampleLevel(point_repeat_s, v.uv0, 0).r; v.vertex.xyz += v.normal * _Outlines_Width * thickness; @@ -44,8 +41,7 @@ v2f vert(appdata v) { #if defined(_VERTEX_DEFORMATION) && ( \ defined(_VERTEX_DEFORMATION_FRAGMENT_NORMALS) || \ - defined(_VERTEX_DEFORMATION_TESSELLATION)) || \ - (defined(_IMPOSTORS) && defined(_INSTANCE_TEXTURE_OFFSET)) + defined(_VERTEX_DEFORMATION_TESSELLATION)) o.objPos_orig = v.vertex; #endif @@ -218,8 +214,7 @@ v2f domain( #if defined(_VERTEX_DEFORMATION) && ( \ defined(_VERTEX_DEFORMATION_FRAGMENT_NORMALS) || \ - defined(_VERTEX_DEFORMATION_TESSELLATION)) || \ - defined(_IMPOSTORS) && defined(_INSTANCE_TEXTURE_OFFSET) + defined(_VERTEX_DEFORMATION_TESSELLATION)) o.objPos_orig = DOMAIN_INTERP(objPos_orig); o.objPos = o.objPos_orig; deform(o.objPos); @@ -286,12 +281,9 @@ void geom(triangle v2f tri_in[3], //endex float4 frag(v2f i, uint facing : SV_IsFrontFace -#if defined(_IMPOSTORS_DEPTH) - , out float depth : SV_DepthLessEqual -#endif ) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); -#if defined(SHADOW_CASTER_PASS) && !defined(_IMPOSTORS_DEPTH) +#if defined(SHADOW_CASTER_PASS) return 0; #endif @@ -310,16 +302,6 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace Pbr pbr = getPbr(i); -#if defined(_IMPOSTORS) - i.normal = pbr.normal; -#if defined(_IMPOSTORS_DEPTH) - i.objPos = pbr.objPos; - propagateObjPos(i); - float4 imp_clip_pos = UnityObjectToClipPos(i.objPos); - depth = imp_clip_pos.z / imp_clip_pos.w; -#endif -#endif - #if defined(_DEBUG_VIEW_UNLIT) return pbr.albedo; #elif defined(_DEBUG_VIEW_WORLD_SPACE_NORMALS) diff --git a/3ner.shader b/3ner.shader index be4a19b..476a7f4 100755 --- a/3ner.shader +++ b/3ner.shader @@ -38,6 +38,15 @@ Shader "yum_food/3ner" _Metallic("Metallic", Range(0, 1)) = 0 _Glossiness("Smoothness", Range(0, 1)) = 0.5 + //ifex _Emissions_Enabled==0 + [HideInInspector] m_start_Emissions("Emissions", Float) = 0 + [ThryToggle(_EMISSIONS)] _Emissions_Enabled("Enable", Float) = 0 + _EmissionColor("Tint", Color) = (1, 1, 1, 1) + _EmissionMap("Color", 2D) = "white" {} + _EmissionMask("Mask", 2D) = "white" {} + [HideInInspector] m_end_Emissions("Emissions", Float) = 0 + //endex + //ifex _Details_Enabled==0 [HideInInspector] m_start_Details("Details", Float) = 0 [ThryToggle(_DETAILS)] _Details_Enabled("Enable", Float) = 0 @@ -112,7 +121,7 @@ Shader "yum_food/3ner" [ThryToggle(_RIM_LIGHTING0)] _Rim_Lighting0_Enabled("Enable", Float) = 0 _Rim_Lighting0_Color("Color", Color) = (1, 1, 1, 1) _Rim_Lighting0_Center("Center", Range(0, 1)) = 1 - _Rim_Lighting0_Blur("Blur", Range(0, 0.5)) = 0.1 + _Rim_Lighting0_Blur("Blur", Range(0, 1)) = 0.1 [ThryWideEnum(Replace, 0, Add, 1, Multiply, 2, Subtract, 3, Add Product, 4)] _Rim_Lighting0_Mode("Mode", Int) = 1 //ifex _Rim_Lighting0_Quantization_Enabled==0 @@ -531,26 +540,6 @@ Shader "yum_food/3ner" [HideInInspector] m_end_Marble("Marble", Float) = 0 //endex - //ifex _Impostors_Enabled==0 - [HideInInspector] m_start_Impostors("Impostors", Float) = 0 - [ThryToggle(_IMPOSTORS)] _Impostors_Enabled("Enable", Float) = 0 - _Impostors_Atlas("Atlas", 2D) = "white" {} - _Impostors_Normal_Atlas("Normal Atlas", 2D) = "bump" {} - _Impostors_Metallic_Gloss_Depth_Atlas("Metallic Gloss Depth Atlas", 2D) = "white" {} - _Impostors_Grid_Resolution("Grid Resolution", Int) = 5 - _Impostors_Sphere_Radius("Sphere Radius", Float) = 1.0 - _Impostors_Near_Clip("Near clip distance", Float) = 0.01 - _Impostors_Far_Clip("Far clip distance", Float) = 1.0 - _Impostors_Cutoff("Alpha Cutoff", Range(0, 1)) = 0.5 - _Impostors_Parallax("Parallax Strength", Range(0, 1)) = 1 - - [ThryToggle(_IMPOSTORS_DEPTH)] _Impostors_Depth_Enabled("Enable depth", Float) = 0 - - [Toggle] _Impostors_Debug_Mode("Debug Mode", Float) = 0 - [Toggle] _Impostors_Debug_Depth("Debug Depth", Float) = 0 - [HideInInspector] m_end_Impostors("Impostors", Float) = 0 - //endex - [HideInInspector] m_end_Gimmicks("Gimmicks", Float) = 0 //ifex _Tessellation_Enabled==0 diff --git a/Scripts/Impostors.cs b/Scripts/Impostors.cs deleted file mode 100755 index e77be4e..0000000 --- a/Scripts/Impostors.cs +++ /dev/null @@ -1,649 +0,0 @@ -#if UNITY_EDITOR -using UnityEngine; -using UnityEditor; -using System.IO; - -[ExecuteInEditMode] -public class Impostors : MonoBehaviour -{ - [Header("Bounding Sphere")] - public float radiusScale = 1f; - - [Header("Grid Settings")] - [Range(2, 20)] public int gridResolution = 5; - - [Header("Camera Settings")] - [Range(1, 4096)] public int cameraResolution = 256; - public float nearClippingDistance = 0.01f; - public LayerMask cullingMask = -1; - public bool renderSkybox = false; - - [Header("Original Mesh")] - public GameObject originalMesh; - - [HideInInspector] public Camera[] cameras; - - private GameObject impostorObject; - private Material impostorMaterial; - - public bool HasImpostor => impostorObject != null; - private string OutputFolder => GetOutputFolder(); - - Bounds GetCombinedBounds() - { - Renderer[] allRenderers = originalMesh.GetComponentsInChildren<Renderer>(true); - Renderer[] renderers = System.Array.FindAll(allRenderers, r => r.gameObject != impostorObject); - Bounds bounds = renderers[0].bounds; - for (int i = 1; i < renderers.Length; i++) - bounds.Encapsulate(renderers[i].bounds); - return bounds; - } - - float GetBoundingSphereRadius() - { - return GetCombinedBounds().extents.magnitude * radiusScale; - } - - void OnEnable() => Camera.onPreRender += UpdateMainCameraPos; - void OnDisable() => Camera.onPreRender -= UpdateMainCameraPos; - - static void UpdateMainCameraPos(Camera cam) - { - if (cam.cameraType == CameraType.Game || cam.cameraType == CameraType.SceneView) - Shader.SetGlobalVector("_Impostors_Main_Camera_Pos", cam.transform.position); - } - - void OnDrawGizmos() - { - if (originalMesh == null) return; - - Bounds bounds = GetCombinedBounds(); - Vector3 center = bounds.center; - float radius = GetBoundingSphereRadius(); - - Gizmos.color = Color.cyan; - Gizmos.DrawWireSphere(center, radius); - - if (Application.isEditor && gridResolution > 0) - { - Gizmos.color = Color.yellow; - for (int y = 0; y < gridResolution; y++) - { - for (int x = 0; x < gridResolution; x++) - { - Vector3 worldPos = center + PlaneToHemiOctahedron(x, y) * (radius + nearClippingDistance); - Gizmos.DrawSphere(worldPos, radius * 0.05f); - Gizmos.DrawLine(worldPos, center); - } - } - } - } - - string GetOutputFolder() - { - string hierarchyPath = GetHierarchyPath(); - return $"Assets/yum_food/3ner/Impostor_Generated/{hierarchyPath}"; - } - - string GetHierarchyPath() - { - string path = gameObject.name; - Transform parent = transform.parent; - while (parent != null) - { - path = parent.name + "/" + path; - parent = parent.parent; - } - return path; - } - - Vector3 PlaneToHemiOctahedron(int gridX, int gridY) - { - float x = (gridX / (float)(gridResolution - 1)) * 2f - 1f; - float z = (gridY / (float)(gridResolution - 1)) * 2f - 1f; - - // Rotate 45° to fit square into diamond - float x_rot = (x + z) * 0.5f; - float z_rot = (z - x) * 0.5f; - - // Octahedral decode - float y = Mathf.Max(0f, 1f - Mathf.Abs(x_rot) - Mathf.Abs(z_rot)); - - // Normalize - Vector3 oct_pos = new Vector3(x_rot, y, z_rot).normalized; - - // Rotate back by -45° around y - float rcp_sqrt2 = 0.70710678f; - float x_unrot = (oct_pos.x - oct_pos.z) * rcp_sqrt2; - float z_unrot = (oct_pos.x + oct_pos.z) * rcp_sqrt2; - - return new Vector3(x_unrot, oct_pos.y, z_unrot); - } - - public void CreateCameras() - { - DestroyExistingCameras(); - - GameObject parent = new GameObject("Cameras"); - parent.transform.SetParent(transform, false); - - cameras = new Camera[gridResolution * gridResolution]; - int idx = 0; - - Bounds bounds = GetCombinedBounds(); - Vector3 center = bounds.center; - float radius = GetBoundingSphereRadius(); - - for (int y = 0; y < gridResolution; y++) - { - for (int x = 0; x < gridResolution; x++) - { - Vector3 localDir = PlaneToHemiOctahedron(x, y); - Vector3 worldPos = center + (transform.rotation * localDir) * (radius + nearClippingDistance); - - GameObject camObj = new GameObject($"Camera_{x}_{y}"); - camObj.transform.SetParent(parent.transform, false); - camObj.transform.position = worldPos; - camObj.transform.LookAt(center, transform.up); - - Camera cam = camObj.AddComponent<Camera>(); - cam.orthographic = true; - cam.orthographicSize = radius; - cam.nearClipPlane = nearClippingDistance; - cam.farClipPlane = radius * 2f + nearClippingDistance; - cam.cullingMask = cullingMask; - cam.clearFlags = renderSkybox ? CameraClearFlags.Skybox : CameraClearFlags.SolidColor; - cam.backgroundColor = Color.clear; - cam.enabled = false; - - cameras[idx++] = cam; - } - } - } - - public void DestroyExistingCameras() - { - Transform camsTransform = transform.Find("Cameras"); - if (camsTransform != null) DestroyImmediate(camsTransform.gameObject); - cameras = null; - } - - struct BakePass - { - public string name; - public string keyword; - public Texture2D atlas; - public bool isDepth; - public bool linear; - - public BakePass(string name, string keyword, Texture2D atlas, bool isDepth = false, bool linear = false) - { - this.name = name; - this.keyword = keyword; - this.atlas = atlas; - this.isDepth = isDepth; - this.linear = linear; - } - } - - void RenderAtlasPass(Texture2D atlas, RenderTexture colorRT, RenderTexture depthOnlyRT, Material depthBlitMat = null) - { - bool isDepth = depthBlitMat != null; - RenderTexture linearDepthRT = isDepth ? RenderTexture.GetTemporary(cameraResolution, cameraResolution, 0, RenderTextureFormat.RFloat) : null; - - int idx = 0; - for (int y = 0; y < gridResolution; y++) - { - for (int x = 0; x < gridResolution; x++) - { - Camera cam = cameras[idx++]; - cam.SetTargetBuffers(colorRT.colorBuffer, depthOnlyRT.depthBuffer); - cam.Render(); - - if (isDepth) - { - depthBlitMat.SetTexture("_DepthTex", depthOnlyRT); - depthBlitMat.SetFloat("_Near", cam.nearClipPlane); - depthBlitMat.SetFloat("_Far", cam.farClipPlane); - Graphics.Blit(null, linearDepthRT, depthBlitMat); - RenderTexture.active = linearDepthRT; - } - else - { - RenderTexture.active = colorRT; - } - - Texture2D temp = new Texture2D(cameraResolution, cameraResolution, isDepth ? TextureFormat.RFloat : TextureFormat.RGBA32, false); - temp.ReadPixels(new Rect(0, 0, cameraResolution, cameraResolution), 0, 0); - temp.Apply(); - atlas.SetPixels(x * cameraResolution, y * cameraResolution, cameraResolution, cameraResolution, temp.GetPixels()); - DestroyImmediate(temp); - } - } - atlas.Apply(); - - if (linearDepthRT != null) RenderTexture.ReleaseTemporary(linearDepthRT); - } - - void SetMaterialDebugKeyword(string keyword, bool enabled) - { - if (originalMesh == null || string.IsNullOrEmpty(keyword)) return; - foreach (Renderer r in originalMesh.GetComponentsInChildren<Renderer>(true)) - { - foreach (Material mat in r.sharedMaterials) - { - if (mat != null) - { - if (enabled) - mat.EnableKeyword(keyword); - else - mat.DisableKeyword(keyword); - } - } - } - } - - void ExecutePassesSequentially(BakePass[] passes, RenderTexture srgbRT, RenderTexture linearRT, RenderTexture depthOnlyRT, Material depthBlitMat, int passIndex = 0) - { - if (passIndex >= passes.Length) - { - // All passes complete - RenderTexture.active = null; - RenderTexture.ReleaseTemporary(srgbRT); - RenderTexture.ReleaseTemporary(linearRT); - RenderTexture.ReleaseTemporary(depthOnlyRT); - DestroyImmediate(depthBlitMat); - - SaveAndConfigureTextures(passes[0].atlas, passes[1].atlas, passes[2].atlas, passes[3].atlas); - return; - } - - BakePass pass = passes[passIndex]; - Debug.Log($"Baking {pass.name} pass..."); - - SetMaterialDebugKeyword(pass.keyword, true); - - UnityEditor.EditorApplication.delayCall += () => { - RenderTexture colorRT = pass.linear ? linearRT : srgbRT; - RenderAtlasPass(pass.atlas, colorRT, depthOnlyRT, pass.isDepth ? depthBlitMat : null); - SetMaterialDebugKeyword(pass.keyword, false); - ExecutePassesSequentially(passes, srgbRT, linearRT, depthOnlyRT, depthBlitMat, passIndex + 1); - }; - } - - public void BakeTexture() - { - SetRenderersEnabled(true); - CreateCameras(); - - Shader depthBlitShader = Shader.Find("Hidden/yum_food/DepthBlit"); - if (depthBlitShader == null) { Debug.LogError("DepthBlit shader not found"); return; } - Material depthBlitMat = new Material(depthBlitShader); - - int size = cameraResolution * gridResolution; - BakePass[] passes = new BakePass[] - { - new BakePass("albedo", "_DEBUG_VIEW_UNLIT", new Texture2D(size, size, TextureFormat.RGBA32, false)), - new BakePass("normals", "_DEBUG_VIEW_WORLD_SPACE_NORMALS", new Texture2D(size, size, TextureFormat.RGBA32, false), linear: true), - new BakePass("metallic/gloss", "_DEBUG_VIEW_METALLIC_GLOSS", new Texture2D(size, size, TextureFormat.RGBA32, false), linear: true), - new BakePass("depth", "", new Texture2D(size, size, TextureFormat.RFloat, false), isDepth: true) - }; - - RenderTextureDescriptor srgbDesc = new RenderTextureDescriptor(cameraResolution, cameraResolution, RenderTextureFormat.ARGB32, 24); - srgbDesc.sRGB = true; - RenderTexture srgbRT = RenderTexture.GetTemporary(srgbDesc); - - RenderTextureDescriptor linearDesc = new RenderTextureDescriptor(cameraResolution, cameraResolution, RenderTextureFormat.ARGB32, 24); - linearDesc.sRGB = false; - RenderTexture linearRT = RenderTexture.GetTemporary(linearDesc); - - RenderTextureDescriptor depthDesc = new RenderTextureDescriptor(cameraResolution, cameraResolution, RenderTextureFormat.Depth, 24); - RenderTexture depthOnlyRT = RenderTexture.GetTemporary(depthDesc); - - // Ensure all debug keywords start disabled - foreach (var pass in passes) SetMaterialDebugKeyword(pass.keyword, false); - - ExecutePassesSequentially(passes, srgbRT, linearRT, depthOnlyRT, depthBlitMat); - } - - struct TextureExportSettings - { - public string suffix; - public bool isEXR; - public bool mipmaps; - public bool sRGB; - public FilterMode filter; - public bool alphaTransparency; - public bool uncompressed; - public bool isNormalMap; - - public TextureExportSettings(string suffix, bool isEXR = false, bool mipmaps = true, bool sRGB = true, - FilterMode filter = FilterMode.Trilinear, bool alphaTransparency = false, - bool uncompressed = false, bool isNormalMap = false) - { - this.suffix = suffix; - this.isEXR = isEXR; - this.mipmaps = mipmaps; - this.sRGB = sRGB; - this.filter = filter; - this.alphaTransparency = alphaTransparency; - this.uncompressed = uncompressed; - this.isNormalMap = isNormalMap; - } - } - - void DilateTexture(Texture2D tex, Texture2D alphaSource, bool preserveAlpha = false, int iterations = 8) - { - int w = tex.width, h = tex.height; - Color[] pixels = tex.GetPixels(); - Color[] alpha = alphaSource.GetPixels(); - Color[] origAlpha = preserveAlpha ? (Color[])alpha.Clone() : null; - Color[] buffer = (Color[])pixels.Clone(); - - bool[] filled = new bool[pixels.Length]; - for (int i = 0; i < pixels.Length; i++) - filled[i] = alpha[i].a > 0.01f; - bool[] filledNext = new bool[filled.Length]; - - int[] dx = { -1, 1, 0, 0 }; - int[] dy = { 0, 0, -1, 1 }; - - for (int iter = 0; iter < iterations; iter++) - { - System.Array.Copy(pixels, buffer, pixels.Length); - System.Array.Copy(filled, filledNext, filled.Length); - - for (int y = 0; y < h; y++) - { - for (int x = 0; x < w; x++) - { - int i = y * w + x; - if (filled[i]) continue; - - Color sum = Color.clear; - int count = 0; - for (int d = 0; d < 4; d++) - { - int nx = x + dx[d], ny = y + dy[d]; - if (nx < 0 || nx >= w || ny < 0 || ny >= h) continue; - int ni = ny * w + nx; - if (filled[ni]) - { - sum += pixels[ni]; - count++; - } - } - if (count > 0) - { - buffer[i] = sum / count; - buffer[i].a = 1; - filledNext[i] = true; - } - } - } - var tmpFilled = filled; filled = filledNext; filledNext = tmpFilled; - var tmpPixels = pixels; pixels = buffer; buffer = tmpPixels; - } - - if (preserveAlpha) - for (int i = 0; i < pixels.Length; i++) pixels[i].a = origAlpha[i].a; - - tex.SetPixels(pixels); - tex.Apply(); - } - - void DilateDepthTexture(Texture2D depthTex, Texture2D alphaSource, int iterations = 8) - { - int w = depthTex.width, h = depthTex.height; - Color[] depth = depthTex.GetPixels(); - Color[] mask = alphaSource.GetPixels(); - - bool[] filled = new bool[depth.Length]; - for (int i = 0; i < depth.Length; i++) - filled[i] = mask[i].a > 0.01f; - - Color[] buffer = (Color[])depth.Clone(); - bool[] filledNext = new bool[filled.Length]; - - int[] dx = { -1, 1, 0, 0 }; - int[] dy = { 0, 0, -1, 1 }; - - for (int iter = 0; iter < iterations; iter++) - { - // Preserve all previously-filled pixels; only write new pixels outside the alpha mask. - System.Array.Copy(depth, buffer, depth.Length); - System.Array.Copy(filled, filledNext, filled.Length); - - for (int y = 0; y < h; y++) - { - for (int x = 0; x < w; x++) - { - int i = y * w + x; - if (filled[i]) continue; - - float sum = 0f; - int count = 0; - for (int d = 0; d < 4; d++) - { - int nx = x + dx[d], ny = y + dy[d]; - if (nx < 0 || nx >= w || ny < 0 || ny >= h) continue; - int ni = ny * w + nx; - if (!filled[ni]) continue; - sum += depth[ni].r; - count++; - } - - if (count > 0) - { - buffer[i].r = sum / count; - filledNext[i] = true; - } - } - } - - var tmpFilled = filled; filled = filledNext; filledNext = tmpFilled; - var tmpDepth = depth; depth = buffer; buffer = tmpDepth; - } - - depthTex.SetPixels(depth); - depthTex.Apply(); - } - - void SaveAndConfigureTexture(Texture2D atlas, TextureExportSettings settings, string baseName, out string path) - { - path = Path.Combine(OutputFolder, $"{baseName}_{settings.suffix}.{(settings.isEXR ? "exr" : "png")}"); - byte[] data = settings.isEXR ? atlas.EncodeToEXR(Texture2D.EXRFlags.OutputAsFloat) : atlas.EncodeToPNG(); - File.WriteAllBytes(Path.Combine(Application.dataPath, "..", path), data); - DestroyImmediate(atlas); - } - - void ConfigureTextureImporter(string path, TextureExportSettings settings) - { - TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter; - if (importer != null) - { - if (settings.isNormalMap) importer.textureType = TextureImporterType.NormalMap; - importer.mipmapEnabled = settings.mipmaps; - importer.sRGBTexture = settings.sRGB; - importer.wrapMode = TextureWrapMode.Clamp; - importer.filterMode = settings.filter; - if (settings.alphaTransparency) importer.alphaIsTransparency = true; - if (settings.uncompressed) importer.textureCompression = TextureImporterCompression.Uncompressed; - EditorUtility.SetDirty(importer); - importer.SaveAndReimport(); - AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport); - } - } - - void SaveAndConfigureTextures(Texture2D albedoAtlas, Texture2D normalAtlas, Texture2D metallicGlossAtlas, Texture2D depthAtlas) - { - if (!AssetDatabase.IsValidFolder(OutputFolder)) - { - string[] pathParts = OutputFolder.Split('/'); - string currentPath = ""; - for (int i = 0; i < pathParts.Length; i++) - { - string parentPath = i == 0 ? "" : string.Join("/", pathParts, 0, i); - currentPath = i == 0 ? pathParts[0] : $"{parentPath}/{pathParts[i]}"; - if (!AssetDatabase.IsValidFolder(currentPath)) - { - string folderName = pathParts[i]; - AssetDatabase.CreateFolder(parentPath, folderName); - } - } - } - - string baseName = gameObject.name.Replace(" ", "_"); - - // Dilate before combining - DilateTexture(albedoAtlas, albedoAtlas, preserveAlpha: true); - DilateTexture(normalAtlas, albedoAtlas); - DilateTexture(metallicGlossAtlas, albedoAtlas); - DilateDepthTexture(depthAtlas, albedoAtlas); - - // Combine metallic_gloss (RG) with depth (B) into a single texture - Texture2D combinedAtlas = new Texture2D(metallicGlossAtlas.width, metallicGlossAtlas.height, TextureFormat.RGBA32, false); - Color[] metallicGlossPixels = metallicGlossAtlas.GetPixels(); - Color[] depthPixels = depthAtlas.GetPixels(); - Color[] combinedPixels = new Color[metallicGlossPixels.Length]; - - for (int i = 0; i < combinedPixels.Length; i++) - { - combinedPixels[i] = new Color( - metallicGlossPixels[i].r, // Metallic - metallicGlossPixels[i].g, // Gloss - depthPixels[i].r, // Depth - 1.0f // Alpha (unused) - ); - } - combinedAtlas.SetPixels(combinedPixels); - combinedAtlas.Apply(); - - // Clean up the separate textures - DestroyImmediate(metallicGlossAtlas); - DestroyImmediate(depthAtlas); - - var exportSettings = new (TextureExportSettings settings, string materialProp)[] - { - (new TextureExportSettings("albedo", mipmaps: true, sRGB: true, alphaTransparency: true), "_Impostors_Atlas"), - (new TextureExportSettings("normal", mipmaps: true, sRGB: false), "_Impostors_Normal_Atlas"), - (new TextureExportSettings("metallic_gloss_depth", mipmaps: true, sRGB: false, uncompressed: true), "_Impostors_Metallic_Gloss_Depth_Atlas") - }; - - Texture2D[] atlases = { albedoAtlas, normalAtlas, combinedAtlas }; - string[] paths = new string[exportSettings.Length]; - for (int i = 0; i < exportSettings.Length; i++) - SaveAndConfigureTexture(atlases[i], exportSettings[i].settings, baseName, out paths[i]); - - AssetDatabase.Refresh(); - - for (int i = 0; i < paths.Length; i++) - ConfigureTextureImporter(paths[i], exportSettings[i].settings); - - // Wait for shader compiler then create impostor - WaitForCompilerThenCreateImpostor(paths, exportSettings, baseName); - } - - void WaitForCompilerThenCreateImpostor(string[] paths, (TextureExportSettings settings, string materialProp)[] exportSettings, string baseName) - { - if (EditorApplication.isCompiling) - { - EditorApplication.delayCall += () => WaitForCompilerThenCreateImpostor(paths, exportSettings, baseName); - return; - } - - Texture2D[] textures = new Texture2D[paths.Length]; - for (int i = 0; i < paths.Length; i++) - textures[i] = AssetDatabase.LoadAssetAtPath<Texture2D>(paths[i]); - - if (textures[0] != null) - { - DestroyExistingImpostor(); - - Shader shader = Shader.Find("yum_food/3ner"); - if (shader == null) { Debug.LogError("Shader not found"); return; } - - Bounds bounds = GetCombinedBounds(); - float radius = GetBoundingSphereRadius(); - - impostorMaterial = new Material(shader); - impostorMaterial.enableInstancing = true; - for (int i = 0; i < textures.Length; i++) - impostorMaterial.SetTexture(exportSettings[i].materialProp, textures[i]); - impostorMaterial.SetInt("_Impostors_Grid_Resolution", gridResolution); - impostorMaterial.SetFloat("_Impostors_Sphere_Radius", radius); - impostorMaterial.SetFloat("_Impostors_Near_Clip", nearClippingDistance); - impostorMaterial.SetFloat("_Impostors_Far_Clip", radius * 2f + nearClippingDistance); - impostorMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); - impostorMaterial.SetFloat("_Impostors_Enabled", 1); - impostorMaterial.SetFloat("_Impostors_Parallax", 1); - impostorMaterial.SetFloat("_Cull", (float)UnityEngine.Rendering.CullMode.Front); - AssetDatabase.CreateAsset(impostorMaterial, Path.Combine(OutputFolder, $"{baseName}_mat.mat")); - - impostorObject = GameObject.CreatePrimitive(PrimitiveType.Quad); - impostorObject.name = "Impostor"; - impostorObject.transform.position = bounds.center; - impostorObject.transform.localScale = Vector3.one * radius * 2.0f; - impostorObject.transform.SetParent(transform, true); - DestroyImmediate(impostorObject.GetComponent<Collider>()); - impostorObject.GetComponent<MeshRenderer>().sharedMaterial = impostorMaterial; - - SetRenderersEnabled(false); - Debug.Log("Impostor baking complete!"); - } - } - - public void DestroyExistingImpostor() - { - if (impostorObject != null) DestroyImmediate(impostorObject); - impostorObject = null; - impostorMaterial = null; - } - - public void ToggleRenderers() - { - if (originalMesh == null) return; - bool showing = originalMesh.GetComponentInChildren<Renderer>()?.enabled ?? false; - SetRenderersEnabled(!showing); - } - - void SetRenderersEnabled(bool enabled) - { - if (originalMesh == null) return; - foreach (Renderer r in originalMesh.GetComponentsInChildren<Renderer>(true)) - r.enabled = enabled; - if (impostorObject != null) - { - Renderer impostorRenderer = impostorObject.GetComponent<Renderer>(); - if (impostorRenderer != null) impostorRenderer.enabled = !enabled; - } - } -} - -[CustomEditor(typeof(Impostors))] -public class ImpostorsEditor : Editor -{ - public override void OnInspectorGUI() - { - DrawDefaultInspector(); - Impostors s = (Impostors)target; - - GUILayout.Space(10); - GUILayout.Label("Impostor Management", EditorStyles.boldLabel); - - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Create Impostor", GUILayout.Height(40))) s.BakeTexture(); - GUI.enabled = s.HasImpostor; - if (GUILayout.Button("Destroy Impostor", GUILayout.Height(40))) - { - s.DestroyExistingImpostor(); - s.DestroyExistingCameras(); - } - GUI.enabled = true; - EditorGUILayout.EndHorizontal(); - - if (s.originalMesh != null && GUILayout.Button("Toggle Visibility", GUILayout.Height(30))) - s.ToggleRenderers(); - } -} -#endif // UNITY_EDITOR @@ -177,7 +177,12 @@ float4 brdf(Pbr pbr, LightData data) { #endif specular *= data.common.spec_ao; - return float4(diffuse + specular, 1); +#if defined(_EMISSIONS) && defined(FORWARD_BASE_PASS) + float3 emission = pbr.emission; +#else + float3 emission = 0; +#endif + return float4(diffuse + specular + emission, 1); } #endif // __BRDF_INC diff --git a/features.cginc b/features.cginc index bd527ba..2919950 100755 --- a/features.cginc +++ b/features.cginc @@ -1,6 +1,10 @@ #ifndef __FEATURES_INC #define __FEATURES_INC +//ifex _Emissions_Enabled==0 +#pragma shader_feature_local _EMISSIONS +//endex + //ifex _Gradient_Normals_Enabled==0 #pragma shader_feature_local _GRADIENT_NORMALS //endex @@ -154,14 +158,6 @@ #pragma shader_feature_local _RAY_MARCHING_HEXAGON //endex -//ifex _Impostors_Enabled==0 -#pragma shader_feature_local _IMPOSTORS -//endex - -//ifex _Impostors_Depth_Enabled==0 -#pragma shader_feature_local _IMPOSTORS_DEPTH -//endex - //ifex _Matcap0_Enabled==0 #pragma shader_feature_local _MATCAP0 #pragma shader_feature_local _MATCAP0_QUANTIZATION diff --git a/globals.cginc b/globals.cginc index 00dd279..2f4dc1e 100755 --- a/globals.cginc +++ b/globals.cginc @@ -32,6 +32,14 @@ float _Specular_AA_Variance; float _Specular_AA_Threshold; float _BRDF_Specular_Min_Denom; +#if defined(_EMISSIONS) +texture2D _EmissionMap; +float4 _EmissionMap_ST; +texture2D _EmissionMask; +float4 _EmissionMask_ST; +float3 _EmissionColor; +#endif // _EMISSIONS + #if defined(_OUTLINES) float4 _Outlines_Color; float _Outlines_Width; @@ -231,23 +239,6 @@ float _Parallax_Heightmap_Bias; float _Parallax_Heightmap_Ray_Marching_Steps; #endif // _PARALLAX_HEIGHTMAP_RAY_MARCHING -#if defined(_IMPOSTORS) -Texture2D _Impostors_Atlas; -float4 _Impostors_Atlas_TexelSize; -Texture2D _Impostors_Normal_Atlas; -// R=metallic, G=gloss, B=depth -Texture2D _Impostors_Metallic_Gloss_Depth_Atlas; -int _Impostors_Grid_Resolution; -float _Impostors_Sphere_Radius; -float _Impostors_Near_Clip; -float _Impostors_Far_Clip; -float _Impostors_Cutoff; -float _Impostors_Parallax; -float _Impostors_Debug_Mode; -float _Impostors_Debug_Depth; -float3 _Impostors_Main_Camera_Pos; -#endif // _IMPOSTORS - #define MATCAP_MODE_REPLACE 0 #define MATCAP_MODE_ADD 1 #define MATCAP_MODE_MULTIPLY 2 diff --git a/impostor.cginc b/impostor.cginc deleted file mode 100755 index 5674c02..0000000 --- a/impostor.cginc +++ /dev/null @@ -1,326 +0,0 @@ -#ifndef __IMPOSTOR_INC -#define __IMPOSTOR_INC - -#include "UnityCG.cginc" -#include "globals.cginc" -#include "vertex_deformation.hlsl" - -struct ImpostorResult { - float4 albedo; - float3 normal; - float metallic; - float smoothness; - float3 objPos; -}; - -#if defined(_IMPOSTORS) -float2 HemiOctEncode(float3 N) { - N.y = max(N.y, 1e-4); - float3 p = hemi_octahedron_to_plane(normalize(N), 0, float3(1,0,0), float3(0,1,0), 1); - return p.xz; -} - -float3 HemiOctDecode(float2 uv) { - return normalize(plane_to_hemi_octahedron(float3(uv.x, 0, uv.y), 0, float3(1,0,0), float3(0,1,0), 1)); -} - -void FrameBasis(float3 frameDir, out float3 planeX, out float3 planeY, out float3 planeN) { - planeN = normalize(frameDir); - float3 up = abs(planeN.y) > 0.999 ? float3(0,0,1) : float3(0,1,0); - planeX = normalize(cross(planeN, up)); - planeY = cross(planeX, planeN); // Already normalized since planeX and planeN are orthonormal -} - -void BillboardBasis(float3 fwd, out float3 right, out float3 up) { - right = abs(fwd.y) > 0.999 ? float3(-1,0,0) : normalize(cross(float3(0,1,0), fwd)); - up = cross(fwd, right); -} - -float2 GridFromDir(float3 viewDir, float gridRes) { - float2 uv = HemiOctEncode(viewDir) * 0.5 + 0.5; - return clamp(uv * (gridRes - 1.0), 0.0, gridRes - 1.0); -} - -float3 DirFromCell(float2 cell, float gridRes) { - float2 uv = cell * rcp(max(1.0, gridRes - 1.0)) * 2.0 - 1.0; - return HemiOctDecode(uv); -} - -float3 BarycentricWeights3(float2 gridFrac, bool isBottomRight) { - float3 br = float3(1.0 - gridFrac.x, gridFrac.x - gridFrac.y, gridFrac.y); - float3 tl = float3(1.0 - gridFrac.y, gridFrac.y - gridFrac.x, gridFrac.x); - return isBottomRight ? br : tl; -} - -float2 VirtualPlaneUV(float3 planeX, float3 planeY, float3 planeN, float3 pivotToCam, float3 vertexToCam) { - float projPivot = dot(planeN, pivotToCam); - float projVertex = dot(planeN, vertexToCam); - projVertex = (abs(projVertex) < 1e-4) ? (projVertex < 0 ? -1e-4 : 1e-4) : projVertex; - float ratio = projPivot / projVertex; - - float3 offset = vertexToCam * ratio - pivotToCam; - - return 0.5 - float2(dot(planeX, offset), dot(planeY, offset)); -} - -float2 ClampUvInCell(float2 uv, float2 halfTexelInCell) { - return clamp(saturate(uv), halfTexelInCell, 1.0 - halfTexelInCell); -} - -struct ImpostorSample { - float4 albedo; - float4 normal; - float2 metallicGloss; - float depth; -}; - -ImpostorSample SampleImpostorCell(float2 cell, float2 uvInCell, float invGridRes) { - float2 atlasUv = (cell + uvInCell) * invGridRes; - float2 gradX = ddx(uvInCell) * invGridRes; - float2 gradY = ddy(uvInCell) * invGridRes; - - ImpostorSample s; - s.albedo = _Impostors_Atlas.SampleGrad(bilinear_clamp_s, atlasUv, gradX, gradY); - s.normal = _Impostors_Normal_Atlas.SampleGrad(bilinear_clamp_s, atlasUv, gradX, gradY); - float4 mgd = _Impostors_Metallic_Gloss_Depth_Atlas.SampleGrad(bilinear_clamp_s, atlasUv, gradX, gradY); - s.metallicGloss = mgd.rg; - s.depth = mgd.b; - return s; -} - -float2 ImpostorParallaxOffset(float3 planeX, float3 planeY, float3 planeN, float3 pivotToCamOS, float encodedDepth, - float impostorNear, float impostorFar, float impostorRadius) { - float2 camXY = float2(dot(pivotToCamOS, planeX), dot(pivotToCamOS, planeY)); - float camZ = dot(pivotToCamOS, planeN); - camZ = (abs(camZ) < 1e-4) ? (camZ < 0 ? -1e-4 : 1e-4) : camZ; - - float worldSpaceDepth = lerp(impostorNear, impostorFar, encodedDepth); - float depth01 = (worldSpaceDepth - impostorNear) / (2.0 * impostorRadius); - float height = 0.5 - depth01; - - return (camXY / camZ) * height; -} - -float3 ReconstructObjectOffset(float3 planeX, float3 planeY, float3 planeN, float2 uv, float encodedDepth, - float impostorNear, float impostorFar, float impostorRadius) { - float2 offsetXY = (0.5 - uv) * (2.0 * impostorRadius); - float worldSpaceDepth = lerp(impostorNear, impostorFar, encodedDepth); - float offsetZ = (impostorRadius + impostorNear) - worldSpaceDepth; - - return offsetXY.x * planeX + offsetXY.y * planeY + offsetZ * planeN; -} - -ImpostorSample BlendImpostorSamples(ImpostorSample s0, ImpostorSample s1, ImpostorSample s2, float3 bw) { - ImpostorSample result; - float3 alpha = float3(s0.albedo.a, s1.albedo.a, s2.albedo.a); - float alphaOut = dot(alpha, bw); - float3 alphaBw = alpha * bw * rcp(max(alphaOut, 1e-4)); - - result.albedo = float4(s0.albedo.rgb * alphaBw.x + s1.albedo.rgb * alphaBw.y + s2.albedo.rgb * alphaBw.z, alphaOut); - result.normal = s0.normal * alphaBw.x + s1.normal * alphaBw.y + s2.normal * alphaBw.z; - result.metallicGloss = s0.metallicGloss * alphaBw.x + s1.metallicGloss * alphaBw.y + s2.metallicGloss * alphaBw.z; - return result; -} -#endif // _IMPOSTORS - -void impostor_vert(inout float3 vertexOS) { -#if defined(_IMPOSTORS) - float3 center = mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz; - -#if defined(_INSTANCE_TEXTURE_OFFSET) && defined(UNITY_INSTANCING_ENABLED) - float3 instanceCenter; - float4 instanceRotation; - float3 instanceScale; - if (get_instance_transform(instanceCenter, instanceRotation, instanceScale)) { - center = mul(unity_ObjectToWorld, float4(instanceCenter, 1.0)).xyz; - } -#endif // _INSTANCE_TEXTURE_OFFSET && UNITY_INSTANCING_ENABLED - -#ifdef SHADOW_CASTER_PASS - float3 camPos = _Impostors_Main_Camera_Pos; -#else - float3 camPos = _WorldSpaceCameraPos; -#endif // SHADOW_CASTER_PASS - - float3 viewWS = normalize(camPos - center); - float3 right, up; - BillboardBasis(viewWS, right, up); - float radiusScale = _Impostors_Sphere_Radius * 2.0; - float3 worldPos = center + (vertexOS.x * right + vertexOS.y * up) * radiusScale; - vertexOS = mul(unity_WorldToObject, float4(worldPos, 1.0)).xyz; -#endif // _IMPOSTORS -} - -ImpostorResult impostor_frag(float3 worldPos) { - ImpostorResult result = (ImpostorResult)0; -#if defined(_IMPOSTORS) - - float3 center = mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz; - float4 instanceRotation = float4(0, 0, 0, 1); - float instanceScale = 1.0; - bool hasInstanceTransform = false; - -#if defined(_INSTANCE_TEXTURE_OFFSET) && defined(UNITY_INSTANCING_ENABLED) - float3 instanceCenter; - float3 instanceScale3; - if (get_instance_transform(instanceCenter, instanceRotation, instanceScale3)) { - center = mul(unity_ObjectToWorld, float4(instanceCenter, 1.0)).xyz; - instanceScale = max(instanceScale3.x, max(instanceScale3.y, instanceScale3.z)); - hasInstanceTransform = true; - } -#endif // _INSTANCE_TEXTURE_OFFSET && UNITY_INSTANCING_ENABLED - -#ifdef SHADOW_CASTER_PASS - float3 camPos = _Impostors_Main_Camera_Pos; -#else - float3 camPos = _WorldSpaceCameraPos; -#endif - float3 camToCenter = camPos - center; - float3 viewDir = normalize(worldPos - camPos); - - float impostorRadius = _Impostors_Sphere_Radius * instanceScale; - float impostorNear = _Impostors_Near_Clip * instanceScale; - float impostorFar = _Impostors_Far_Clip * instanceScale; - - float b = dot(camToCenter, viewDir); - float c = dot(camToCenter, camToCenter) - impostorRadius * impostorRadius; - clip(b * b - c); - - float3x3 worldToObject = (float3x3)unity_WorldToObject; - float3 viewOS = mul(worldToObject, normalize(camToCenter)); - - float3 pivotToCamOS = mul(worldToObject, camToCenter); - float3 vertexPosOS = mul(worldToObject, worldPos - center); - - if (hasInstanceTransform) { - float4 instanceRotationInv = qconj(instanceRotation); - viewOS = qrotate(instanceRotationInv, viewOS); - pivotToCamOS = qrotate(instanceRotationInv, pivotToCamOS); - vertexPosOS = qrotate(instanceRotationInv, vertexPosOS); - } - float3 vertexToCamOS = pivotToCamOS - vertexPosOS; - - float gridRes = (float)_Impostors_Grid_Resolution; - float invGridRes = rcp(gridRes); - float2 halfTexelInCell = 0.5 * _Impostors_Atlas_TexelSize.xy * gridRes; - - float2 grid = GridFromDir(viewOS, gridRes); - float2 gridFloor = floor(grid); - float2 gridFrac = frac(grid); - - bool isBottomRight = gridFrac.x > gridFrac.y; - float3 bw = BarycentricWeights3(gridFrac, isBottomRight); - - float2 cell0 = clamp(gridFloor, 0, gridRes - 1); - float2 cell1 = clamp(gridFloor + (isBottomRight ? float2(1,0) : float2(0,1)), 0, gridRes - 1); - float2 cell2 = clamp(gridFloor + float2(1,1), 0, gridRes - 1); - - float3 frameDir0 = DirFromCell(cell0, gridRes); - float3 frameDir1 = DirFromCell(cell1, gridRes); - float3 frameDir2 = DirFromCell(cell2, gridRes); - - float3 planeX0, planeY0, planeN0; - float3 planeX1, planeY1, planeN1; - float3 planeX2, planeY2, planeN2; - FrameBasis(frameDir0, planeX0, planeY0, planeN0); - FrameBasis(frameDir1, planeX1, planeY1, planeN1); - FrameBasis(frameDir2, planeX2, planeY2, planeN2); - - float2 uvBase0 = ClampUvInCell(VirtualPlaneUV(planeX0, planeY0, planeN0, pivotToCamOS, vertexToCamOS), halfTexelInCell); - float2 uvBase1 = ClampUvInCell(VirtualPlaneUV(planeX1, planeY1, planeN1, pivotToCamOS, vertexToCamOS), halfTexelInCell); - float2 uvBase2 = ClampUvInCell(VirtualPlaneUV(planeX2, planeY2, planeN2, pivotToCamOS, vertexToCamOS), halfTexelInCell); - - ImpostorSample s0 = SampleImpostorCell(cell0, uvBase0, invGridRes); - ImpostorSample s1 = SampleImpostorCell(cell1, uvBase1, invGridRes); - ImpostorSample s2 = SampleImpostorCell(cell2, uvBase2, invGridRes); - - float baseAlpha0 = s0.albedo.a, depth0 = s0.depth; - float baseAlpha1 = s1.albedo.a, depth1 = s1.depth; - float baseAlpha2 = s2.albedo.a, depth2 = s2.depth; - - float baseAlphaBlended = dot(float3(baseAlpha0, baseAlpha1, baseAlpha2), bw); - float parallaxStrength = _Impostors_Parallax * smoothstep(_Impostors_Cutoff, 1.0, baseAlphaBlended); - float depthBlended = dot(float3(depth0, depth1, depth2), bw); - - [branch] - if (_Impostors_Debug_Depth > 0.5) { - result.albedo = float4(depthBlended.xxx, 1); - return result; - } - - float2 parallaxOffset0 = 0, parallaxOffset1 = 0, parallaxOffset2 = 0; - bool needsParallaxResample = false; - - [branch] - if (parallaxStrength > 0.001) { - parallaxOffset0 = ImpostorParallaxOffset(planeX0, planeY0, planeN0, pivotToCamOS, depthBlended, - impostorNear, impostorFar, impostorRadius) * parallaxStrength; - parallaxOffset1 = ImpostorParallaxOffset(planeX1, planeY1, planeN1, pivotToCamOS, depthBlended, - impostorNear, impostorFar, impostorRadius) * parallaxStrength; - parallaxOffset2 = ImpostorParallaxOffset(planeX2, planeY2, planeN2, pivotToCamOS, depthBlended, - impostorNear, impostorFar, impostorRadius) * parallaxStrength; - - float maxOffsetSq = max(max(dot(parallaxOffset0, parallaxOffset0), dot(parallaxOffset1, parallaxOffset1)), dot(parallaxOffset2, parallaxOffset2)); - needsParallaxResample = maxOffsetSq > 0.00005; - } - - float2 finalUv0 = uvBase0, finalUv1 = uvBase1, finalUv2 = uvBase2; - - [branch] - if (needsParallaxResample) { - float2 uv0 = ClampUvInCell(uvBase0 + parallaxOffset0, halfTexelInCell); - float2 uv1 = ClampUvInCell(uvBase1 + parallaxOffset1, halfTexelInCell); - float2 uv2 = ClampUvInCell(uvBase2 + parallaxOffset2, halfTexelInCell); - - ImpostorSample ps0 = SampleImpostorCell(cell0, uv0, invGridRes); - ImpostorSample ps1 = SampleImpostorCell(cell1, uv1, invGridRes); - ImpostorSample ps2 = SampleImpostorCell(cell2, uv2, invGridRes); - - if (ps0.albedo.a >= _Impostors_Cutoff || baseAlpha0 <= _Impostors_Cutoff) { - s0 = ps0; - finalUv0 = uv0; - } - if (ps1.albedo.a >= _Impostors_Cutoff || baseAlpha1 <= _Impostors_Cutoff) { - s1 = ps1; - finalUv1 = uv1; - } - if (ps2.albedo.a >= _Impostors_Cutoff || baseAlpha2 <= _Impostors_Cutoff) { - s2 = ps2; - finalUv2 = uv2; - } - } - - ImpostorSample blended = BlendImpostorSamples(s0, s1, s2, bw); - - [branch] - if (_Impostors_Debug_Mode > 0.5) { - result.albedo = float4(bw, 1); - return result; - } - - clip(blended.albedo.a - _Impostors_Cutoff); - - result.albedo = blended.albedo; - float3 normalOS = blended.normal.xyz * 2.0 - 1.0; - if (hasInstanceTransform) { - normalOS = qrotate(instanceRotation, normalOS); - } - result.normal = normalize(mul((float3x3)unity_ObjectToWorld, normalOS)); - result.metallic = blended.metallicGloss.r; - result.smoothness = blended.metallicGloss.g; - -#if defined(_IMPOSTORS_DEPTH) - float3 offset0 = ReconstructObjectOffset(planeX0, planeY0, planeN0, finalUv0, depth0, - impostorNear, impostorFar, impostorRadius); - float3 offset1 = ReconstructObjectOffset(planeX1, planeY1, planeN1, finalUv1, depth1, - impostorNear, impostorFar, impostorRadius); - float3 offset2 = ReconstructObjectOffset(planeX2, planeY2, planeN2, finalUv2, depth2, - impostorNear, impostorFar, impostorRadius); - result.objPos = offset0 * bw.x + offset1 * bw.y + offset2 * bw.z; -#endif - - return result; -#endif // _IMPOSTORS -} - -#endif // __IMPOSTOR_INC diff --git a/interpolators.cginc b/interpolators.cginc index a6a24e9..5f993db 100755 --- a/interpolators.cginc +++ b/interpolators.cginc @@ -34,8 +34,7 @@ struct v2f { UNITY_LIGHTING_COORDS(7,8) // TODO figure out some metaprogramming or preprocessor to better allocate optional texcoords :( #if defined(_VERTEX_DEFORMATION_FRAGMENT_NORMALS) || \ - defined(_VERTEX_DEFORMATION_TESSELLATION) || \ - defined(_IMPOSTORS) && defined(_INSTANCE_TEXTURE_OFFSET) + defined(_VERTEX_DEFORMATION_TESSELLATION) float3 objPos_orig : TEXCOORD9; #endif #if defined(_RAY_MARCHING_BAKED_ORIGINS) diff --git a/lighting.cginc b/lighting.cginc index 2820c12..f5957b8 100755 --- a/lighting.cginc +++ b/lighting.cginc @@ -208,7 +208,7 @@ float4 getIndirectDiffuse(v2f i, Pbr pbr, inout LightData light) { ); // Multiply unit vector by L1 matrix to get vector pointing in direction of // light. - float3 dom_dir = normalize(mul(float3(1,1,1), mat)); + float3 dom_dir = normalize(mul(mat, float3(1,1,1))); float light_amount = dot(dom_dir, pbr.normal); float3 shadow_color = lerp( _Shadow_0_Color.rgb, diff --git a/matcap.cginc b/matcap.cginc index d9391af..462ba9b 100644 --- a/matcap.cginc +++ b/matcap.cginc @@ -3,10 +3,15 @@ #include "globals.cginc" #include "lighting.cginc" +#include "math.cginc" #include "pbr.cginc" #include "texture_utils.cginc" #if defined(_MATCAP0) || defined(_MATCAP1) || defined(_RIM_LIGHTING0) +#define HAS_MATCAP_RL +#endif + +#if defined(HAS_MATCAP_RL) float2 getMatcapUV(v2f i, Pbr pbr) { const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(pbr.normal, 0))); const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(-i.eyeVec.xyz, 0))); @@ -52,10 +57,10 @@ float2 quantizeMatcapUV(float2 muv, float muv_r, float steps) { const float epsilon = 1e-4f; return muv_r_q * (muv / max(epsilon, muv_r)); } -#endif // _MATCAP0 || _RIM_LIGHTING0 +#endif // HAS_MATCAP_RL void applyMatcapsAndRimLighting(v2f i, inout Pbr pbr, inout LightData light_data) { -#if defined(_MATCAP0) || defined(_MATCAP1) || defined(_RIM_LIGHTING0) +#if defined(HAS_MATCAP_RL) float2 muv = getMatcapUV(i, pbr); float2 muv_centered = muv * 2 - 1; float muv_r = length(muv_centered); @@ -109,7 +114,22 @@ void applyMatcapsAndRimLighting(v2f i, inout Pbr pbr, inout LightData light_data #if defined(_RIM_LIGHTING0_QUANTIZATION) rl0_dist = floor(rl0_dist * _Rim_Lighting0_Quantization_Steps) / _Rim_Lighting0_Quantization_Steps; #endif - float3 rl0 = lerp(1, _Rim_Lighting0_Color, rl0_dist); + + float3 rl0; + switch(_Rim_Lighting0_Mode) { + case MATCAP_MODE_ADD: + // Fall through. + case MATCAP_MODE_SUBTRACT: + rl0 = lerp(0, _Rim_Lighting0_Color, rl0_dist); + break; + case MATCAP_MODE_MULTIPLY: + rl0 = lerp(1, _Rim_Lighting0_Color, rl0_dist); + break; + default: + rl0 = lerp(pbr.albedo.xyz, _Rim_Lighting0_Color, rl0_dist); + break; + } + #if defined(_RIM_LIGHTING0_MASK) float rl0_mask = _Rim_Lighting0_Mask.Sample(linear_repeat_s, UV_SCOFF(i, _Rim_Lighting0_Mask_ST, /*which_channel=*/0)); #else @@ -100,5 +100,10 @@ float3 blendNormalsHill12(float3 n0, float3 n1) { return normalize(n0 * dot(n0, n1) - n1 * n0.z); } +// https://en.wikipedia.org/wiki/Relative_luminance +float luminance(float3 rgb) { + return dot(float3(0.2126, 0.7152, 0.0722), rgb); +} + #endif // __MATH_INC @@ -6,7 +6,6 @@ #include "instancing.cginc" #include "interpolators.cginc" #include "texture_utils.cginc" -#include "impostor.cginc" // From filament: min roughness s.t. MIN_PERCEPTUAL_ROUGHNESS^4 > 0 in target // precision. Although we use fp32, the higher min roughness gives us a broader @@ -22,6 +21,9 @@ struct Pbr { float roughness_perceptual; float roughness; float metallic; +#if defined(_EMISSIONS) && defined(FORWARD_BASE_PASS) + float3 emission; +#endif #if defined(_AMBIENT_OCCLUSION) float ao; #endif @@ -33,10 +35,6 @@ struct Pbr { float cc_roughness_perceptual; float cc_strength; #endif -#if defined(_IMPOSTORS_DEPTH) - float3 objPos; - float debug; // TODO rm -#endif }; #if defined(_PARALLAX_HEIGHTMAP) @@ -187,16 +185,6 @@ Pbr getPbr(v2f i) { float2 uv_parallax = i.uv01.xy; #endif // _PARALLAX_HEIGHTMAP -#if defined(_IMPOSTORS) - ImpostorResult imp = impostor_frag(i.worldPos); - pbr.albedo = imp.albedo * _Color; - pbr.normal = imp.normal; - pbr.smoothness = imp.smoothness; - pbr.metallic = imp.metallic; -#if defined(_IMPOSTORS_DEPTH) - pbr.objPos = imp.objPos; -#endif -#else // !_IMPOSTORS #if defined(OUTLINES_PASS) && defined(_OUTLINES) pbr.albedo = _Outlines_Color; #else @@ -229,7 +217,6 @@ Pbr getPbr(v2f i) { float4 metallic_gloss = _MetallicGlossMap.Sample(aniso4_trilinear_repeat_s, uv_parallax * _MetallicGlossMap_ST.xy); pbr.smoothness = metallic_gloss.a * _Glossiness; pbr.metallic = metallic_gloss.r * _Metallic; -#endif // _IMPOSTORS #if defined(_CLEARCOAT) pbr.cc_roughness = _Clearcoat_Roughness; @@ -242,6 +229,15 @@ Pbr getPbr(v2f i) { pbr.ao = saturate(lerp(1.0, _OcclusionMap.Sample(bilinear_repeat_s, i.uv01.xy).r, _OcclusionStrength)); #endif +#if defined(_EMISSIONS) && defined(FORWARD_BASE_PASS) + float3 emission_tint = _EmissionColor; + float3 emission_color = _EmissionMap.Sample(trilinear_repeat_s, + i.uv01.xy * _EmissionMap_ST.xy + _EmissionMap_ST.zw); + float emission_mask = _EmissionMask.Sample(trilinear_repeat_s, + i.uv01.xy * _EmissionMask_ST.xy + _EmissionMask_ST.zw).r; + pbr.emission = emission_tint * emission_color * emission_mask; +#endif + return pbr; } @@ -57,11 +57,6 @@ float3 HSVtoRGB(in float3 HSV) return ((RGB - 1) * HSV.y + 1) * HSV.z; } -float calculateluminance(float3 color) -{ - return color.r * 0.299 + color.g * 0.587 + color.b * 0.114; -} - bool SceneHasReflections() { float width, height; |
