diff --git a/.gitignore b/.gitignore index d55d4ee..8f9fa90 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,5 @@ Hoyo2VRC.meta Deployment.meta Editor/Deployment.meta /Scripts/Editor/Deployment +/Private +Private.meta diff --git a/Scripts/Editor/Post Processing/HoyoToonPostEditor.cs b/Scripts/Editor/Post Processing/HoyoToonPostEditor.cs index 7890828..ee7e607 100644 --- a/Scripts/Editor/Post Processing/HoyoToonPostEditor.cs +++ b/Scripts/Editor/Post Processing/HoyoToonPostEditor.cs @@ -1,5 +1,6 @@ #if UNITY_EDITOR using UnityEditor; +using UnityEditorInternal; using UnityEngine; namespace HoyoToon @@ -48,6 +49,7 @@ public override void OnInspectorGUI() } } + // Preset settings ShowPresets = EditorGUILayout.BeginFoldoutHeaderGroup(ShowPresets, "Preset Settings"); if (ShowPresets) @@ -101,7 +103,8 @@ public override void OnInspectorGUI() script.bloomMode = (HoyoToonPostProcess.BloomMode)EditorGUILayout.EnumPopup("Bloom Mode", script.bloomMode); script.bloomThreshold = EditorGUILayout.FloatField("Bloom Threshold", script.bloomThreshold); script.bloomIntensity = EditorGUILayout.FloatField("Bloom Intensity", script.bloomIntensity); - script.bloomWeights = EditorGUILayout.Vector4Field("Bloom Weights", script.bloomWeights); + script.bloomScalar = EditorGUILayout.FloatField("Bloom Scalar", script.bloomScalar); + // script.bloomWeights = EditorGUILayout.Vector4Field("Bloom Weights", script.bloomWeights); script.bloomColor = EditorGUILayout.ColorField("Bloom Color", script.bloomColor); script.blurSamples = EditorGUILayout.FloatField("Blur Samples", script.blurSamples); script.blurWeight = EditorGUILayout.FloatField("Blur Weight", script.blurWeight); @@ -136,6 +139,12 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFoldoutHeaderGroup(); } + + // Apply changes + if (GUI.changed) + { + EditorUtility.SetDirty(script); + } } } } diff --git a/Scripts/Post Processing/HoyoToonPostProcess.cs b/Scripts/Post Processing/HoyoToonPostProcess.cs index 9adb9ae..803a39b 100644 --- a/Scripts/Post Processing/HoyoToonPostProcess.cs +++ b/Scripts/Post Processing/HoyoToonPostProcess.cs @@ -1,9 +1,10 @@ using UnityEngine; +using UnityEngine.Rendering; namespace HoyoToon { [ExecuteInEditMode] - [ImageEffectAllowedInSceneView] + [DisallowMultipleComponent, ImageEffectAllowedInSceneView] public class HoyoToonPostProcess : MonoBehaviour { [SerializeField] @@ -33,6 +34,7 @@ public enum BloomMode public BloomMode bloomMode = BloomMode.Color; public float bloomThreshold = 0.7f; + public float bloomScalar = 0.7f; public float bloomIntensity = 0.5f; public Vector4 bloomWeights = new(0.1f, 0.2f, 0.3f, 0.4f); public Color bloomColor = Color.white; @@ -58,15 +60,43 @@ public enum ToneMode public float ACESParamD = 0.5f; public float ACESParamE = 1.5f; + + private CommandBuffer commandBuffer; + void OnEnable() { if (postShader == null) postShader = Shader.Find("Hidden/HoyoToon/Post Processing"); if (postMaterial == null) postMaterial = new Material(postShader); postMaterial.hideFlags = HideFlags.HideAndDontSave; + + commandBuffer = new CommandBuffer { name = "HoyoToon Post Processing" }; + + var camera = Camera.main; + if (camera != null) + { + camera.AddCommandBuffer(CameraEvent.BeforeImageEffects, commandBuffer); + } } void OnRenderImage(RenderTexture source, RenderTexture destination) { + commandBuffer.Clear(); + + if (bloomMode == BloomMode.Color) + { + // Add commands to the command buffer here + commandBuffer.Blit(source, destination, postMaterial); + } + else if (bloomMode == BloomMode.Brightness) + { + // Add commands to the command buffer here + commandBuffer.Blit(source, destination, postMaterial); + } + else + { + // Add commands to the command buffer here + commandBuffer.Blit(source, destination, postMaterial); + } if (bloomMode == BloomMode.Color) { postMaterial.SetFloat("_BloomMode", 1); @@ -86,6 +116,7 @@ void OnRenderImage(RenderTexture source, RenderTexture destination) if (toneMode == ToneMode.Off) postMaterial.SetFloat("_UseTonemap", 0); postMaterial.SetFloat("_BloomThreshold", bloomThreshold); postMaterial.SetFloat("_BloomIntensity", bloomIntensity); + postMaterial.SetFloat("_BloomScalar", bloomScalar); postMaterial.SetVector("_BloomWeights", bloomWeights); postMaterial.SetColor("_BloomColor", bloomColor); postMaterial.SetFloat("_BlurSamples", blurSamples); @@ -100,14 +131,19 @@ void OnRenderImage(RenderTexture source, RenderTexture destination) postMaterial.SetFloat("_ACESParamD", ACESParamD); postMaterial.SetFloat("_ACESParamE", ACESParamE); - postMaterial.SetTexture("_RenderTarget", source); + // var originalTex = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.ARGB32); + // RenderTexture.ReleaseTemporary(originalTex); + + var renderTextureMain = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.RGB111110Float); + Graphics.Blit(source, renderTextureMain); + postMaterial.SetTexture("_RenderTarget", renderTextureMain); + RenderTexture.ReleaseTemporary(renderTextureMain); int width = Mathf.RoundToInt(source.width * downsampleValue); int height = Mathf.RoundToInt(source.height * downsampleValue); - var bloomPre = RenderTexture.GetTemporary(width, height, 0, source.format); + var bloomPre = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32); - Graphics.Blit(source, bloomPre); - Graphics.Blit(null, bloomPre); + // Graphics.Blit(renderTextureMain, bloomPre); Graphics.Blit(source, bloomPre, postMaterial, 0); // prefilter postMaterial.SetTexture("_BloomTexturePre", bloomPre); @@ -119,6 +155,13 @@ void OnRenderImage(RenderTexture source, RenderTexture destination) void OnDisable() { + var camera = Camera.main; + if (camera != null && commandBuffer != null) + { + camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, commandBuffer); + commandBuffer.Release(); + commandBuffer = null; + } postMaterial = null; } } diff --git a/Shaders/Post Processing/HoyoToonPostProcessing.shader b/Shaders/Post Processing/HoyoToonPostProcessing.shader index d394f52..e85dcc4 100644 --- a/Shaders/Post Processing/HoyoToonPostProcessing.shader +++ b/Shaders/Post Processing/HoyoToonPostProcessing.shader @@ -7,11 +7,14 @@ Shader "Hidden/HoyoToon/Post Processing" HLSLINCLUDE //variables and textures + int _LayerMask; + float _BloomMode; float _BloomThreshold; float _BloomIntensity; float4 _BloomWeights; float4 _BloomColor; + float _BloomScalar; float _BlurWeight; float _UseTonemap; float _Exposure; @@ -50,7 +53,8 @@ Shader "Hidden/HoyoToon/Post Processing" const static int kernelSize = 9; - const static float kernelOffsets[9] = { + const static float kernelOffsets[9] = + { -4.0, -3.0, -2.0, @@ -61,7 +65,8 @@ Shader "Hidden/HoyoToon/Post Processing" 3.0, 4.0, }; - const static float kernel[9] = { + const static float kernel[9] = + { 0.01621622, 0.05405405, 0.12162162, @@ -82,18 +87,30 @@ Shader "Hidden/HoyoToon/Post Processing" } float3 LinearToLogC(float3 x) -{ - return 0.244161f * log10(5.555556f * x + 0.047996f) + 0.386036f; -} - - // functions : - float3 tonemap(float3 color) { - float3 c0 = (1.36 * color + 0.047) * color; - float3 c1 = (0.93 * color + 0.56) * color + 0.14; - return saturate(c0 / c1); + return 0.244161f * log10(5.555556f * x + 0.047996f) + 0.386036f; } + + + float3 newTonemap(float3 color, float3 bloom) + { + float3 final = color + bloom; + float3x3 whiteBalanceMatrix = + { + float3(1.00032, -0.00002, 0.00002), + float3(0.0004, 0.99977, 0.00008), + float3(-0.00002, -0.00002, 1.00058) + }; + + final = mul(whiteBalanceMatrix, final); + + final = final * _Exposure; + float3 f0 = (1.36 * final + 0.047) * final; + float3 f1 = (0.93 * final + 0.56) * final + 0.14; + final = saturate(f0 / f1); + return final; + } float3 CustomACESTonemapping(float3 x) @@ -103,47 +120,6 @@ Shader "Hidden/HoyoToon/Post Processing" return saturate((x * u) / (x * v + _ACESParamE)); } - static const float e = 2.71828f; - - float W_f(float x,float e0,float e1) { - if (x <= e0) - return 0; - if (x >= e1) - return 1; - float a = (x - e0) / (e1 - e0); - return a * a*(3.0f - 2.0f * a); - } - float H_f(float x, float e0, float e1) { - if (x <= e0) - return 0; - if (x >= e1) - return 1; - return (x - e0) / (e1 - e0); - } - - float GranTurismoTonemapper(float x) { - float P = 1.f; - float a = 1.f; - float m = 0.22f; - float l = 0.4f; - float c = 1.33f; - float b = 0.f; - float l0 = (P - m)*l / a; - float L0 = m - m / a; - float L1 = m + (1.f - m) / a; - float L_x = m + a * (x - m); - float T_x = m * pow(x / m, c) + b; - float S0 = m + l0; - float S1 = m + a * l0; - float C2 = a * P / (P - S1); - float S_x = P - (P - S1)*pow(e,-(C2*(x-S0)/P)); - float w0_x = 1 - W_f(x, 0.f, m); - float w2_x = H_f(x, m + l0, m + l0); - float w1_x = 1 - w0_x - w2_x; - float f_x = T_x * w0_x + L_x * w1_x + S_x * w2_x; - return f_x; - } - float _BlurSamples; static float pi = 3.1415926; static int samples = _BlurSamples; @@ -206,13 +182,12 @@ Shader "Hidden/HoyoToon/Post Processing" } else if(_BloomMode == 1) // if bloom mode is set to color { - color.xyz = max(color.xyz - _BloomThreshold, 0.0f); + color.xyz = max((color.xyz) - _BloomThreshold, 0.0f); } - return color; + return color * _BloomScalar; } - float4 fp_tone(v2f i) : SV_TARGET { // initialize inputs : @@ -228,21 +203,16 @@ Shader "Hidden/HoyoToon/Post Processing" { bloom = gaussianBlur(sampler_BloomTexturePre, _BloomTexturePre, uv, _BlurWeight * _MainTex_TexelSize); bloom = (bloom * _BloomIntensity) * _BloomColor; - toned.xyz = toned.xyz + bloom; + // toned.xyz = toned.xyz + bloom; } - toned.xyz = toned.xyz * _Exposure; - - if(_UseTonemap == 2) - { - toned.xyz = tonemap(toned.xyz); - } - else if(_UseTonemap == 1) + if(_UseTonemap != 3 ) { - toned.xyz = float3(GranTurismoTonemapper(toned.x), GranTurismoTonemapper(toned.y), GranTurismoTonemapper(toned.z)); + toned.xyz = newTonemap(toned.xyzw, bloom); } else if(_UseTonemap == 3) { + toned.xyz = toned.xyz * _Exposure; toned.xyz = CustomACESTonemapping(toned.xyz); if(_BloomMode > 0) { @@ -250,23 +220,26 @@ Shader "Hidden/HoyoToon/Post Processing" bloom = (bloom * _BloomIntensity) * _BloomColor; toned.xyz = toned.xyz + bloom; } + float3 colorLog = LinearToLogC(toned.xyz); + colorLog = lerp(ACEScc_MIDGRAY, colorLog, _Contrast); + toned.xyz = LogCToLinear(colorLog); + float3 luma = dot(toned.xyz, float3(0.2126f, 0.7152f, 0.0722f)); + toned.xyz = lerp(luma, toned, _Saturation); } - float3 colorLog = LinearToLogC(toned.xyz); - colorLog = lerp(ACEScc_MIDGRAY, colorLog, _Contrast); - toned.xyz = LogCToLinear(colorLog); - - - float3 luma = dot(toned.xyz, float3(0.2126f, 0.7152f, 0.0722f)); - toned.xyz = lerp(luma, toned, _Saturation); toned.w = original.w; return toned; } + float4 fp_final(v2f i) : SV_TARGET + { + return _RenderTarget.Sample(sampler_RenderTarget, i.uv); + } ENDHLSL + Subshader { Pass