사용자 도구

사이트 도구


language:shader:unity:surface-shader-basic

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판이전 판
language:shader:unity:surface-shader-basic [2014/05/16 14:57] – [작동] kieunslanguage:shader:unity:surface-shader-basic [2024/04/23 22:45] (현재) – 바깥 편집 127.0.0.1
줄 1: 줄 1:
 +베이직이라는데 매뉴얼에서 건질게 별로 없어 보이네.
  
 +[[https://docs.unity3d.com/Documentation/Components/SL-SurfaceShaders.html|Surface Shader 작성]], (예제 작성법으로 다 떠넘겨버리는) 문서.
 +
 +아무튼,
 +
 +  * Vertex/Pixel shader 보다는 덜 복잡한 방법으로 셰이더를 작성하기 위해서 
 +  * 다른 스크립트 랭귀지를 제공하는 것도 아니고
 +  * 반복적인 코드 작업을 대신 해주는 정도라는데(뭔소리?)
 +  * 실제 작업은 **Cg/HLSL**을 그대로 사용한답니다.
 +
 +====== 작동 ======
 +
 +  * surface function을 작성
 +  * 계산 결과물을 저장할 SurfaceOutput 에 값을 채워줌
 +
 +SurfaceShader에서 input,output에 필요한 부분을 찾아서 여기에 맞는 vertex,pixel shader를 작성해줌
 +
 +===== 컴파일 지시자 =====
 +
 +SurfaceShader 부분은, **CGPROGRAM .. ENDCG** 부분에 추가
 +
 +  * 이 구문은, SubShader에 들어가야 한다. Pass 부분에 넣지 않는다. \\ 멀티 패스가 필요한 경우, 자동으로 만들어짐
 +  * **%%#pragma surface ..%%** 지시문으로 SurfaceShader 부분을 가리킨다.
 +
 +<code>
 +ShaderLab "Study/SurfaceOne" {
 +  SubShader {
 +    CGPROGRAM
 +    ENDCG
 +  }
 +}
 +</code>
 +
 +**%%#pragma surface ..%%** 부분은,
 +
 +<code>
 +#pragma surface <surfaceFunction> <lightModel> <[optionalparams]>
 +</code>
 +
 +  * surfaceFunction : 어느 함수가 셰이더 코드를 갖고 있는지 알려줘야 한다. <code>
 +void surf (Input IN, inout SurfaceOutput o)</code>
 +  * 라이트 모델도 적어야 한다.
 +    * 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
 +
 +<code>
 +struct SurfaceOutput {
 +  half3 Albedo;   // RGB 색상
 +  half3 Normal;   // 법선
 +  half3 Emission; // 메시표면의 방출되는 빛. 외부에 영향을 주지 못한다.
 +  half Specular;  // 정반사광
 +  half Gloss;     // 
 +  half Alpha;     // 알파
 +};
 +</code>
 +
 +  * half (== float)
 +====== 예 ======
 +
 +===== One Color Diffuse =====
 +
 +SurfaceShader에 대한 기본 뼈대
 +
 +  * 반투명 오브젝트
 +  * 표면 색상을 전부 흰색으로 칠한다.
 +  * 라이팅연산 결과를 사용하기 때문에 빛에 따라 색의 명암이 달라진다.
 +  * in : 색상 정보만 얻어다 사용
 +  * out에 대한 구조체는 기본 값을 사용
 +
 +<code>
 +//표면 색상을 전부 흰색으로 칠한다.
 +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"
 +}
 +</code>
 +
 +===== Textured Diffuse, 텍스쳐를 사용한 Diffuse =====
 +
 +  * 텍스쳐 프로퍼티 추가
 +  * Input 구조체에 텍스쳐 UV를 넘겨 받기 위한 구조체로 설정
 +    * **uv_**로 시작되는 부분 주목
 +  * 출력값에는 rgb값을 Albedo에 입력
 +
 +<code>
 +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"
 +}
 +</code>
 +
 +===== Texture Bump Diffuse =====
 +
 +Bump 맵을 받아서, surfaceFunction에서 사용하는 방법 확이
 +
 +<code>
 +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"
 +}
 +</code>
 +
 +===== Rim Lighting 적용 =====
 +
 +  * 림라이트 : {{language:shader:주변-정보#라이팅-모델}}
 +
 +<code>
 + 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"
 +}
 +</code>