구현 목표
- 특정 Shader만 제외하고 전체 화면에 Grayscale 효과 적용시키기
구현을 위해 필요했던 지식들
- 유니티 렌더 파이프라인의 변화
- SRP 구조
- Custom Renderer Feature 작성법
URP를 사용하면서 기존에 있던걸 사용할 수 없거나 교체된 부분들이 있어 여러 자료를 찾아봐야 했다
Custom Renderer Feature를 만들기 위해선 두 클래스를 사용하면 된다
- ScriptableRenderPass
- ScriptableRendererFeature
기본적인 부분은 Unity Manual에 나와있다
Unity Manual: How to create a custom Renderer Feature
최종 결과물
using UnityEngine;
using UnityEngine.Rendering.Universal;
public class GrayscaleWithOriginColorRendererFeature : ScriptableRendererFeature
{
[System.Serializable]
public class GrayRenderSettings
{
public RenderPassEvent Event = RenderPassEvent.AfterRenderingOpaques;
public Material fullScreenMaterial;
}
public GrayRenderSettings settings = new GrayRenderSettings();
private GrayscaleWithOriginColorRenderPass grayPass;
public override void Create()
{
// 초기 실행시 호출, 렌더 패스 생성 및 초기값 설정을 여기서 한다
grayPass = new GrayscaleWithOriginColorRenderPass(settings.fullScreenMaterial, settings.Event);
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
var src = renderer.cameraColorTarget;
grayPass.SetSource(src);
renderer.EnqueuePass(grayPass);
}
}
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
internal class GrayscaleWithOriginColorRenderPass : ScriptableRenderPass
{
// 원하는 이름으로 짓기, Frame Debugger에서 사용될 이름임
private const string ProfilerName = "Grayscale With Origin Color";
// 원하는 이름으로 짓기, 임시 렌더 텍스쳐 이름으로 쓰임
private const string TempRTName = "_TempRT";
private ProfilingSampler m_ProfilingSampler = new ProfilingSampler(ProfilerName);
private RenderTargetIdentifier source;
// RenderTargetHandle 대신 Shader ID를 얻어와 사용
private int destinationID = Shader.PropertyToID(TempRTName);
private Material overrideMaterial;
public GrayscaleWithOriginColorRenderPass(Material overrideMaterial, RenderPassEvent renderPassEvent)
{
this.overrideMaterial = overrideMaterial;
this.renderPassEvent = renderPassEvent;
}
public void SetSource(RenderTargetIdentifier source)
{
this.source = source;
}
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
cmd.GetTemporaryRT(destinationID, cameraTextureDescriptor, FilterMode.Point);
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get();
using (new ProfilingScope(cmd, m_ProfilingSampler))
{
cmd.CopyTexture(source, destinationID);
Blit(cmd, destinationID, source, overrideMaterial);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public override void FrameCleanup(CommandBuffer cmd)
{
cmd.ReleaseTemporaryRT(destinationID);
}
cmd.GetTemporaryRT를 하면 임시로 사용할 렌더 텍스쳐가 생성된다
ProfilingScope를 사용하면 해당 name으로 아래와 같이 토글이 생성돼서 Frame Debug를 보기 용이해진다
현재 cameraColorTarget을 source에 할당하고
source를 임시 렌더 텍스쳐인 destinationID에 복사해준다
그 후 Blit을 통해 destinationID를 현재 카메라가 render하고 있는 텍스쳐인 source에 overrideMaterial를 적용시켜 복사해준다
Blit
주로 사용자 지정 셰이더를 사용해 렌더 텍스쳐에서 다른 텍스쳐로 복사하는데 사용된다
Stencil
위 화면처럼 전체 화면은 OverrideMaterial (Grayscale 효과)로 그려지고 몇몇 오브젝트는 원래 색으로 그려지고 있다
이 효과는 Stencil을 사용해서 구현했다
[Color Shader]
Stencil
{
Ref 1
Comp Always
Pass Replace
}
[Grayscale Shader Code]
Stencil
{
Ref 1
Comp NotEqual
}
1. 원래 색으로 표현되어야 할 오브젝트들은
Ref 1
Comp Always
Pass Replace로 함으로써
화면에 그려질 때 먼저 쓰여있는 Stencil 값과 상관없이 항상 Render하고
먼저 쓰여있는 값을 1로 대체해놓는다
2. Grayscale로 전체 화면을 그릴 때
Ref 1
Comp NotEqual로 둬서
화면에 있는 Stencil 값이 1이 아닌 부분만 Render하게해서
원래 색으로 표현되어야 할 오브젝트부분을 제외한 곳만 Grayscale로 Render되게 만들었다
어려웠던 점
Shader Graph에 Stencil 값을 적용시킬 수 없다는 것이었는데
일단 Shader Graph의 Generated Shader를 통해 Shader Code를 복사하여
새로운 Shader를 만든 뒤 붙여넣고 Stencil 값만 추가하여 사용하고있다
첨부
Scriptable Renderer Feature를 만들기 위해 URP의 기본 개념부터 익혀야했는데
그 때 많은 도움이 되었던 영상과 글들을 첨부해둔다
Dev Weeks: URP 기본 구성과 흐름 (Unity 유튜브 채널)
https://mathmakeworld.tistory.com/59
Unity SRP 처음부터 시작하기 2
이번에는 저번 시간에 이어서 Unity SRP를 이용해 Object를 그리는 방법에 대해서 알아보겠습니다. 저번 시간과 마찬가지로 결과 화면 먼저 보겠습니다. 역시나 저번 포스팅과 비슷하게 그래픽스 수
mathmakeworld.tistory.com
https://catlikecoding.com/unity/tutorials/scriptable-render-pipeline/
Unity Scriptable Render Pipeline Tutorials
A collection of tutorials that cover the scriptable render pipeline of Unity.
catlikecoding.com
'프로젝트 > Color Lim 개발일지' 카테고리의 다른 글
File.ReadAllText와 StreamReader.ReadToEnd의 차이점 (0) | 2023.01.18 |
---|---|
BinaryReader와 StreamReader 클래스의 차이 (0) | 2023.01.18 |
2021-08-16 개발일지 (0) | 2021.08.17 |
2021-08-14 개발일지 (0) | 2021.08.15 |
2021-08-11 개발일지 (0) | 2021.08.11 |