4-9. 2조 PortalCamera

keubung·2024년 11월 6일

포탈 모작 스크립트 수정
: 기존 URP 사용 -> URP 사용 X
: 하나의 카메라가 아닌 각 포탈에 카메라를 위치시켜 총 2개의 카메라를 사용
PortalCamera.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PortalCamera : MonoBehaviour
{
    [SerializeField]
    private Portal[] portals = new Portal[2];

    [SerializeField]
    private Camera portalCameraA; // 포탈 A 전용 카메라
    [SerializeField]
    private Camera portalCameraB; // 포탈 B 전용 카메라

    [SerializeField]
    private int iterations = 7;

    private RenderTexture renderTextureA;
    private RenderTexture renderTextureB;

    private void Awake()
    {
        // 화면 해상도에 맞게 RenderTexture를 생성
        renderTextureA = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32);
        renderTextureB = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32);
    }

    void Start()
    {
        // 각 포탈의 Material에 상대 포탈의 RenderTexture를 설정
        portals[0].Renderer.material.mainTexture = renderTextureB; // 포탈 A에 포탈 B의 텍스처를 설정
        portals[1].Renderer.material.mainTexture = renderTextureA; // 포탈 B에 포탈 A의 텍스처를 설정

        // 각 포탈 카메라의 RenderTexture를 설정
        portalCameraA.targetTexture = renderTextureA;
        portalCameraB.targetTexture = renderTextureB;
    }

    void Update()
    {
        // RenderTexture의 해상도가 화면 크기에 맞지 않으면 재설정
        UpdateRenderTextures();

        // 두 포탈이 배치되어 있지 않으면 렌더링을 건너뜀
        if (!portals[0].IsPlaced || !portals[1].IsPlaced)
        {
            return;
        }

        // 포탈 A에서 포탈 B를 통한 뷰를 렌더링
        if (portals[0].Renderer.isVisible)
        {
            RenderPortalView(portalCameraA, portals[0], portals[1]);
        }

        // 포탈 B에서 포탈 A를 통한 뷰를 렌더링
        if (portals[1].Renderer.isVisible)
        {
            RenderPortalView(portalCameraB, portals[1], portals[0]);
        }
    }

    private void UpdateRenderTextures()
    {
        // 화면 크기가 변경되었으면 RenderTexture를 새로 생성
        if (renderTextureA.width != Screen.width || renderTextureA.height != Screen.height)
        {
            renderTextureA.Release();
            renderTextureB.Release();

            renderTextureA = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32);
            renderTextureB = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32);

            // 각 포탈의 Material에 새로운 RenderTexture를 다시 설정
            portals[0].Renderer.material.mainTexture = renderTextureB;
            portals[1].Renderer.material.mainTexture = renderTextureA;

            // 각 포탈 카메라의 RenderTexture를 설정
            portalCameraA.targetTexture = renderTextureA;
            portalCameraB.targetTexture = renderTextureB;
        }
    }

    private void RenderPortalView(Camera portalCamera, Portal inPortal, Portal outPortal)
    {
        portalCamera.clearFlags = CameraClearFlags.SolidColor;
        portalCamera.backgroundColor = Color.white;

        Transform inTransform = inPortal.transform;
        Transform outTransform = outPortal.transform;

        Transform cameraTransform = portalCamera.transform;
        cameraTransform.position = transform.position;
        cameraTransform.rotation = transform.rotation;

        // 카메라를 반복적으로 이동시켜 포탈 렌더링 효과 적용
        for (int i = 0; i < iterations; i++)
        {
            Vector3 relativePos = inTransform.InverseTransformPoint(cameraTransform.position);
            relativePos = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativePos;
            cameraTransform.position = outTransform.TransformPoint(relativePos);

            Quaternion relativeRot = Quaternion.Inverse(inTransform.rotation) * cameraTransform.rotation;
            relativeRot = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativeRot;
            cameraTransform.rotation = outTransform.rotation * relativeRot;
        }

        // 카메라에 설정된 RenderTexture로 렌더링
        portalCamera.Render();
    }
}
profile
김나영(Unity_6기)

0개의 댓글