728x90
※이 포스팅에서 알려드릴 픽셀레이트효과는 URP환경에서 구현했습니다. 또한 URP에 대한 지식이 어느 정도 있다고 가정하고 설명합니다.
이 포스팅에서는 URP의 커스텀렌더패스(Custom Render Pass)를 이용해 픽셀레이트효과구현합니다. 개별 오브젝트에 효과를 주는 방식이 아닌 카메라 전체에 효과를 적용하는 방식입니다. 쉐이더를 이용해 원하는 오브젝트에만 픽셀레이트 효과를 적용하는 방식은 나중에 시간이 되면 만들어 보도록 하겠습니다.
전체코드
먼저 픽셀레이트패스(PixelatePass) 클래스의 전체 코드를 보고, 중요한 부분만 설명하겠습니다. 이 픽셀레이트 효과의 구현원리는 쉽게말하면 현재 화면을 낮은 해상도를 가진 화면에 복사하고 그 복사된 낮은 해상도의 화면을 다시 원래 해상도의 화면으로 잡아 늘린다고 생각하시면 됩니다.
[System.Serializable]
public class PixelatePassSettings
{
public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
public int screenHeight = 256;
}
public class PixelatePass : ScriptableRenderPass
{
private PixelatePassSettings settings;
private RenderTargetIdentifier colorBuffer, pixelBuffer;
private int pixelBufferID;
public PixelatePass(PixelatePassSettings setting)
{
if (setting != null)
{
this.settings = setting;
this.renderPassEvent = settings.renderPassEvent;
}
}
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
colorBuffer = renderingData.cameraData.renderer.cameraColorTarget;
RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
var pixelScreenHeight = settings.screenHeight;
var pixelScreenWidth = (int)(pixelScreenHeight * renderingData.cameraData.camera.aspect);
descriptor.height = pixelScreenHeight;
descriptor.width = pixelScreenWidth;
cmd.GetTemporaryRT(pixelBufferID, descriptor, FilterMode.Point);
pixelBuffer = new RenderTargetIdentifier(pixelBufferID);
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get();
Blit(cmd, colorBuffer, pixelBuffer);
Blit(cmd, pixelBuffer, colorBuffer);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public override void OnCameraCleanup(CommandBuffer cmd)
{
if (cmd == null)
{
throw new System.ArgumentNullException("cmd");
}
cmd.ReleaseTemporaryRT(pixelBufferID);
}
}
이 코드에서 실질적으로 픽셀레이트 효과가 구현되는 곳은 OnCameraSetup함수와 Execute함수입니다.
OnCameraSetup
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
// 먼저 현재 카메라의 화면의 컬러타겟을 가져옵니다. 이 컬러타켓은 현재 카메라 화면을 텍스쳐로 가져온다고 생각하면됩니다.
colorBuffer = renderingData.cameraData.renderer.cameraColorTarget;
// 현재 화면의 부가정보를 가져옵니다.
RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
// PixelatePassSettings 인스턴스에 설정된 screenHeight값으로 화면 해상도를 만듭니다.
var pixelScreenHeight = settings.screenHeight;
var pixelScreenWidth = (int)(pixelScreenHeight * renderingData.cameraData.camera.aspect);
// 아까 가져온 화면의 부가정보중에서 해상도를 방금 만든 해상도로 바꿉니다.
descriptor.height = pixelScreenHeight;
descriptor.width = pixelScreenWidth;
// 수정된 부가정보를 토대로 임시렌더타겟을 만듭니다. 선명한 픽셀레이트 효과를 위해 필터모드는 포인트로 해줍니다.
cmd.GetTemporaryRT(pixelBufferID, descriptor, FilterMode.Point);
// pixelBuffer변수에 임시로 만든 렌더타켓을 인스턴스화하여 할당해줍니다.
pixelBuffer = new RenderTargetIdentifier(pixelBufferID);
}
Execute
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get();
// 현재 화면의 컬러정보가 담겨있는 버퍼를 보다 화면해상도가 낮게 설정되어있는 pixelBuffer에 복사합니다.
// 현재 화면의 해상도가 낮아진다고 생각하시면됩니다.
Blit(cmd, colorBuffer, pixelBuffer);
// 해상도가 낮아진 현재화면이 담겨있는 pixelBuffer를 다시 colorBuffer로 복사합니다.
// 이렇게 되면 해상도가 낮아진 현재화면을 다시 현재 해상도로 잡아서 늘린다고 생각하시면 됩니다.
Blit(cmd, pixelBuffer, colorBuffer);
// 명령을 제출합니다.
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
결과
PixelatePassSettings에서 높이값을 변경하면 픽셀화 수치를 조절 할 수 있습니다.
728x90
반응형