Unity/URP

210712_URP 쉐이더 1

minquu 2021. 7. 13. 01:02
반응형

기존에 했던 쉐이더에서 URP 쉐이더의 스크립터는 조금 다르다.

 

이렇게 날라간다.

 

https://www.youtube.com/watch?v=mlNWoROvavY&t=1111s 

 

튜토리얼 참고.

 

일단 기본 쉐이더를 만들어서 매터리얼에 적용하고 모델링에 적용한다.

 

 

 

https://docs.google.com/document/d/1UX0319CXa29fCFAgg0qa5vnH-U6875jt0KLKUk5mke8/edit#

 

URP Shader Basic

URP Shader Basic term 2 Shader란? 2 Basic simple basic code 2 Shader “shader folder name / shader name” 3 Properties에서 변수 설정하고 매터리얼에서 확인 3 SubShader 4 Shader Tag 5 Rendering Order - Queue Tag 5 Render type 5 Pass 5 HLSL

docs.google.com

 

이 도큐먼터리에서 

베이직 코드를 그대로 붙여넣기한다.

 

폴더를 제외한 

 

그냥 파일 이름만 넣어도 된다.

 

내 쉐이더폴더 / 쉐이더파일이름으로 위에를 바꿔준다.

 

 // Shader 시작. 셰이더의 폴더와 이름을 여기서 결정합니다.
Shader "Shader/emblem_base_shader"
{


   Properties
             {   
// Properties Block : 셰이더에서 사용할 변수를 선언하고 이를 material inspector에 노출시킵니다
           	}  

	SubShader
	{  

	Tags
            {
//Render type과 Render Queue를 여기서 결정합니다.
	   "RenderPipeline"="UniversalPipeline"
                "RenderType"="Opaque"          
                "Queue"="Geometry"
            }
    	Pass
    	{  		
     	 Name "Universal Forward"
              Tags { "LightMode" = "UniversalForward" }

       	HLSLPROGRAM

        	#pragma prefer_hlslcc gles
        	#pragma exclude_renderers d3d11_9x
        	#pragma vertex vert
        	#pragma fragment frag

//cg shader는 .cginc를 hlsl shader는 .hlsl을 include하게 됩니다.
       	#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"        	
  
//vertex buffer에서 읽어올 정보를 선언합니다. 	
         	struct VertexInput
         	{
            	float4 vertex : POSITION;
          	};

//보간기를 통해 버텍스 셰이더에서 픽셀 셰이더로 전달할 정보를 선언합니다.
        	struct VertexOutput
          	{
           	float4 vertex  	: SV_POSITION;
      	};

//버텍스 셰이더
      	VertexOutput vert(VertexInput v)
        	{

          	VertexOutput o;      
          	o.vertex = TransformObjectToHClip(v.vertex.xyz);

         	return o;
        	}

//픽셀 셰이더
        	half4 frag(VertexOutput i) : SV_Target
        	{ 
                 	
          	return half4(0.5 , 0.5, 0.5, 1);  
       	
        	}

        	ENDHLSL  
    	}
     }
}

베이직 코드

 

----

 

기존 빌트인 렌더링에서 하는 것과 유사한 점이 많음

 

 

먼저 프로퍼티에 코드를 넣어서 

 

인스펙터에서 노출이 된다.

 

pragma 밑에 half4 _Color;

 

선언해주고,

 

frag에서 return를 해준다.

 

오브젝의 색이 바뀐걸 확인 할 수 있다.

 

----

 

이론적인 내용

 

 

SubShader

메시를 렌더링 할 때 Unity는 대상 장치의 GPU와 호환되는 첫 번째 SubShader 블록을 선택하는데 SubShader 블록은 SubShader Tags 블록을 선택적으로 포함 할 수 있다. Tags 키워드를 사용하여 SubShader Tags 블록을 아래와 같이 선언하게 된다. 

 

 

 

Tag 를 통해서 이 쉐이더의 타입을 선언하게 된다.

 

 

 

렌더링 오더 에는 Queue Tag를 사용해서 오브젝트를 그리는 순서를 결정할 수 있다.

 

이 그리는 순서를 유니티에서는 번호를 입력해서 관리한다.

 

 

 

"Queue" 태그 

 

기본 2000 으로 되어있음

 

그래서 인스펙터에 보면 

 

Render Queue 가 2000으로 적혀있음

 

프롬 세이더는 스크립터에 있는 렌더 큐를 그대로 사용한다는 의미

 

아니면 저기서도 바꿀수도있다.

 

 

 

렌더 타입 태그는 셰이더를 미리 정의된 여러그룹을 분류하게 된다. 

 

 

"Render tpye" 태그 

 

 

Pass

Pass block은 shader에서 사용할 각 렌더 패스를 결정한다.

패스에서 LightMode 태그를 설정하지 않으면 URP는 해당 패스에 대해 SRPDefaultUnlit 태그 값을 사용하게 된다.

 

 

윈도우 - 아날리시스 - 프레임 디버그 창을 보면 지금 보는 화면이 어떻게 렌더링이 되었는지 확인 할 수 있다.

 

렌더링은 여러 패스 쌓여서 완성되는  화면을 보는 것이다 .

 

 

왼쪽에 패스가 하나하나 쌓이는 것이다 .

 

아래 예제처럼 Pass를 하나하나 쌓아서 하는 것이다. 

 

