성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Unity - shader의 직교 투영(Orthographic projection) 행렬(UNITY_MATRIX_P)을 수작업으로 구성</h1> <p> 지난 글에서 다룬,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Unity - shader의 원근 투영(Perspective projection) 행렬(UNITY_MATRIX_P)을 수작업으로 구성 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11695'>http://www.sysnet.pe.kr/2/0/11695</a> </pre> <br /> 원근 투영에 이어 이번에는 직교 투영 행렬에 대해 다뤄보겠습니다.<br /> <br /> Main Camera의 Projection 설정을 "Orthographic"으로 바꾸고 shader를 디버깅해 보면 투영 행렬을 담은 2가지 변수에 대해 다음과 같은 decomposeProjection 값이 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [초기 Scene 화면의 기본값] <span style='color: blue; font-weight: bold'>Size = 5</span> Near = 0.3 Far = 1000 카메라 위치 = (0, 1, -10) camera.projectionMatrix.decomposeProjection _top 5.000000000 _bottom -5.000000000 _left -8.911290000 _right 8.911290000 _near 0.299959800 _far 1000.000000000 GL.GetGPUProjectionMatrix(camera.projectionMatrix, true).decomposeProjection _top -5.000000000 _bottom 5.000000000 _left -8.911290000 _right 8.911290000 _near 1999.700000000 _far 0.299959800 </pre> <br /> 원근 투영과 달라진 점이 있다면, Unity의 Inspector 화면에서 원근 투영에 있던 FOV 옵션이 없어지고 근-평면과 원-평면의 크기를 나타내는 Size가 새로 생겼습니다. 그리고 위의 설정일 때 shader의 glstate_matrix_projection, unity_CameraWorldClipPlanes 내장 변수의 값은 다음과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > glstate_matrix_projection = [0.112217200 0.0 0.0 0.0; 0.0 -0.2 0.0 0.0; 0.0 0.0 0.001000300 1.000300000; 0.0 0.0 0.0 1.0] unity_CameraWorldClipPlanes[0] x = 1.000000000, y = 0.000000000, z = 0.000000000, w = 8.911290000 unity_CameraWorldClipPlanes[1] x = -1.000000000, y = 0.000000000, z = 0.000000000, w = 8.911290000 unity_CameraWorldClipPlanes[2] x = 0.000000000, y = -1.000000000, z = 0.000000000, w = 6.000000000 unity_CameraWorldClipPlanes[3] x = 0.000000000, y = 1.000000000, z = 0.000000000, w = 4.000000000 unity_CameraWorldClipPlanes[4] x = 0.000000000, y = 0.000000000, z = -1.000000000, w = 1989.700000000 unity_CameraWorldClipPlanes[5] x = 0.000000000, y = 0.000000000, z = 1.000000000, w = 9.700010000 </pre> <br /> 이번에도 역시 OpenGL을 따르는 투영 행렬과 유니티가 실행하는 환경에서의 투영 행렬 공식이 달라질 수 있는데 제 테스트 환경에서는 다음과 같습니다.<br /> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'> [OpenGL을 따르는 투영 행렬]<br /> <br /> ${<br /> P = \begin{bmatrix} \frac {2} {r - l} & 0 & 0 & 0 \\ 0 & \frac {2} {t - b} & 0 & 0 \\ 0 & 0 & \frac {-2} {f - n} & \frac {-(f + n)} {f - n} \\ 0 & 0 & 0 & 0 \end{bmatrix}<br /> }$<br /> <br /> [실행 환경에 맞는 투영 행렬 - 아래는 DirectX를 사용하는 윈도우 환경에서의 투영 행렬]<br /> <br /> ${<br /> P = \begin{bmatrix} \frac {2} {r - l} & 0 & 0 & 0 \\ 0 & \frac {-2} {t - b} & 0 & 0 \\ 0 & 0 & \frac {1} {f - n} & \frac {f} {f - n} \\ 0 & 0 & 0 & 0 \end{bmatrix}<br /> }$<br /> </div><br /> <br /> 실제로 camera.projectionMatrix.decomposeProjection의 값을 위의 투영 행렬 공식에 대입하면 다음과 같은 값들이 나옵니다.<br /> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'> [OpenGL을 따르는 투영 행렬]<br /> <br /> ${<br /> P = \begin{bmatrix} 0.112217200 & 0 & 0 & 0 \\ 0 & 0.2 & 0 & 0 \\ 0 & 0 & -0.002000600 & -1.000600099 \\ 0 & 0 & 0 & 0 \end{bmatrix}<br /> }$<br /> <br /> [실행 환경에 맞는 투영 행렬 - 아래는 DirectX를 사용하는 윈도우 환경에서의 투영 행렬]<br /> <br /> ${<br /> P = \begin{bmatrix} 0.112217200 & 0 & 0 & 0 \\ 0 & -0.2 & 0 & 0 \\ 0 & 0 & 0.001000300 & 1.000300049 \\ 0 & 0 & 0 & 0 \end{bmatrix}<br /> }$<br /> </div><br /> <br /> <hr style='width: 50%' /><br /> <br /> 이것을 shader 코드에서 구현하는 방법은 투영 행렬과는 다소 다릅니다. 왜냐하면 직교 투영을 하는 경우 FOV가 아닌 단순 직육면체를 나타내는 절두체의 크기를 구해야 하기 때문입니다.<br /> <br /> <img alt='ortho_projection_1.png' src='/SysWebRes/bbs/ortho_projection_1.png' /><br /> <br /> 다행히 이 크기는 <a target='tab' href='https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html'>unity_OrthoParams</a>에서 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 이름: unity_OrthoParams 형식: float4 설명: x is orthographic camera’s width y is orthographic camera’s height z is unused w is 1.0 when camera is orthographic, 0.0 when perspective. </pre> <br /> 따라서 shader에서는 다음과 같이 투영 행렬을 재구성할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > v2f vert (appdata v) { float4 pos; v2f o; float orthoWidth = unity_OrthoParams.x; float orthoHeight = unity_OrthoParams.y; float nearPlane = _ProjectionParams.y; float farPlane = _ProjectionParams.z; <span style='color: blue; font-weight: bold'>float top = orthoHeight; float bottom = -top; float right = orthoWidth; float left = -right; float p00 = 2 / (right - left); float p11 = -2 / (top - bottom); float p22 = 1 / (farPlane - nearPlane); float p23 = farPlane / (farPlane - nearPlane);</span> float4x4 projectionMatrix; projectionMatrix[0] = float4(p00, 0, 0, 0); projectionMatrix[1] = float4(0, p11, 0, 0); projectionMatrix[2] = float4(0, 0, p22, p23); projectionMatrix[3] = float4(0, 0, 0, 1); pos = mul(unity_ObjectToWorld, v.vertex); pos = mul(UNITY_MATRIX_V, pos); <span style='color: blue; font-weight: bold'>pos = mul(projectionMatrix, pos);</span> // pos = mul(UNITY_MATRIX_P, pos); o.vertex = pos; return o; } </pre> <br /> Unity의 Scene 디자인 화면에서 정상적으로 직교 투영 변환이 되었는지는 보기 방식을 "Iso(metric)"로 바꿔야 합니다.<br /> <br /> <img alt='ortho_projection_2.png' src='/SysWebRes/bbs/ortho_projection_2.png' /><br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1855
(왼쪽의 숫자를 입력해야 합니다.)