Notice
Recent Posts
Recent Comments
Link
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Archives
Today
Total
관리 메뉴

행복한 개구리

Unity 복습 21.05.09. Shader - 외곽선, Diffuse Wrap, CubeMap 본문

Unity/복습

Unity 복습 21.05.09. Shader - 외곽선, Diffuse Wrap, CubeMap

HappyFrog 2021. 5. 9. 21:42

외곽선 적용

Shader "Custom/Test1"
{
	Properties
	{

		_MainTex("Albedo (RGB)", 2D) = "white" {}
	_Thickness("Thickness", Float) = 0
		_Color("Color", Color) = (1,1,1,1)

	}
		SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 200

		Cull Front

		CGPROGRAM
		#pragma surface surf Test1 vertex:vert noambient noshadow

		float _Thickness;
	float4 _Color;

		void vert(inout appdata_full v)
	{
		v.vertex.xyz += v.vertex.xyz * _Thickness;
	}
			

		struct Input{float2 uv_MainTex;};
		void surf(Input IN, inout SurfaceOutput o){}

		float4 LightingTest1(SurfaceOutput s, float3 lightDir, float atten)
		{
			float4 color = _Color;
			return color;
		}

		ENDCG

		Cull Back

		CGPROGRAM
		#pragma surface surf Lambert 

		float _Thickness;

		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"
}

Culling효과를 반드시 정해주어야 외곽선이 적용된다.

Culling 적용 x // Culling 1,2pack모두 적용

============================================================================

Diffuse Wraping

 Wrap시킬 텍스쳐는 uv좌표를 직접 할당할 것이기 때문에 Input구조체에서 할당하지 않는다.

그리고 Wrap시킬 때는 surf가 아닌 빛으로 적용시키며 위와 같이 UV좌표는 직접 할당한다.

 

Ramp텍스쳐의 UV좌표에 ndotl과 spec을 할당하고 ramp텍스쳐의 끝부분에 흰색이 존재한다면 

대머리라서 반사광이 나오는 것만은 아니다.

이런식으로 spec의 시선벡터와 빛의벡터를 계산한 hVec이 달라지므로 그에 따른 반사광같은 효과를 볼 수 있다

환경광을 없앴더니 너무 안보여서 noambient를 지우고 외곽선을 추가하기 위해 2pack으로 나누었다. 2pack으로 텍스쳐를 표현하고 1pack으로 외곽선을 표현했다.

Shader "Custom/Test2"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    _RampTex("RampTexture", 2D) = "white" {}
       
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        Cull Front
        CGPROGRAM
        #pragma surface surf Test2 vertex:vert

        void vert(inout appdata_full v)
        {
            v.vertex.xyz += v.vertex.xyz * 0.01;
        }

        struct Input
        {
            float2 uv_MainTex;
        };

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

        float4 LightingTest2(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten)
        {
            return float4(1, 0, 0, 1);
        }
        ENDCG


        Cull Back

        CGPROGRAM
        #pragma surface surf Test2 

        sampler2D _MainTex;
        sampler2D _RampTex;

        struct Input
        {            
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;           
            o.Alpha = c.a;
        }

        float4 LightingTest2(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten)
        {
            float ndotl = dot(s.Normal, lightDir);
            float3 hVec = normalize(lightDir + viewDir);
            float spec = dot(hVec, s.Normal);
            float4 ramp = tex2D(_RampTex, float2(ndotl, spec));

            float4 final;
            final.rgb = s.Albedo * ramp.rgb;
            final.a = s.Alpha;
            return final;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

============================================================================

CubeMap

 

가슴부위와 머리 등 반사될 수 있는 부위에 배경이 반사될 예정이다.

코드 작성시 주의할 점은 여태까지와 다르게 큐브맵은

1.Cube라는 형식이 존재한다는 점

2. samplerCUBE로 선언한다는 점 (CUBE의 대문자까지 지켜줘야한다.)

3.texCUBE를 받는 형식이 조금은 다르다는 점 texCUBE(큐브맵, 월드반사값)

큐브맵을 할당하기 전 // 큐브맵을 할당한 후

보면 오른쪽에 반사되는 효과가 적용됐지만 너무 밝아서 잘 안보인다. 그래서 알베도를 0으로 만들기로 했다.

Emission출력 // Albedo 출력

아주 잘 반사가 되고있다.

쉐이더를 처음 배울때 들은 부분인데, Albedo와 Emission을 함께 사용하면 훨씬 밝아진다고 한다.. 그래서 둘 중 하나를 빼니 정상적으로 출력되는 것이다. 그리고 궁금해서 둘 다 출력해보았는데, Emission의 반사되는 모습이 더욱 선명하고 밝은 색감을 가진다. 오브젝트가 Directional Light를 등지고 있기 때문에 로봇의 앞은 Emission이 더 밝고 뒷부분은 Albedo가 더욱 밝은것이다.

Emission // Albedo

Albedo는 빛계산까지 처리하여 출력해주기 때문에 빛을 받는 부위는 오른쪽 사진과 같이 굉장히 밝게 출력된다.

반면 Emission은 출력할 색을 그대로 출력해주기 때문에 빛의 효과를 받지 않는다.

 

Bump를 적용하려 했는데, UnpackNormal을 사용하니 이런 오류가 뜬다. INTERNAL_DATA를 INPUT구조체에 선언해야 한다는데,

선언하면 이렇게 투명해진다.

궁금한건 못참아 // Unity Manual

일단 o.Normal을 그냥 적용시킨 상태이다. 이걸 위의 WorldReflectionVector라는 기능으로 반사-범프형 쉐이더로 적용시키면 될 것 같다.

 

WorldReflectionVertor를 사용하여 normal값을 적용시키니 자글자글한 느낌이 표현된다.

여기서 주의할 점은 'IN.~~~'가 아니라 Input 구조체인 IN을 그대로 대입해야 한다는 점이다.

직접 월드노멀값과 월드 반사값을 할당하면 어떨까 해서 해봣는데 오류가 난다.

o.Emission = o.Normal // IN.worldNormal // worldNormal(벡터로 구한 값)

그리고 IN.worldRefl을 적용시키면 아래와 같이 반사되는 값이 바뀌기 때문에 시선의 위치를 바꾸면 색이 바뀌는 것을 볼 수 있다.