summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x3ner.cginc24
-rwxr-xr-x3ner.shader31
-rwxr-xr-xScripts/Impostors.cs649
-rwxr-xr-xbrdf.cginc7
-rwxr-xr-xfeatures.cginc12
-rwxr-xr-xglobals.cginc25
-rwxr-xr-ximpostor.cginc326
-rwxr-xr-xinterpolators.cginc3
-rwxr-xr-xlighting.cginc2
-rw-r--r--matcap.cginc26
-rwxr-xr-xmath.cginc5
-rwxr-xr-xpbr.cginc28
-rw-r--r--poi.cginc5
13 files changed, 73 insertions, 1070 deletions
diff --git a/3ner.cginc b/3ner.cginc
index e13332e..8ddbce8 100755
--- a/3ner.cginc
+++ b/3ner.cginc
@@ -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
diff --git a/brdf.cginc b/brdf.cginc
index 0e1cc02..d73bde8 100755
--- a/brdf.cginc
+++ b/brdf.cginc
@@ -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
diff --git a/math.cginc b/math.cginc
index 3d7e92e..e2d4169 100755
--- a/math.cginc
+++ b/math.cginc
@@ -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
diff --git a/pbr.cginc b/pbr.cginc
index c89a97c..9fbf2de 100755
--- a/pbr.cginc
+++ b/pbr.cginc
@@ -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;
}
diff --git a/poi.cginc b/poi.cginc
index b92e414..1815af9 100644
--- a/poi.cginc
+++ b/poi.cginc
@@ -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;