본문으로 바로가기
반응형


Unity fragment shader는 Surface shader와 달리 vertex shader와 pixel shader로 나누어 작성을 해야 한다.


기본구조는 크게 다르지 않으나 차이점이 있다면 surface 구조는 전처리 되어있는걸 사용하지 않는다고 막는구조라면 fragment 구조는 하나하나 만들어 줘야 한다는 정도.(fragment shader역시 전처리가 많이 되어있다. 다만 버텍스/픽셀 셰이더 구분이 되어있고 HLSL이나 GLSL과 구조가 유사하다는 정도일 뿐)




예제는 다음 링크에서 확인할 수 있다 : https://docs.unity3d.com/Manual/SL-VertexFragmentShaderExamples.html




Shader "Test/FragmentBase" {


    Properties    {

        _MainTex ("Texture", 2D) = "white" {}

    }


    SubShader

    {


        Tags { "RenderType"="Opaque" }


        LOD 100

        Pass


        {

            CGPROGRAM


            #pragma vertex vert

            #include "UnityCG.cginc"

      

            struct vertexInput

            {

            float4 vertex : POSITION;

            float2 uv  : TEXCOORD0;

            };


            struct vertexOutput // v2f

            {

                float4 vertex : SV_POSITION;

                float2 uv : TEXCOORD0;       

             };



            sampler2D _MainTex;

            float4 _MainTex_ST;  

                    

            vertexOutput vert(vertexInput v)  

            {


                vertexOutput o;

                o.vertex = UnityObjectToClipPos(v.vertex);

                o.uv = TRANSFORM_TEX(v.uv.xy, _MainTex);

                return o;


            }



            fixed4 frag (vertexOutput i) : SV_Target

            {


             fixed4 col = tex2D(_MainTex, i.uv);

              return col;

            }

            ENDCG

        }

    }

}



 

Vertex and Fragment shader 기본구조


struct vertexInput

            {

            ...

            };


// vertex buffer에서 가져오는 정보를 정한다. 


struct vertexOutput

           {

          ...

            };


// vertex shader에서 계산된 정보를 pixel shader로 넘기는 데이터 타입을 결정한다.


vertexOutput vert(vertexInput v)  

            {

            vertexOutput o;  

// vertex Input v. means struct vertexOutput

            return o;

            }


vertex shader stage


fixed4 frag (vertexOutput i) : SV_Target

            {

                                                 

// vertexOnput i. means vertexOutput vert

            return col;

            }



pixel shader stage