Basic 과정에서는 각 Pass를 다루지는 않는다. 개략적인 구조는 아래 simpleLit shader의 구조를 참고한다.

SubShader
    {
       Tags { "RenderType" = "Opaque"
                  "RenderPipeline" = "UniversalPipeline"
                  "UniversalMaterialType" = "SimpleLit" 
                  "IgnoreProjector" = "True"
                   "ShaderModel"="4.5"}
        Pass
        {
           Name "ForwardLit"
           Tags { "LightMode" = "UniversalForward" }
           …
        }
   
        Pass
        {
            Name "ShadowCaster"
            Tags{"LightMode" = "ShadowCaster"}
          …
        }
       Pass
        {
            Name "GBuffer"
            Tags{"LightMode" = "UniversalGBuffer"}
        …
        }
       Pass
       {
            Name "DepthOnly"
            Tags{"LightMode" = "DepthOnly"}
       …
       }

 

 

 

 

기존 내가 배운 빌트인 - 레거시 코드에서는  CG 그래픽스 언어를 사용하였고,

 

URP 에서는 HLSL 그래픽스 언어를 사용한다.

 

 

 

 

 

CG shader를 사용할 경우에는 .cginc 파일을 include 하지만 HLSL에서는 .hlsl 파일을 include하게 된다

 

경로에 있는 파일을 뜯어서 공부하면 도움이 많이 된다.

 

 

 

 

pragma

C언어에서 pragma는 컴파일러가 입력을 처리하는 방법을 지정하는 언어 문법,

이는 쉐이더가 어떻게 컴파일 될지를 지시하는 전처리 문법임

 

 

 

Rendering Pipeline

 

 

 

큰 파이프라인인 Input Assembly (가져온 모델링의 점들을 모아준다)

Vertex Shading - 3D 공간에서 점으로 바꿔준다.

Rasterization - 모니터 화면에 보이는 픽셀에 맞춰서 배열함Pixel Shading - 그 픽셀에 어떤 색이 들어갈지 정하게 된다.

 

 

 

-----

 

 

Input Assembly : GPU는 메모리에서 버텍스 및 인덱스 버퍼를 읽고, 버텍스가 Tri를 형성하는 방식을 결정하고 나머지는 파이프 라인에 전달.

 

Vertex Shading : 한번에 하나의 버텍스에서 실행되는 메쉬의 모든 버텍스에 대해 한번 실행된다. 여기에서 버텍스를 변환하고 위치를 받은다음 카메라 및 뷰포트 설정을 사용해 화면서 최종 위치를 계산

 

Rasterization : 버텍스 셰이더가 삼각형의 각 버텍스에 실행되고 GPU가 화면에 표시될 위치를 알고 있으면 삼각형이 레스터화 되어 개별 픽셀의 모음으로 변환된다. 버텍스별 정보(UV좌표, 버텍스 컬러, 노멀등)은 삼각형 픽셀을 통해 보간된다(레스터화 된 픽셀은 각 버텍스의 보간된 값을 가지게 된다)

 

Pixel Shading : 레스터화 된 각 픽셀은 픽셀 셰이더를 통해 실행(기술적으로는 아직 픽셀이 아닌 프래그먼트 셰이더라고 한다). 매터리얼 속성, 텍스쳐, 광원등 기타 매개 변수를 프로그래밍 된 방식으로 결합해 특정 색상을 얻음으로써 픽셀에 색상을 부여

 

Render Target output : 마지막으로 픽셀은 렌더링 대상에 쓰여지지만 일부 테스트를 거쳐야 유효하게 된다. 예를 들어 깊이 테스트는 이미 렌더링 대상보다 멀리 떨어진 픽셀을 생략할 수 있다. 이러한 모든 테스트(Depth, alpha, stencil등)를 통과하면 메모리의 렌더링 타겟에 쓰여지게 된다.

 

Z sort 방식 : 렌더링 하는 물체를 카메라 시점으로부터 거리로 소팅(정렬)해 두고 시점으로 부터 먼 것부터 순서대로 렌더링 하는 방식. 뒤에 있는 것을 앞에 있는 물체가 덮어 씌워간다.(메쉬가 겹칠경우 소팅이슈 발생)

 

Z buffer 방식 : 물체를 렌더링하면서 그 물체까지의 거리를 픽셀(텍셀) 단위로 깊이 버퍼에 저장해두고 다음에 런더링 할때 이미 렌더링 되어 있는 물체의 거리와 렌더링 하려는 물체의 거리를 비교하면서 앞에 있으면 렌더링(반투명의 경우 렌더링 어려움)

 

 

즉, 버텍스세이더 -> 픽셀 세이더로 보내야 한다.

 

---- 

 

1. vertex buffer에서 읽어올 정보를 선언

 

2. 보간기를 통해 버텍스 세이더 -> 픽셀 세이더로 전달할 정보를 선언

3.버텍스 세이더

 

4.픽셀 세이더

 

 

크게 4단계로 나누어져 있다고 생각하면 된다.

 

----

1. VertexInput

 

 

즉, 메쉬가 가지고있는 값들을 가져오는 역할을 한다고 보면 된다.

 

마야나 시포디에서는 사각으로 보이지만 그것은 디자이너의 편의를 위해서 그런것, 실제로는 삼각형으로 이루어져있음

 

 

반응형