Unity/수업내용

Unity 수업내용 21.07.15. Shader 기초 - Bump, Rim, Hologram

HappyFrog 2021. 7. 15. 12:12

우선 내가 사용할 텍스쳐를 임포트시켰다.

 

그리고 Shaders폴더와 Materials폴더를 생성한다.

몬스터 어셋은 아무거나 원하는 것으로 사용하면 된다. (Robot Kyle추천)

  • 그리고 Fire라는 Material과 Shader를 만들어준다.
  • Shader는 Standard Surface Shader형식으로 만들자.

  • 이어서 씬에 Quad를 만들어주자.
  • Quad에 Fire Material을 적용시키자.
Shader "Custom/Fire"
{
    Properties
    {      
        _MainTex ("Albedo (RGB)", 2D) = "white" {}     
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
      

        CGPROGRAM
     
        #pragma surface surf Standard fullforwardshadows

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };
              
        void surf (Input IN, inout SurfaceOutputStandard o)
        {        
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

  • 그리고 해당 쉐이더 스크립트에서 필요없는 부분을 위 코드와 같이 모두 지워준다.
  • 그리고 Material에 FireTest텍스쳐를 넣어주자.
  • 위와 같이 씬에서 불 텍스쳐가 보일것이다.
Shader "Custom/Fire"
{
    Properties
    {      
        _MainTex ("Albedo (RGB)", 2D) = "white" {}    
        _MainTex2("Albedo2 (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue" = "Transparent"}
      

        CGPROGRAM
     
        #pragma surface surf Standard alpha:fade

        sampler2D _MainTex;
        sampler2D _MainTex2;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_MainTex2;
        };
              
        void surf (Input IN, inout SurfaceOutputStandard o)
        {        
            fixed4 d = tex2D(_MainTex2, IN.uv_MainTex2);
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb; 
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
  • 그리고 텍스쳐를 한장 더 받을 수 있도록 해준다.
  • 이어서 렌더타입과 큐를 설정해준 뒤 알파값이 0인부분을 잘라내주는 alpha:fade를 작성해준다.
  • 이 때 surf안에 o.Alpha = c.a;를 작성해주어야 제대로 출력된다. => 안그러면 전부 다 투명하게 나옴

 

  • 그리고 surf에서 텍스쳐 1과 2를 섞어서 출력할 수 있도록 코드를 작성한다.
  • c는 Fire이며 d는 새로 넣은 숫자판 텍스쳐이다.
  • IN.uv_MainTex + d.r은 UV좌표에 d의 rgb중 r값을 더해주는 것이고
  • d의 UV값은 _Time.y때문에 시간에 따라 값이 바뀐다.
  • 그러면 위 짤과 같이 상승하는 듯한 효과를 줄 수 있다.
  • 이것을 이용하여 불이 타오르는 효과를 줄 수있다.

 

 

  • 따라서 2번텍스쳐에 효과로 넣을 텍스쳐를 넣어주고 코드를 살짝 수정한다.
  • c2.r값에 0.01을 곱한 이유는 c2.r을 그대로 곱하면 값이 너무 커서 크게 일그러지게 된다.
  • 투명도도 겹치는부분만 출력해주기 위하여 서로의 텍스쳐의 Alpha값을 곱해주어서 출력한다. (색깔도 맞춰주기 위해 마찬가지.)

 

  • 0분의 1로 만들어주지 않으면 왼쪽과같이 크게 일그러지게 된다.

 


몬스터에는 vertex를 이용하여 표면을 조정해보자.

Shader "Custom/Skeleton"
{
	Properties
	{
		_MainTex("Albedo (RGB)", 2D) = "white" {}
	}
		SubShader
	{
		Tags { "RenderType" = "Opaque"}

		CGPROGRAM

		#pragma surface surf Standard
		sampler2D _MainTex;

		struct Input
		{
			float2 uv_MainTex;
		};

		void surf(Input IN, inout SurfaceOutputStandard o)
		{

			fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		ENDCG
	}
		FallBack "Diffuse"
}
  • 우선 마찬가지로 Material과 Shader를 만들어준다.
  • 쉐이더 스크립트에서 텍스쳐를 한장만 받도록 하고 필요없는 부분을 모두 삭제해준다. 

  • 그리고 램버트 형식을 사용하기위해 스크립트를 수정한다.
  • 표면을 vertex를 이용하여 내가 원하는 대로 늘리거나 줄일 수 있는 형식이다.
  • 결과는 오른쪽 사진과 같이 뼈대는 그대로인데 표면은 지방이마냥 부풀어 오른 모습을 확인할 수 있다.
  • 해당코드는 해당 객체의 vertex의 normal(굴곡이라고 표현해야하나)방향의 0.01을 곱한 값만큼 증가시키겠다는 뜻이다.
  • *주의 메서드 이름 vert는 반드시 vertex:"이름"의 이름과 일치해야한다.

 


이번엔 커스텀라이트를 사용해보자.(커스텀이라 해봤자 빛효과를 없앨것이다.)

 

  • 프라그마에서 커스텀라이트를 사용한다고 선언하고
  • 그림자와 환경광을 없애준다.(noambient)

  • 그리고 surf의 내용을 없애고 커스텀라이트 메서드를 만들어준 뒤 내용으로는 까맣게 출력한다는 코드를 작성한다.
  • * 주의 커스텀라이트로 선언한 이름과 메서드의 "Lighting+'이름'"의 이름은 일치해야한다.

 


이어서 2pass를 사용해보자. 두개의 쉐이더를 동시에 사용하는 것이다.

 

Shader "Custom/Skeleton"
{
	Properties
	{
		_MainTex("Albedo (RGB)", 2D) = "white" {}
		_Color("Color", Color) = (0,0,0,0)
	}
		SubShader
	{
		Tags { "RenderType" = "Opaque"}

		Cull Front
		CGPROGRAM

		#pragma surface surf _NoLight vertex:Vert noshadow noambient
		sampler2D _MainTex;
		float4 _Color;

		void Vert(inout appdata_full v)
		{
			v.vertex.xyz += v.normal.xyz * 0.001f;
		}

		struct Input
		{
			float2 uv_MainTex;
		};

		void surf(Input IN, inout SurfaceOutput o)
		{
		}

		float4 Lighting_NoLight(SurfaceOutput s, float3 lightdir, float atten)
		{
			float4 result;
			result = _Color;
			return result;
		}
		ENDCG

		Cull Back

		CGPROGRAM
		#pragma surface surf Lambert

		sampler2D _MainTex;
		struct Input
		{
			float2 uv_MainTex;
		};

		void surf(Input IN, inout SurfaceOutput o)
		{
			float4 c = tex2D(_MainTex, IN.uv_MainTex);
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		ENDCG
	}
		FallBack "Diffuse"
}
  • 2pass를 사용할 때 주의점은
  • 1. CGPROGRAM과 ENDCG로 pass가 끝나는 지점을 명확히 설정해야하며
  • 2. Culling을 이용하여 어떤 쉐이더가 어떤식으로 출력이 될건지 순서를 정해주어야 한다.
  • 3. 렌더타입과 커스텀프로퍼티는 1pass에서 한 번만 선언해도 된다.
  • 위 코드에서는 1pass에서는 커스텀 라이트를 이용하여 외곽선을 출력하였고
  • 2pass에서는 본체의 텍스쳐를 표현했다.

 


이번엔 Hologram을 만들어보자. 무기에 적용시킬것이다.

 

 

Shader "Custom/Sword"
{
	Properties
	{
		_MainTex("Albedo (RGB)", 2D) = "white" {}
	}
		SubShader
	{
		Tags { "RenderType" = "Opaque" }

		CGPROGRAM

		#pragma surface surf Standard fullforwardshadows

		sampler2D _MainTex;

		struct Input
		{
			float2 uv_MainTex;
		};

		void surf(Input IN, inout SurfaceOutputStandard o)
		{

			fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		ENDCG
	}
		FallBack "Diffuse"
}
  • 앞선 글들과 마찬가지로 Material을 만들고 Shader를 적용시킨 뒤 해당 Material을 무기에 적용시켜준다.
  • 그리고 텍스쳐 한장만 받게 만들고 필요없는 코드를 모두 지운다. 

 

이제 반투명하게 구현해보자.

 

  • 렌더타입, 큐 = transparent로 설정해준다.
  • surf의 inout을 SurfaceOutput으로 변경해준다.
  • alpha:fade적용 및 환경광을 제거한다.
  • 모두 완료됐다면 오른쪽과 같이 투명하게 보인다.

 

  • Albedo(색깔)을 제거해주자.
  • 이어서 카메라 시야각(Vector3)을 사용하기 위해 Input안에 viewDir을 선언해준다.
  • 그리고 rim을 구해준다.
  • 구한 rim을 제곱식을 이용하여 자연스러운 효과를 연출해준다.

 

Shader "Custom/Sword"
{
	Properties
	{
		_MainTex("Albedo (RGB)", 2D) = "white" {}
		_Color("Color", Color) = (0,0,0,0)
	}
		SubShader
	{
		Tags { "RenderType" = "Transparent" "Queue" = "Transparent"}

		CGPROGRAM

		#pragma surface surf Lambert alpha:fade noambient

		sampler2D _MainTex;
		float4 _Color;

		struct Input
		{
			float2 uv_MainTex;
			float3 viewDir;
		};

		void surf(Input IN, inout SurfaceOutput o)
		{
			fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
			float rim = saturate(dot(o.Normal, IN.viewDir));
			rim = pow(1 - rim, 3);
			o.Emission = _Color.rgb;
			o.Alpha = rim;
		}
		ENDCG
	}
		FallBack "Diffuse"
}
  • 해당 칼에 색을 입히고 싶다면 Albedo나 Emission을 사용해주면 된다. => _Color를 추가했음

 

 

  • frac은 소수점 이하를 반환해주는 함수이다.
  • 그리고 rim에 월드좌표 일부와 시간값을 사용하여 frac시키면 새로운 효과를 줄 수 있다.