Fix : 케비티 포스트 효과 추가 패치

This commit is contained in:
qsxft258@gmail.com 2025-08-24 20:18:49 +09:00
parent 2c4c4cc300
commit c34d6080e2
9 changed files with 127 additions and 22 deletions

View File

@ -24,6 +24,10 @@ namespace ScreenSpaceCavityCurvature
[HideInInspector] public Shader ssccShader;
[Header("Volume Integration")]
[Tooltip("Enable this to use Volume-based SSCC instead of this component. This component will be disabled when Volume SSCC is active.")]
public bool useVolumeSystem = true;
//
[Tooltip("Lerps the whole effect from 0 to 1.")] [Range(0f, 1f)] public float effectIntensity = 1f;
[Tooltip("Divides effect intensity by (depth * distanceFade).\nZero means effect doesn't fade with distance.")] [Range(0f, 1f)] public float distanceFade = 0f;
@ -73,6 +77,25 @@ namespace ScreenSpaceCavityCurvature
OutputEffectTo Output => debugMode != DebugMode.Disabled ? OutputEffectTo.Screen : output;
// Volume 시스템 확인 메서드 추가 (Built-in 렌더 파이프라인용)
private bool IsVolumeSystemActive()
{
if (!useVolumeSystem) return false;
try
{
// Built-in 렌더 파이프라인에서는 볼륨 시스템이 없으므로 항상 false 반환
// URP용 SSCC가 활성화되어 있는지 확인할 수 없으므로 기본적으로 비활성화
return false;
}
catch (System.Exception e)
{
Debug.LogWarning($"SSCC Volume system check failed: {e.Message}");
}
return false;
}
static class Pass
{
public const int Copy = 0;
@ -220,6 +243,26 @@ namespace ScreenSpaceCavityCurvature
void OnPreRender()
{
// 씬뷰에서는 SSCC 효과 비활성화
if (ssccCamera.cameraType == CameraType.SceneView)
{
if (cmdBuffer != null)
{
ClearCommandBuffer(cmdBuffer);
}
return;
}
// 볼륨 시스템이 활성화되어 있으면 이 컴포넌트는 비활성화
if (IsVolumeSystemActive())
{
if (cmdBuffer != null)
{
ClearCommandBuffer(cmdBuffer);
}
return;
}
if (ssccShader == null || ssccCamera == null) return;
FetchRenderParameters();

View File

@ -42,7 +42,7 @@ namespace ScreenSpaceCavityCurvature.Universal
//
[Header("(Make sure Post Processing and Depth Texture are enabled.)")]
[Tooltip("Lerps the whole effect from 0 to 1.")] public ClampedFloatParameter effectIntensity = new ClampedFloatParameter(1f, 0f, 1f);
[Tooltip("Lerps the whole effect from 0 to 1.")] public ClampedFloatParameter effectIntensity = new ClampedFloatParameter(0f, 0f, 1f);
[Tooltip("Divides effect intensity by (depth * distanceFade).\nZero means effect doesn't fade with distance.")] public ClampedFloatParameter distanceFade = new ClampedFloatParameter(0f, 0f, 1f);
[Space(6)]
@ -73,6 +73,11 @@ namespace ScreenSpaceCavityCurvature.Universal
[Space(6)]
[Tooltip("Screen: Applies the effect over the entire screen.\n\n_SSCCTexture: Instead of writing the effect to the screen, will write the effect into a global shader texture named _SSCCTexture, so you can sample it selectively in your shaders and exclude certain objects from receiving outlines etc. See \"Output To Texture Examples\" folder for example shaders.")] public OutputParameter output = new OutputParameter(OutputEffectTo.Screen);
[Space(6)]
[Header("NiloToon Integration")]
[Tooltip("Enable NiloToon character masking. When enabled, SSCC effect will not be applied to NiloToon characters.")] public BoolParameter enableNiloToonMasking = new BoolParameter(true);
//
public bool IsActive() => effectIntensity.value > 0f;

View File

@ -67,13 +67,14 @@ namespace ScreenSpaceCavityCurvature.Universal
public static int cavityValley = Shader.PropertyToID("_CavityDarks");
public static int globalSSCCTexture = Shader.PropertyToID("_SSCCTexture");
public static int niloToonPrepassBufferTex = Shader.PropertyToID("_NiloToonPrepassBufferTex");
}
Material mat { get; set; }
RenderTargetIdentifier source { get; set; }
CameraData cameraData { get; set; }
RenderTextureDescriptor sourceDesc { get; set; }
public void Setup(Shader shader, ScriptableRenderer renderer, RenderingData renderingData)
{
if (mat == null) mat = CoreUtils.CreateEngineMaterial(shader);
@ -157,6 +158,13 @@ namespace ScreenSpaceCavityCurvature.Universal
if (!sscc.IsActive()) return;
var cmd = CommandBufferPool.Get("SSCC");
// NiloToon prepass 텍스처는 이미 각 카메라에서 자동 생성되므로 그대로 사용
if (sscc.enableNiloToonMasking.value)
{
// NiloToon prepass 텍스처가 이미 전역으로 설정되어 있으므로 추가 설정 불필요
// _NiloToonPrepassBufferTex는 NiloToon 시스템에서 자동으로 관리됨
}
int div = sscc.cavityResolution.value == SSCC.CavityResolution.Full ? 1 : sscc.cavityResolution.value == SSCC.CavityResolution.HalfUpscaled ? 2 : 2;
cmd.GetTemporaryRT(ShaderProperties.cavityTex, sourceDesc.width / div, sourceDesc.height / div, 0, FilterMode.Bilinear, GraphicsFormat.R32G32B32A32_SFloat);
cmd.GetTemporaryRT(ShaderProperties.cavityTex1, sourceDesc.width / div, sourceDesc.height / div, 0, FilterMode.Bilinear, GraphicsFormat.R32G32B32A32_SFloat);
@ -224,18 +232,32 @@ namespace ScreenSpaceCavityCurvature.Universal
mat.SetFloat(ShaderProperties.cavityValley, sscc.cavityDarks.value * 2f);
}
void UpdateShaderKeywords()
private void UpdateShaderKeywords()
{
mat.shaderKeywords = new string[]
{
cameraData.camera.orthographic ? "ORTHOGRAPHIC_PROJECTION" : "__",
sscc.debugMode.value == SSCC.DebugMode.EffectOnly ? "DEBUG_EFFECT" : sscc.debugMode.value == SSCC.DebugMode.ViewNormals ? "DEBUG_NORMALS" : "__",
sscc.normalsSource.value == SSCC.PerPixelNormals.ReconstructedFromDepth ? "NORMALS_RECONSTRUCT" : "__",
sscc.cavitySamples.value == SSCC.CavitySamples.Low6 ? "CAVITY_SAMPLES_6" : sscc.cavitySamples.value == SSCC.CavitySamples.Medium8 ? "CAVITY_SAMPLES_8" : sscc.cavitySamples.value == SSCC.CavitySamples.High12 ? "CAVITY_SAMPLES_12" : sscc.cavitySamples.value == SSCC.CavitySamples.VeryHigh20 ? "CAVITY_SAMPLES_20" : "",
sscc.saturateCavity.value ? "SATURATE_CAVITY" : "__",
Output == SSCC.OutputEffectTo._SSCCTexture ? "OUTPUT_TO_TEXTURE" : "__",
sscc.cavityResolution.value == SSCC.CavityResolution.HalfUpscaled ? "UPSCALE_CAVITY" : "__"
};
if (mat == null) return;
// 디버그 모드 키워드 설정
bool debugEffect = sscc.debugMode.value == SSCC.DebugMode.EffectOnly;
bool debugNormals = sscc.debugMode.value == SSCC.DebugMode.ViewNormals;
CoreUtils.SetKeyword(mat, "DEBUG_EFFECT", debugEffect);
CoreUtils.SetKeyword(mat, "DEBUG_NORMALS", debugNormals);
// NiloToon 마스킹 키워드 설정
CoreUtils.SetKeyword(mat, "CHARACTER_MASKING", sscc.enableNiloToonMasking.value);
// 기타 키워드 설정
CoreUtils.SetKeyword(mat, "ORTHOGRAPHIC_PROJECTION", cameraData.camera.orthographic);
CoreUtils.SetKeyword(mat, "NORMALS_RECONSTRUCT", sscc.normalsSource.value == SSCC.PerPixelNormals.ReconstructedFromDepth);
CoreUtils.SetKeyword(mat, "SATURATE_CAVITY", sscc.saturateCavity.value);
CoreUtils.SetKeyword(mat, "OUTPUT_TO_TEXTURE", Output == SSCC.OutputEffectTo._SSCCTexture);
CoreUtils.SetKeyword(mat, "UPSCALE_CAVITY", sscc.cavityResolution.value == SSCC.CavityResolution.HalfUpscaled);
// Cavity 샘플 수 키워드 설정
CoreUtils.SetKeyword(mat, "CAVITY_SAMPLES_6", sscc.cavitySamples.value == SSCC.CavitySamples.Low6);
CoreUtils.SetKeyword(mat, "CAVITY_SAMPLES_8", sscc.cavitySamples.value == SSCC.CavitySamples.Medium8);
CoreUtils.SetKeyword(mat, "CAVITY_SAMPLES_12", sscc.cavitySamples.value == SSCC.CavitySamples.High12);
CoreUtils.SetKeyword(mat, "CAVITY_SAMPLES_20", sscc.cavitySamples.value == SSCC.CavitySamples.VeryHigh20);
}

View File

@ -4,6 +4,23 @@
#define SAMPLE(texture, sampler, uv) UNITY_SAMPLE_SCREENSPACE_TEXTURE(texture, uv)
#endif
// NiloToon 캐릭터 마스킹 함수 추가
inline float GetCharacterMask(float2 uv)
{
#if CHARACTER_MASKING
// NiloToon prepass 텍스처에서 캐릭터 영역 확인 (g 채널이 visible area)
// _NiloToonPrepassBufferTex는 NiloToon 시스템에서 자동으로 전역 설정됨
float mask = SAMPLE_TEXTURE2D_X(_NiloToonPrepassBufferTex, sampler_PointClamp, uv).g;
// 디버깅: 마스크 값이 0이면 캐릭터 영역, 1이면 배경 영역
// 텍스처가 없거나 제대로 설정되지 않은 경우를 대비해 안전장치 추가
// mask 값이 예상 범위를 벗어나면 마스킹을 비활성화
if (mask < 0.0 || mask > 1.0) return 1.0; // 안전장치
return mask > 0.0 ? 0.0 : 1.0; // 캐릭터 영역이면 0, 아니면 1
#else
return 1.0; // 마스킹 비활성화시 항상 1
#endif
}
//CAVITY V
#ifdef CAVITY_SAMPLES_6
#define CAVITY_SAMPLES 6
@ -255,6 +272,22 @@ float4 Composite_Frag(Varyings input) : SV_Target
//float depth01 = FetchRawDepth(uv);
//if (depth01 == 1.0 || depth01 == 0.0) return col;
// NiloToon 캐릭터 마스킹 적용
#if CHARACTER_MASKING
float mask = GetCharacterMask(uv);
// 디버깅: 마스크 값 확인
// mask가 0이면 캐릭터 영역이므로 원본 색상 반환
// mask가 1이면 배경 영역이므로 SSCC 효과 적용
// 디버깅용: 마스크 값을 시각적으로 확인 (임시로 주석 처리)
// return float4(mask, mask, mask, 1.0); // 마스크 값을 흰색으로 표시
if (mask < 0.5)
{
return untouchedCol; // 캐릭터 영역
}
#endif
float curvature = 0.0;
curvature = Curvature(uv, P);

View File

@ -22,6 +22,7 @@
#pragma multi_compile_local __ SATURATE_CAVITY
#pragma multi_compile_local __ OUTPUT_TO_TEXTURE
#pragma multi_compile_local __ UPSCALE_CAVITY
#pragma multi_compile_local __ CHARACTER_MASKING
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
@ -32,6 +33,7 @@
TEXTURE2D_X(_MainTex);
TEXTURE2D_X(_CavityTex);
TEXTURE2D_X(_NiloToonPrepassBufferTex);
//Unity 6.0's urp #includes themselves define sampler_LinearClamp
#if UNITY_VERSION < 600000
@ -158,7 +160,7 @@
#else
float3 N = float3(0, 0, 0);
#endif
N = float3(N.x, -N.yz);
N = float3(N.x, -N.y, N.z);
#endif
N = float3(N.x, -N.y, N.z);

Binary file not shown.

BIN
Packages/manifest.json (Stored with Git LFS)

Binary file not shown.

BIN
Packages/packages-lock.json (Stored with Git LFS)

Binary file not shown.