충돌 체크

2019.01.24 02:33

PROTECTED ARTICLE. TYPE THE PASSWORD.

일단 결과물부터


* 찬조출연. 앵듀네 크리미 



일단 이걸 이해하려면 패럴렉스 셰이더부터 이해해야 하는데요

기본 공식은 이거고 

http://egloos.zum.com/chulin28ho/v/3749030

 

언리얼에서는 Bump offset이라는 노드로 존재하고 있습니다.
http://api.unrealengine.com/KOR/Engine/Rendering/Materials/HowTo/BumpOffset/


유니티의 엠플리파이트 셰이더에서는 

패럴렉스 옵셋 parallax offset 이라는 이름으로 존재하고 있고요 





캐네디언이 된 풍풍풍이의 글도 좋구요 

https://m.blog.naver.com/PostView.nhn?blogId=sorkelf&logNo=40125344612&proxyReferer=https%3A%2F%2Fwww.google.com%2F



알란 아저씨의 글도 좋습니다. 

https://www.alanzucconi.com/2019/01/01/parallax-shader/



우선 자료가 필요합니다. 

자료는 고양이 사진과 깊이 사진. 


깊이 사진은 제가 걍 그린 겁니다. 캬캬캬캬 

뎁스를 출력할 수 있는 카메라나 렌더러가 있다면 더 정확하겠지요. 뭐 이걸로도 충분. 



패럴렉스는 어차피 시차 보정. 즉 UV 눈속임이지 뭔가 대단한게 아닙니다. 공식도 쉽고 가벼운 편이예요 

효과도 좀 애매한 점이 없지 않고요 

너무 크면 티가 납니다. 요새 페이스북 3D 카메라인가 뭔가 있던데 그거랑 똑같아요 



핵심은 

float4 offsetTex = tex2D(_HeightTex, IN.uv_MainTex);

float2 offset = (IN.viewDir.xy / IN.viewDir.z) *(1-offsetTex.r) *_Depth;


이 두 줄입니다. 


기본 원리는 '기울였을때 UV를 내 방향으로 이동시킨다' 예요. 그러면 깊이가 있는 것처럼 느껴지거든요 


아래 그림 보세요. 

저게저게 깊이가 있는게 아니예요. 기울였을때 UV가 내 쪽으로 이동하는거 보이잖아요 

그래서 IN.viewDir.xy 입니다. [각주:1]




그래서 이렇게 이동한만큼의 위치를    fixed4 c = tex2D (_MainTex, IN.uv_MainTex- offset) * _Color;

로 UV에다가 이동시켜주면 됩니다 


풀코드입니다. 대단히 짧아요 



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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Shader "Custom/height"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Normal("Normal", 2D) = "bump" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _HeightTex("Height", 2D) = "white" {}
        _Depth("Depth",float)= 0.2
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
 
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows
 
        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
 
        sampler2D _MainTex;
        sampler2D _HeightTex;
        sampler2D _Normal;
        half _Glossiness;
        half _Metallic;
        float _Depth;
        fixed4 _Color;
 
        struct Input
        {
            float2 uv_MainTex;
            float2 uv_Normal;
            float3 viewDir;
        };
 
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            
            o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_Normal));
            
            float4 offsetTex = tex2D(_HeightTex, IN.uv_MainTex);
            float2 offset = (IN.viewDir.xy / IN.viewDir.z) *(1-offsetTex.r) *_Depth;
            
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex- offset) * _Color;
 
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs


  1. 이게 주의해야 할게, UnpackNormal로 노말맵을 받을때만 이렇게 되고, 이게 없으면 다른 축입니다. 노말맵이 있으면 서피스 부분이 탄젠트 좌표로 돌아가고 없으면 월드 좌표로 돌아가서 뷰 디렉션도 바뀝니다. -IN.viewDir.xy 로 해주세요 주의. [본문으로]

'공부는 숨쉬듯이 > 유니티 엔진' 카테고리의 다른 글