Subshader{


  Tags{ "Queue" = " 렌더링 큐  " "IgnoreProjector" = "true or false"  "RenderType" = "렌더링 타입" }

  Pass{

  렌더링 패스







#pragma vertex vert


vertex shader 입력 함수 vertex position, normal mesh, and texture coordinates등을 포함한다.


Cg / HLSL 버텍스 프로그램의 경우 메쉬 버텍스 데이터가 버텍스 쉐이더에 전달된다. 각각의 입력은 미리 정의된 키워드를 사용한다


  POSITION : 정점 위치

  NORMAL : 정점 법선

  TANGENT : 탄젠트 벡터. 일반적으로 float4

  TEXCOORD0 : 1번째 UV coordinate.

  TEXCOORD1, TEXCOORD2 and TEXCOORD3 : 2nd, 3rd, 4th UV coordinates

  COLOR : 정점의 색상






정점 데이터 입력은 구조체에 선언된다.

Data structures(자료 구조체)는 UnityCG.cginc에 다음과 같이 정의 되어있다.



    struct appdata_base : vertex shader input with position, normal, one texture coordinate.
    struct appdata_tan : vertex shader input with position, normal, tangent, one texture coordinate.
    struct appdata_full : vertex shader input with position, normal, tangent, vertex color and two texture coordinates.
    struct appdata_img : vertex shader input with position and one texture coordinate.





  struct appdata_base {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float4 texcoord : TEXCOORD0;
    UNITY_VERTEX_INPUT_INSTANCE_ID
  };




  struct appdata_tan


{

    float4 vertex : POSITION;
    float4 tangent : TANGENT;
    float3 normal : NORMAL;
    float4 texcoord : TEXCOORD0;
    UNITY_VERTEX_INPUT_INSTANCE_ID
  };




  struct appdata_full


{

    float4 vertex : POSITION;
    float4 tangent : TANGENT;
    float3 normal : NORMAL;
    float4 texcoord : TEXCOORD0;
    float4 texcoord1 : TEXCOORD1;
    float4 texcoord2 : TEXCOORD2;
    float4 texcoord3 : TEXCOORD3;
    fixed4 color : COLOR;
    UNITY_VERTEX_INPUT_INSTANCE_ID
  };




   struct appdata_img
  {
    float4 vertex : POSITION;
    half2 texcoord : TEXCOORD0;
    UNITY_VERTEX_INPUT_INSTANCE_ID
  };







vertex postion의 matrix 변환은 아래와 같이 이루어진다.



o.pos = UnityObjectToClipPos(v.vertex);
           


//  mul( UNITY_MATRIX_VP, _Object2World);

//  mul( UNITY_MATRIX_MVP, v.vertex ) ;



 inline float4 UnityObjectToClipPos(in float3 pos)
 {


     // More efficient than computing M*VP matrix product
     return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0)));


 }



매트릭스 변환은 다음 링크 참조 : http://www.codinglabs.net/article_world_view_projection_matrix.aspx




_WorldSpaceCameraPos (float3) 카메라의 월드 공간 위치

_ProjectionParams (float4) x는 1.0 (또는 -1.0 반전 한 투영 행렬은 현재 값이 음수 임), y는 카메라 상 평면이고, z는 카메라가있는 평면입니다 / FarPlane입니다.

_ScreenParams (float4)는 1.0 + 1.0 / 넓이이고, w는 1.0 + 1.0 / 높이입니다.

_ZBufferParams (float4) Z 버퍼 값을 선형화하는 데 사용됩니다. x는 (1- 먼 / 가깝), y는 (먼 / 가깝), z는 (x / 먼), w는 (y / 먼)입니다.

unity_OrthoParams (float4) x는 정사각형 카메라의 너비이고, y는 정사각형 카메라의 높이이며 z는 사용되지 않고 카메라가 정사각형 일 때 1.0, 원근감이있을 때 w가 1.0입니다.

unity_CameraProjection (float4x4) 카메라의 투영 행렬입니다.

unity_CameraInvProjection (float4x4) 카메라의 투영 행렬의 반전입니다.

unity_CameraWorldClipPlanes [6] (float4) 왼쪽, 오른쪽, 아래, 위, 가까운, 먼 순서로 카메라 절두 평면 세계 공간 방정식.




                o.color.xyz = v.normal * 0.5 + 0.5;
                o.color.w = 1.0;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target { return i.color; }


            ENDCG




#include "UnityCG.cginc"


Shader에 사용되는 cginc 파일은 아래와 같다.


    HLSLSupport.cginc - (automatically included) Helper macros and definitions for cross-platform shader compilation.

    크로스 플랫폼 셰이더 컴플리에이션을 위한 헬퍼 매크로와 정의


    UnityShaderVariables.cginc - (automatically included) Commonly used global variables.

    일반적인 전역변수


    UnityCG.cginc - commonly used helper functions.

    공통적으로 사용되는 정의들




UnityCG.cginc의 범용 헬퍼 함수들



float3 WorldSpaceViewDir (float4 v)- 월드 공간의, 특정 오브젝트 공간의 정점 위치에서 카메라를 향한, (정규화되지 않은) 방향.


float3 ObjSpaceViewDir (float4 v)- 오브젝트 공간의, 특정 오브젝트 공간의 정점 위치에서 카메라를 향한, (정규화되지 않은) 방향.


