사용자 도구

사이트 도구


language:shader:unity:surface-shader-basic

베이직이라는데 매뉴얼에서 건질게 별로 없어 보이네.

Surface Shader 작성, (예제 작성법으로 다 떠넘겨버리는) 문서.

아무튼,

  • Vertex/Pixel shader 보다는 덜 복잡한 방법으로 셰이더를 작성하기 위해서
  • 다른 스크립트 랭귀지를 제공하는 것도 아니고
  • 반복적인 코드 작업을 대신 해주는 정도라는데(뭔소리?)
  • 실제 작업은 Cg/HLSL을 그대로 사용한답니다.

작동

  • surface function을 작성
  • 계산 결과물을 저장할 SurfaceOutput 에 값을 채워줌

SurfaceShader에서 input,output에 필요한 부분을 찾아서 여기에 맞는 vertex,pixel shader를 작성해줌

컴파일 지시자

SurfaceShader 부분은, CGPROGRAM .. ENDCG 부분에 추가

  • 이 구문은, SubShader에 들어가야 한다. Pass 부분에 넣지 않는다.
    멀티 패스가 필요한 경우, 자동으로 만들어짐
  • #pragma surface .. 지시문으로 SurfaceShader 부분을 가리킨다.
ShaderLab "Study/SurfaceOne" {
  SubShader {
    CGPROGRAM
    ENDCG
  }
}

#pragma surface .. 부분은,

#pragma surface <surfaceFunction> <lightModel> <[optionalparams]>
  • surfaceFunction : 어느 함수가 셰이더 코드를 갖고 있는지 알려줘야 한다.
    void surf (Input IN, inout SurfaceOutput o)
  • 라이트 모델도 적어야 한다.
    • Lambert(diffuse), BlinnPhong(specular)

Input structure

Input 구조체는 기본 텍스쳐UV를 넣는다. 이름은 꼭 uv여야한다. 두번째 텍스쳐가 있는 경우에는 uv2

추가로 Input에 넣을 수 있는 값들

  • (float3) viewDir : 뷰디렉션
  • (float4) with COLOR : 정점 컬러
  • (float4) screenPos : 화면상의 위치
  • (float3) worldPos : 월드스페이스상의 위치
  • (float3) worldRefl
  • (float3) worldRefl; INTERNAL_DATA
  • (float3) worldNormal; INTERNAL_DATA

SurfaceOutput

표준 SurfaceOuptut

struct SurfaceOutput {
  half3 Albedo;   // RGB 색상
  half3 Normal;   // 법선
  half3 Emission; // 메시표면의 방출되는 빛. 외부에 영향을 주지 못한다.
  half Specular;  // 정반사광
  half Gloss;     // 
  half Alpha;     // 알파
};
  • half (== float)

One Color Diffuse

SurfaceShader에 대한 기본 뼈대

  • 반투명 오브젝트
  • 표면 색상을 전부 흰색으로 칠한다.
  • 라이팅연산 결과를 사용하기 때문에 빛에 따라 색의 명암이 달라진다.
  • in : 색상 정보만 얻어다 사용
  • out에 대한 구조체는 기본 값을 사용
//표면 색상을 전부 흰색으로 칠한다.
Shader "Example/Diffuse Simple" {
  SubShader {
    // 반투명 오브젝트
    Tags { "RenderType" = "Opaque" }
  
    CGPROGRAM
    #pragma surface surf Lambert
  
      //in : 색상 정보만 얻어다 사용
      struct Input {
        float4 color : COLOR;
      };
      void surf (Input IN, inout SurfaceOutput o) {
        o.Albedo = 1;
      }
    ENDCG
  }
  Fallback "Diffuse"
}

Textured Diffuse, 텍스쳐를 사용한 Diffuse

  • 텍스쳐 프로퍼티 추가
  • Input 구조체에 텍스쳐 UV를 넘겨 받기 위한 구조체로 설정
    • uv_로 시작되는 부분 주목
  • 출력값에는 rgb값을 Albedo에 입력
Shader "Study/TexturedDiffuse" {
  Properties {
    // 텍스쳐 프로퍼티 추가
    _MainTex ("Texture", 2D) = "white" {}
  }
  
  SubShader {
    Tags { "RenderType" = "Opaque" }
    CGPROGRAM
      #pragma surface surf Lambert
  
      // 텍스쳐 UI를 받는다. uv_로 시작되는 부분에 주목.
      struct Input {
        float2 uv_MainTex;
      };
      
      sampler2D _MainTex;
      
      void surf (Input IN, inout SurfaceOutput o) {
        // Albedo에 색상값을 넣는다.
        o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
    ENDCG
  } 
  Fallback "Diffuse"
}

Texture Bump Diffuse

Bump 맵을 받아서, surfaceFunction에서 사용하는 방법 확이

Shader "Study/TextureBumpDiffuse" {
  Properties {
    _MainTex ("Texture", 2D) = "white" {}
    // 범프맵 텍스쳐 프로퍼티 추가
    _BumpMap ("BumpMap", 2D) = "bump" {}
  }
  SubShader {
    Tags { "RenderType" = "Opaque" }
    CGPROGRAM
    #pragma surface surf Lambert
    struct Input {
      float2 uv_MainTex;
      float2 uv_BumpMap; // Bump맵 UV 좌표를 입력 값으로 받는다
    };
    
    sampler2D _MainTex;
    sampler2D _BumpMap; // 범프맵을 저장할 텍스쳐 샘플(변수)
    
    void surf (Input IN, inout SurfaceOutput o) {
      o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      // 범프맵을 적용한다.
      o.Normal = UnpackNormal( tex2D(_BumpMap, IN.uv_BumpMap) );
    }
    ENDCG
  } 
  Fallback "Diffuse"
}

Rim Lighting 적용

 Shader "Study/TexBumpDiffuseRimLighting" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {} _BumpMap ("BumpMap", 2D) = "bump" {}
        // 림라이트 프로퍼티
        _RimColor ("RimColor", Color) = (0.26, 0.19, 0.16, 0.0)
        _RimPower ("RimPower", Range(0.5, 8.0)) = 3.0
    }
    SubShader {
        Tags { "RenderType" = "Opaque" }
        CGPROGRAM
        #pragma surface surf Lambert
        struct Input {
            float2 uv_MainTex; float2 uv_BumpMap;
            // 림라이트 계산을 위한 뷰Dir
            float3 viewDir;  		
        };

        sampler2D _MainTex; sampler2D _BumpMap;
        // 림라이트 프로퍼티 변수
        float4 _RimColor;
        float _RimPower;

        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
            o.Normal = UnpackNormal( tex2D(_BumpMap, IN.uv_BumpMap) );

            // 림라이트 연산!!
            half rim = 1.0 - saturate( dot( normalize(IN.viewDir), o.Normal ) );
            o.Emission = _RimColor.rgb * pow(rim, _RimPower);
        }
        ENDCG
    } 
    Fallback "Diffuse"
}
language/shader/unity/surface-shader-basic.txt · 마지막으로 수정됨: 2024/04/23 22:45 저자 127.0.0.1