고양이 입체 영상을 만들자! Parallax shader  (0) 2019.01.22
Fake Interior shader  (0) 2019.01.22
melting shader  (0) 2019.01.21
melt shader 기본형 만들기  (0) 2019.01.19
SSS Shader for Unity  (0) 2019.01.19
텍스쳐 회전시키기  (0) 2019.01.11

시차보정을 이용한 페이크 인테리어 쉐이더 


심시티나 스파이더맨에서도 사용함 

http://www.andrewwillmott.com/talks/from-aaa-to-indie


유니티 포럼에서 이 내용에 대해 토의

https://forum.unity.com/threads/interior-mapping.424676/#post-2751518


알란주코니의 모음 

https://www.alanzucconi.com/2018/09/10/shader-showcase-9/



// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'


// Adapted to Unity from http://www.humus.name/index.php?page=3D&ID=80

Shader "Custom/InteriorMapping - Cubemap"

{

Properties

{

_RoomCube("Room Cube Map", Cube) = "white" {}

[Toggle(_USEOBJECTSPACE)] _UseObjectSpace("Use Object Space", Float) = 0.0

}

SubShader

{

Tags { "RenderType" = "Opaque" }

LOD 100


Pass

{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag


#pragma shader_feature _USEOBJECTSPACE


#include "UnityCG.cginc"


struct appdata

{

float4 vertex : POSITION;

float2 uv : TEXCOORD0;

float3 normal : NORMAL;

float4 tangent : TANGENT;

};


struct v2f

{

float4 pos : SV_POSITION;


float2 uv : TEXCOORD0;


float3 viewDir : TEXCOORD1;

};


samplerCUBE _RoomCube;

float4 _RoomCube_ST;


// psuedo random

float3 rand3(float co) {

return frac(sin(co * float3(12.9898,78.233,43.2316)) * 43758.5453);

}


v2f vert(appdata v)

{

v2f o;

o.pos = UnityObjectToClipPos(v.vertex);



// uvs

o.uv = TRANSFORM_TEX(v.uv, _RoomCube);


// get tangent space camera vector

float4 objCam = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0));

float3 viewDir = v.vertex.xyz - objCam.xyz;

float tangentSign = v.tangent.w * unity_WorldTransformParams.w;

float3 bitangent = cross(v.normal.xyz, v.tangent.xyz) * tangentSign;

o.viewDir = float3(

dot(viewDir, v.tangent.xyz),

dot(viewDir, bitangent),

dot(viewDir, v.normal)

);


// adjust for tiling

o.viewDir *= _RoomCube_ST.xyx;


return o;

}


fixed4 frag(v2f i) : SV_Target

{


// room uvs

float2 roomUV = frac(i.uv);


// raytrace box from tangent view dir //이 부분을 모르겠음

float3 pos = float3(roomUV * 2.0 - 1.0, 1.0);

float3 id = 1.0 / i.viewDir;

float3 k = abs(id) - pos * id;

float kMin = min(min(k.x, k.y), k.z);

pos += kMin * i.viewDir;


// randomly flip & rotate cube map for some variety

//float2 flooredUV = floor(i.uv);

//float3 r = rand3(flooredUV.x + 1.0 + flooredUV.y * (flooredUV.x + 1));

//float2 cubeflip = floor(r.xy * 2.0) * 2.0 - 1.0;

//pos.xz *= cubeflip;

//pos.xz = r.z > 0.5 ? pos.xz : pos.zx;



// sample room cube map

fixed4 room = texCUBE(_RoomCube, pos.xyz);


return float4(id, 1);

//return fixed4(room.rgb, 1.0);

}

ENDCG

}

}

}

'공부는 숨쉬듯이 > 유니티 엔진' 카테고리의 다른 글

고양이 입체 영상을 만들자! Parallax shader  (0) 2019.01.22
Fake Interior shader  (0) 2019.01.22
melting shader  (0) 2019.01.21
melt shader 기본형 만들기  (0) 2019.01.19
SSS Shader for Unity  (0) 2019.01.19
텍스쳐 회전시키기  (0) 2019.01.11

melting shader for Unity 