float2 ParallaxOffset (half h, half height, half3 viewDir)- 시차 법선 매핑의 UV 오프셋을 계산합니다.


fixed Luminance (fixed3 c)- 색을 밝기(그레이 스케일)로 변환합니다


fixed3 DecodeLightmap (fixed4 color)- Unity 라이트 맵의 색을 디코딩합니다(플랫폼은 RGBM 또는 dLDR).


float4 EncodeFloatRGBA (float v)- 정밀도 낮은 렌더 타겟을 저장하기 위해 01 사이의 부동 소수점을 RGBA color에 인코딩합니다.


float DecodeFloatRGBA (float4 enc)- RGBA color를 float로 디코딩합니다.

위와 같습니다만, float2 EncodeFloatRG (float v) 및 float DecodeFloatRG (float2 enc) 두 가지 색상 채널을 사용합니다.


float2 EncodeViewNormalStereo (float3 n) - 뷰 공간 법선을 0..1의 범위의 두 숫자로 인코딩합니다.


float3 DecodeViewNormalStereo (float4 enc4) - enc4.xy에서 뷰 공간 법선을 디코딩합니다.


UnityCG.cginc의 Forward Rendering 헬퍼 함수


float3 WorldSpaceLightDir (float4 v) - 월드 공간의, 오브젝트 공간의 정점 위치에서 라이트를 향한, (정규화되지 않은) 방향을 계산합니다


float3 ObjSpaceLightDir (float4 v) - 오브젝트 공간의 정점 위치에서 라이트를 향한, (정규화되지 않은) 방향을 계산합니다


float3 Shade4PointLights (...) - 네 개의 포인트 라이트에서, 라이트의 데이터를 vector에 저장하여 밝기를 산출합니다.


Forward Rendering은 각 정점 당 라이팅에 이 정보를 사용합니다.


UnityCG.cginc의 Vertex-lit 헬퍼 함수
float3 ShadeVertexLights (float4 vertex, float3 normal) - 네 개의 각 정점 라이트에서, 오브젝트 공간의 위치와 법선을 지정하여 밝기와 주변광을 산출합니다.




    AutoLight.cginc - lighting & shadowing functionality, surface shaders use this file internally.

    라이팅과 그림자 기능. surface shader의 경우 내부에 포함


    Lighting.cginc - standard surface shader lighting models, automatically included when you’re writing surface shaders.

    표준 surface shader 조명 모델. surface shader의 경우 자동으로 포함


    TerrainEngine.cginc - helper functions for Terrain & Vegetation shaders.

    지형 및 식생 셰이더를 위한 헬퍼 함수




            #pragma multi_compile_fog