서피스로 충분해서 노드 분석으로 코드로 재작성. 

엠플리파이드 예제 안에 있는 내용을 보기 편하게 재정리하고 살짝 개량함

쓸데없는 부분 제거. 


  





'공부는 숨쉬듯이 > 유니티 엔진' 카테고리의 다른 글

고양이 입체 영상을 만들자! Parallax shader  (0) 2019.01.22
Fake Interior shader  (0) 2019.01.22
melting shader  (0) 2019.01.21
melt shader 기본형 만들기  (0) 2019.01.19
SSS Shader for Unity  (0) 2019.01.19
텍스쳐 회전시키기  (0) 2019.01.11

멜트 기본형 만들기 - 엠플리파이트 셰이더 안에 있는 예제 분석 공부입니다 



일단 버텍스 셰이더에서 


float meltHeight = _Height - vertexPos.y;


을 추가해서 

v.vertex.xyz += float3(0, meltHeight, 0);


을 만듭니다. 


이렇게 되면 _Height 값을 조절하면 , 버텍스 포지션 을 뺀 것에 다시 버텍스 포지션을 더했으니 버텍스 포지션은 0가 되고, 

모든 버텍스가 _Height 값의 y 값으로 이동하게 됩니다 



그 상태에서 여기서 

float meltHeight = min(0,_Height - vertexPos.y);


으로 만들어서, 0보다 아래 값만 존재하게 합니다. 즉 + 값은 없는거임


v.vertex.xyz += float3(0, meltHeight, 0);

그래서 이걸 다시 이렇게 넣으면 

_Height 값이 원래의 vertex y 값보다 낮으면, 즉 _Height 값보다 위에 있는 버텍스들은 결과적으로 음수가 되고, 

그러면 원래 납작한 것 처럼, _Height 값으로 이동하게 됩니다. 


그렇지만 _Height 값이 vertex.y 보다 높으면 양수가 되고, 이러면 버텍스가 올라갔던 것이 0가 되면서 안 올라가게 되고 제자리에 있게되니까 이렇게 되죠 


짜잔



자 이제 저 편평한 윗판을 좀 구기기 위해서 텍스쳐를 사용합시다. 


옛날엔 버텍스 셰이더에서 텍스쳐를 못썼지만 그건 진짜 고릿적때 얘기고.. 지금은 다 쓰죠 

하여간 씁시다


//노이즈 텍스쳐 

float4 noiseTex = tex2Dlod(_NoiseTex, float4(float2(vertexPos.x, vertexPos.z)*0.1, 0, 0));


버텍스 셰이더에서 텍스쳐를 쓰려면 tex2Dlod 함수를 써야 합니다. [각주:1]


tex2dlod (sampler, float4(UV, 0,miplevel))

 

tex2Dlod 는 밉맵의 레벨을 불러온다. 일부러 텍스쳐를 흐리게 할 때 유용함.

단 이걸 사용하면 거리에 따른 밉맵 조절이 안되는 문제가 있다.

miplevel은 0 부터 사용한다. 숫자가 늘어날수록 밉 레벨이 늘어난다.

여기서의 miplevel은 2.5라고 넣는다면 2와 3 사이를 보간해 준다


#pragma target 3.0 필요


http://kblog.popekim.com/2011/04/tex2dlod.html


출처: http://chulin28ho.tistory.com/256?category=458928 [대충 살아가는 게임개발자]



그 후에 

float noiseTexHeight= noiseTex.g + _Height;

로 _Height를 구겨주면 


기존의 _Height를 대체하기 좋겠죠

그리고 출력하면


float meltHeight = min(0, noiseTexHeight - vertexPos.y);


v.vertex.xyz += float3(0, meltHeight, 0);






츠큐웅


지금까지의 코드는 다음과 같습니다. 

_Height에 따라 올라갔다 내려갔다 한다는. 노이즈 좌표 스케일은 적당히 0.1 을 곱해줬습니다. 



float3 vertexPos = v.vertex.xyz;

//노이즈 텍스쳐 

float4 noiseTex = tex2Dlod(_NoiseTex, float4(float2(vertexPos.x, vertexPos.z)*0.1, 0, 0));

float noiseTexHeight= noiseTex.g + _Height;

float meltHeight = min(0, noiseTexHeight - vertexPos.y);

v.vertex.xyz += float3(0, meltHeight, 0);


거기다가 꼼수로 UV에서 U에 해상하는 vertexPos.x 에 _Height를 더해줘서 녹아내려갈때 흔들거리게 해줍니다. 


float3 vertexPos = v.vertex.xyz;

//노이즈 텍스쳐 

float4 noiseTex = tex2Dlod(_NoiseTex, float4(float2(vertexPos.x + _Height, vertexPos.z)*0.1, 0, 0));

float noiseTexHeight= noiseTex.g + _Height;

float meltHeight = min(0, noiseTexHeight - vertexPos.y);

v.vertex.xyz += float3(0, meltHeight, 0);




그러면 이렇게 됨



  1. 당연하지만 적절한 노이즈 텍스쳐는 넣어 놨어야죠 [본문으로]

'공부는 숨쉬듯이 > 유니티 엔진' 카테고리의 다른 글

Fake Interior shader  (0) 2019.01.22
melting shader  (0) 2019.01.21
melt shader 기본형 만들기  (0) 2019.01.19
SSS Shader for Unity  (0) 2019.01.19
텍스쳐 회전시키기  (0) 2019.01.11
씬 머지 기능에서의 한계점  (4) 2018.10.07

¨마둠파님의 정리









float2 rotateUV(float2 uv, float degrees) {
const float Deg2Rad = (UNITY_PI * 2.0) / 360.0; //1도의 라디안값을 구한다
float rotationRadians = degrees * Deg2Rad; //원하는 각도(디그리)의 라디안 값을 구한다
float s = sin(rotationRadians);
float c = cos(rotationRadians);
float2x2 rotationMatrix = float2x2(c, -s, s, c);//회전 2차원 행렬을 만든다
uv -= 0.5;//중심축을 이동시켜 가운데로 만들고
uv = mul(rotationMatrix, uv);//회전한 다음에
uv += 0.5;//다시 중심축 이동시켜 제자리로 만든다
return uv;
}





언리얼에서 같은 이름의 데이터가 같은 폴더에 존재할 수 있는가?[각주:1] 




예를 들어 같은 이름의 tga 파일과 png 파일을 준비해 놓고, 


 


일단 TGA를 드래그해서 부르면 이렇게 불러진다 

그런데 그 이후에 같은 이름의 PNG 파일을 드래그해 불러 들인다면, 




이렇게 불러들이게 된다. PNG 파일은 저렇게 데이터가 완전히 없는 부분은 특정한 색상으로 채워져 보이곤 한다ㅏ. 





그렇다면 다른 폴더에 카피해 놨다가 폴더를 다시 옮기면 어떻게 될까? 같은 자리에 두 개가 생길까?



뉴 폴더에 불러놨던 smokeTest.tga 를 png 파일이 있는 Smoke 폴더로 옮겨 보았다



안된다. 같은 이름이 있다고 안된단다. 



그럼 대문자로 바꾸면 어떻게 될까? 다른 이름으로 인식할까?



해보면 아니다. 즉 결론적으로 

'파일 포맷도 상관 없고 대소문자도 상관없고 뭐가 되었건 같은 이름의 것이 같은 폴더에 존재하는 것은 불가능하다' 라는 규칙이다 


이 규칙은 매우 깐깐한데, 심지어 텍스쳐가 아닌 메터리얼을 만들었다 하더라도 같은 이름인 것을 아주 엄격하게 금지하고 있다 



다소 깐깐하긴 하지만 확실히 관리적인 측면에서의 중요성을 강조하고 있는 느낌이다 