// make fog work. fog 사용에 대해 셰이더를 컴파일 한다.

           


            struct v2f
            {
                float2 uv : TEXCOORD0;




                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;


// SV_POSITION은 GPU가 레스터 치리를 위해 반드시 필요한 선언문이다. 다른값은 vertex shader에 의해 출력된 값이 렌더링 되는 삼각형의 면에 따라 삽입됨으로, fragment shader에 전달하게 된다.

//http://qiita.com/sune2/items/fa5d50d9ea9bd48761b2

 





보간되는 변수의 수의 한계는 플랫폼과 GPU에 의해 제한된다. 자세한건 SM model feature 항목 참조

Mobile Graphics API 및 Shader Model Features(1) : http://illu.tistory.com/1209


     8 개까지 OpenGL ES 2.0 (iOS / Android), Direct3D 11 9.x level (Windows Phone) and Direct3 9 shader model 2.0 (old PCs).
     10 개까지 Direct3D 9 shader model 3.0 (#pragma target 3.0).
     16 개까지 OpenGL ES 3.0 (iOS / Android), Metal (iOS). (#pragma target 3.5)
     32 개까지 Direct3D 10 shader model 4.0 (#pragma target 4.0).




VPOS 스크린 공간의 좌표

UNITY_VPOS_TYPE : (기본 float4) fragment 쉐이더에 입력 shader model 3.0
VFACE : 면이 카메라를 향하고 있는지 여부(적합하면 정, 그렇지 않으면 부정적인) fixed fragment 쉐이더에 입력 shader model 3.0
SV_VertexID 정점 번호 uint vertex 쉐이더에 입력 DX10 (shader model 4.0), GLCore / OpenGL ES 3


VPOS, VFACE은 #pragma target 3.0 SV_VertexID은 #pragma target es3.0을 쓸 필요가있다.


https://docs.unity3d.com/530/Documentation/Manual/SL-ShaderSemantics.html

          };



            sampler2D _MainTex;
            float4 _MainTex_ST;



Materials often have Tiling and Offset fields for their texture properties. This information is passed into shaders in a float4 {TextureName}_ST property:

  • x contains X tiling value
  • y contains Y tiling value
  • z contains X offset value
  • w contains Y offset value

For example, if a shader contains texture named _MainTex, the tiling information will be in a _MainTex_ST vector.


.XY로 타일링, XY는 offset을 설정하게 된다.



{TextureName}_TexelSize - a float4 property contains texture size information:

    x contains 1.0/width
    y contains 1.0/height
    z contains width
    w contains height



Texture HDR parameters

{TextureName}_HDR - a float4 property with information on how to decode a potentially HDR (e.g. RGBM-encoded) texture depending on the color space used. See DecodeHDR function in UnityCG.cginc shader include file.





//Unity Fog 적용

                UNITY_TRANSFER_FOG(o,o.vertex);



                return o;
            }
           
            fixed4 frag (v2f i) : SV_Target



HLSL semantic : https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647(v=vs.85).aspx


SV_Target : 렌더링 대상 픽셀 색상(fixed4)

SV_TARGET1,SV_TARGET2,... : 다른 렌더링 대상에 대한 색상(fixed4) - 멀티 타겟 렌더링의 경우 define

SV_Depth : 렌더링 대상 픽셀 깊이(DX10/DX10.1 - SM 4.1)(float)

COLOR : 정점의 색상




HLSL에서 예제는 아래와 같이 설명하고 있다.


Direct3D 10 Semantic    Direct3D 9 Equivalent Semantic
SV_Depth    DEPTH
SV_Position    POSITION
SV_Target    COLOR



Direct3D 9 VPOS and Direct3D 10 SV_Position

The D3D10 semantic SV_Position provides similar functionality to the Direct3D 9 shader model 3 VPOS semantic. For instance, in Direct3D 9 the following syntax is used for a pixel shader using screen space coordinates:



float4 psMainD3D9( float4 screenSpace : VPOS ) : COLOR
{
  // code here   
}

         
VPOS was added for shader model 3 support, to specify screen space coordinates, since the POSITION semantic was intended for object-space coordinates.

In Direct3D 10 and later, the SV_Position semantic (when used in the context of a pixel shader) specifies screen space coordinates (offset by 0.5). Therefore, the Direct3D 9 shader would be roughly equivalent (without accounting for the 0.5 offset) to the following:



float4 psMainD3D10( float4 screenSpace : SV_Position ) : COLOR
{
  // code here
}
         



            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
 

               // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
 

              return col;
            }
            ENDCG
        }
    }
}





비전처리 구문으로는 다음과 같은 구조를 가진다.






fragment shader의 예제는 다음 링크를 참고한다. : https://illu.tistory.com/1371













반응형

'Technical Report > R&D test' 카테고리의 다른 글

Unity Sprites/Cheap Outer Glow Shader  (0) 2018.02.05
Unity SRP LightweightForward  (0) 2018.02.01
GLSL Rotate image shader  (0) 2017.07.21
Unity Bilboard shader  (0) 2017.07.13
approximate oren-nayar shader  (0) 2017.06.19