게다가 하나 또 재미있는것은 저 텍스쳐에 붙어 있는 * 표인데, 저건 '저장' 이 필요하다는 의미다. 즉 텍스쳐를 단순히 폴더에 카피해 놨는데도 '저장' 하지 않으면 uasset으로 인식되지 않는 것 같다. 일종의 베이킹과 같은걸까



  1. 이런 점에서 유니티는 굉장히 관대한 편이다. 좋게 말하면 관대하고 나쁘게 말하면 규칙없고. [본문으로]


먼 옛날 (..한 10년전쯤) 에는 많이 쓰던 방법인데 요즘엔 라이트맵 때문에 잘 안쓰는 방법이죠 

뭐 그래도 .. 라이트맵을 쓸 수 없는 상황에서라던가 특이한 경우에 쓸만한 기능이니까 알아두면 나쁠건 없습니다. 



일단 라이트를 넣습니다. 라이트는 걍 보통 옴니 라이트라도 괜찮습니다. 

옛날에는 라디오시티 기능을 이용해서 버텍스 베이킹을 했었는데 요샌 안그래도 되는군요. (세상이 좋아졌다)



저는 여기서 색상을 보려고 굳이 조명을 좀 붉은 색으로 만들었고, 구석진 부분의 AO를 표현하고자 범위를 조금 제한했습니다. 



그리고 오브젝트를 선택한 상태에서 유틸리티에 들어가서 More -> Assign Vertex Color를 선택합니다. 



설정은 위와 같이. 

라이팅 데이터만 가져갈거니까 라이팅만으로 처리하고, 


라디오시티를 구우면 라디오시티를 가져가겠지만 지금은 아무것도 안했으니 뭐. 그리고 적은 데이터를 위한건데 라디오시티보다는 걍 일반 라이팅 데이터를 굽는게 직관적이니 그냥 처리합니다. 

Assign to Selection을 적용해 주면 버텍스 칼라에 구워집니다 


그리고 나서 그 아래 버튼인 Edit 를 눌러주면 리셋도 가능하고 구워진 것만 확인하는것도 가능합니다 


Edit를 누르면 모디파이어에서 버텍스 페인트 연것과 같은 창이 뜨거든요 


맨 위 칼라 박스 버튼들이 버텍스 칼라를 볼꺼냐 그냥 셰이딩을 볼꺼냐 그런거 선택하는 거였고 

지우개 버튼을 누르면 초기화도 시킬 수 있습니다 


하여간 이렇게 구우면


엔진으로 가져가면.. 


이렇게 엔진에서도 보입니다. 버텍스 칼라 스러운 무늬가 보이긴 하지만, 좀 강도를 잘 조절하면 보기 꽤 괜찮습니다 


아 물론 버텍스 칼라가 보이도록 셰이더를 짜야 하지만 말이죠 





그렇게 하면 이렇게 사용할 수도 있습니다 

버텍스 칼라만으로 AO를 구워서 적용한 거니까 훨씬 가볍고 좋죠


뭐 그 외에도 조절해서 이래저래 쓸 수 있습니다. RGB가 구워지니까 저렴한 라이트맵처럼 쓸 수도 있죠 


 

폴리곤 배열에 따라 이것저것 할 것도 많아서 사실 사용하기 좋습니다 






3Dmax에 들어간지는 꽤 오래 된 걸로 알고 있긴 한데...

하드섭 하시는 분들은 잘 알지만 일반 모델러나 학생들은 잘 모르는 사람들이 있길래.. 



그냥 챔퍼를 해도 뭐 기본적으로 별 무리는 없지만.. 


엣지를 늘려주면 면 배열이 엉망이 됩니다 



아니 엉망이라기 보다 짜증난다고 해야 하나. 폴리곤이 저렇게 삼각으로 뭉치니까요 

이후 모델링 할때라던가 여러 모로 짜증나는 일이 많아지게 됩니다 




그럴땐 쿼드 챔퍼를 선택해 주세요. 첫 시작 면 부터 4각형 면들로만 만들어 집니다. 면수는 약간 늘어나지만. 




그럼 면을 늘려도 짜잔 하고 이쁘게 사각형만으로 만들어진 챔퍼가 만들어지게 됩니다.