좋은 책 감사드립니다^^* 그리고 책을 읽다가 궁금한 것이 있습니다 CHAPTER 10 - 그림자 기법을 평정한 그림자매핑 단원에서 난반사광을 구할 때 float형을 쓰더라고요...이전단원까지는 float3를 쓰는데...형을 바꾸면 값이 짤려서 나오지않나요..? (219페이지입니다)
현재 이삿짐을 싸버려서 책을 볼수 없는관계로..... 대충 생각나는대로 답변을 달아봅니다.
난반사광은 어차피 코사인 함수일 뿐이므로 빛의 위치에 따른 난반사광의 차이는 float이 맞습니다. 거기다가 빛의 색상(RGB)를 곱한 결과를 저장하면 float3가 되는거죠. 즉 float만 쓰면 greyscale이 되는거고 거기다 색상(RGB)를 곱하면 float3가 되는겁니다.
이삿짐 때문에 현재 소스코드를 볼수 없지만 그림자 매핑에서 색을 입힐때는 픽셀쉐이더에서 마지막에 색상을 하나 곱하는게 아닌가 추측만 해봅니다~
아직 모르겠어요.. 생각보다 일이 커져서.. 대학 교재로도 채택되고 있어서... 고민중입니다..
원래 생각으로는 책 판매량이 줄어들면 그때 공개해서 출판사에도 피해를 안주고 책이 절판되는 일이 있더라도 온라인으로 내용을 보존할 생각이었는데.. 이제 대학교재로 채택되서 계속 팔릴거 같고 그러면 출판사에서도 절판을 안시킬 거니까... 괜히 제가 온라인으로 공개해서 출판사에게 피해주고.. 그로 인해 절판까지 가는 일은 없게 하는게 나을거 같아서요. (생각보다 종이책으로 있는걸 좋아하시는분들이 너무 많으시더라구요.)
뭐든간에 고민중입니다. 출판사하고 계약조건상 제가 출간후 한 반년뒤에 온라인 공개는 가능한데.. 그럼으로 인해서 종이책이 사라지는 일까지 이어지는 일이 없었으면 해서요..
지금 현재 생각으로는 당분간 공개 안하는게 낫겠다 싶습니다. 자세한건 책 판매되는거 더 살펴보고 결정하겠습니다.
책을 샀는데...프로젝트 돌리면 \program files\microsoft directx sdk (august 2007)\include\d3d9.h(37): fatal error C1083: 포함 파일을 열 수 없습니다. 'stdlib.h': No such file or directory 이런 에러가 끝도 없이 생기네요. vs 2005만 쓰다보니 인클루드 관련된 문제인거 같긴 한데 명확하게 이유를 알수 없어요. 심지어는 전부 복붙해서 프로젝트 폴더 내에 붙여도 관련 참조 링크에러가 끝도 없이 뜨구요. 해결방법 알려주시면 감사하겠습니다 ㅠㅠ
위의 형태는 책에서 나온 TBN을 전체한 것과 같지요.. 즉 접선->월드변환(사실 TBN은 탄젠트, 종법선, 노말을 모아서 만든 행렬이란 의미이므로 어떻게 표현해도 이게 틀리다곤 할 순 없습니다. 따라서 TBN은 접선 <--> 월드 공간변환을 하는 행렬이다.. 라고 해야 둘다 포함하는 케이스..이게 더 정확하죠..)
어쨌든 책에서 TBN이 이걸 접선->월드고안 변환이라고 할 떈 TBN을 이미 전치한 바로 윗줄의 TBN을 의미한 거였습니다. 혼란을 드렸다면 죄송합니다.
안녕하세요~ 다시 와보니 바로 윗글에 글 남긴 사람이네요 ㅎㅎㅎ Appendix A 까지 다 보고 코드로 적용해본다음 후기 올리려 왔답니다
지금으로부터 한.. 7일 전, 처음 이 책을 서점에서 목차를 봤던 기억이 나네요 ㅎㅎ 처음엔 그냥 셰이더 책 또 하나 나왔구나 라고 생각을 하고 지나쳤더랬죠 그런데 저 개인적으로 프로젝트를 진행하던 중이였습니다, 그동안 수학,물리를 공부해서 실질적으로 뭔가 보려고 했지만, 막상 시간이 지나다보니 셰이더를 넣어야겠다는 생각에 봉착하게 됐습니다, 그런데 2,3년 전 셰이더를 본적이 있긴 하지만 다시 시작해볼려고 하니깐 막상 주변엔 셰이더 관련 책이 있긴 하지만 셰이더 책들 분량이 대부분 많아 다시 보기에도 귀차니즘이 승리할 것 같아 그냥 필요한 부분만 보면서 넘어가자라는 식으로 하려고 했으나 원래 성격이 그렇지 못한지라 결국 다른 방법이 없을까 생각을 했죠 생각을 하던중 셰이더 프로그래밍 입문 책의 목차가 머리속에 사~~악 지나가더군요, 그때 드는 생각이 그래! 이거다! 라는 생각이 들어 바로 서점으로 튀어가서 한권 구입했더랬죠 ㅎㅎ 처음엔 챕터8 정도까지만 본 다음 다시 본래 프로젝트로 돌아가려 했지만 8 장을 vs로 코딩하던 중 드는 생각이 "어.. 이 책 뭔가 다르다" 는 생각이 들게 되더군요 처음 해본다면 오랜 시간 투자해야되는 여러가지 DX 설정들과 셰이더와의 상호 상태와 값과 그 의미들이 간단 명료하고 잘 연결 되어있다는 느낌을 받게 되더군요 결국 한챕터 더 보까? 더보까? 더 보까? 하다가 끝까지 보게 됐습니다
인터넷 뒤져가며 두꺼운 셰이더 책 뒤져가며 찾아 설정해야 되는 것들에 대한 시간 절약과 셰이더 소스코드들의 간략하면서도 이해가 잘가는 설명은 처음 앞뒤 뭐 대락 소개나 이런 저런것 빼면 2백 50~60 페이지 정도 되는 분량이 좀 적은거 아닌가? 조금 비싼거 아닌가? 라는 생각을 완전히 뒤바꿔 주더군요
기본적인 탄탄한 노하우가 담겨져 있는 책이라는 느낌이 들었습니다
게임관련 많은책을 보긴했지만 이렇게 직접 사이트에 찾아와 후기를 남기는건 처음이네요
또 질문 하나 하고싶어서 글을 남기기도 한건데요
Q: 대부분 프로그래머는 자신이 익힌 것을 잘 공개하려는 마인드를 갖고 있진 않다고 생각 하곤 합니다, 그런데.. 사이트에 보면 이 책의 일부 챕터가 올라와있는것도 볼 수 있고 책 또한 기본적인 내용들을 담았다곤 했다고 하셨지만 노하우가 많이 묻어나온 책이라는걸 느낄 수가 있었습니다, 책을 보면서 이렇게 까지 이 한권의 책으로 도움을 받아도 되나 라는 생각을 하게 되었는데요, 왜 이리 적지 않은 부분을 공개한것인지 궁금하네요 ㅎㅎ p.s 렌더몽키를 소스코드로 옮기는 과정은 감탄이 나오더군요 ㅎㅎ 스승으로 모셔도 될까요?? ㅎㅎㅎㅎ
일단 이 책이 도움이 되었다니 정말다행입니다. 몇만원하는 책 사셨는데 도움이 안되면 정말 죄송스럽지요 ㅎㅎ..
다른 플머뷴들은 모르겠지만 제가 공개를 꺼려왔던건(한때 그랬죠) 제 지식에 대해 스스로 다신이 없어서였죠. 난 이렇게 알고있는데 그래서 다른 사람들에게 이렇다 말했는데.. 내가 그걸 잘못알고있는거여서 다른 사람에게 누를 끼치지 않을까... 하는 걱정이요... 근데 어느순간 뒤돌아보니 저보다도 허접한 지식을 사람들에게 전파하며 누를 끼치는 사람이 너무 많더라구요. 그래서 '아 , 차라리 내가 떠드는게 낫겠구나' 생각이 들아서 제가 아는건 다 공유하는 정신으로 가고 있습니다.
한 2010년부 그런것 같네요.
다른 사람이 제 지식을 다 가져가서 제 가치가 떨어지는건 걱정하지 않죠. 어차피 이미 알고있는 지식이나 재탕하며 살아나갈 생각은 없구요. 발전이 없는 제 모습이 보이면 언제라도 떠날거니까요.
이 셰이더책을 쓰게된 계기, 그리고 홈피에 다 공개하려고까지 했던 또다른 이유는 이 자료를 썩혀두기 싫어서 였습니다. 학교에서 12학기나 가르쳐봐서 이게 얼마나 좋은 내용인지(특히 초보자들에게) 확신이 있었거든요. 책으로 안나오면 그냥 블로그에 공개한단 생각으로 썼죠. 어차피 몇년지나면 필요없을지도 모르는 내용 너무 늦기전에 사람들에게 보여주려 한게 전부입니다. 실제 한빛하고 계약할때도.. 언제라도 나머지 챕터들을 제 홈피에 공개할수 있는 조건으로 했습니다. 단 한빛에서 그런조건에도 계약을 해주셨기에 최대한 출판사에 피해안가게 절판전에는 공개안할 생각이지만요...
절 스승으로 모시는건 저야 영광입니다.다만 전 정헌님을 제자라기보다는 동료 프그래 정도로 생각할 것 같습니다. 저도 정헌님께 배울점이 많을테니까요.
7장에서 법선, 종법선, 접선에 대해 행렬을 구성할 때 나오는 설명 중에, 열기준 또는 행기준에 대해 설명이 반대가 아닌가 해서요. 저도 이 부분이 항상 헷깔리는데, 일단 mul에 대해서 msdn에서 찾아보면 아래와 같은 설명이 나옵니다.
------------------ msdn mul ------------------------------ Item Description x [in] The x input value. If x is a vector, it treated as a row vector. y [in] The y input value. If y is a vector, it treated as a column vector. ------------------------------------------------------------
보면 y 쪽에다가 벡터를 넣으면 열 벡터로 처리한다는건데, 포프님의 책에선 행기준 벡터는 mul(행렬, 벡터), 열기준 벡터는 mul(벡터, 행렬) 이라고 적혀있었습니다.
167P의 "float3x3 생성자를 이용하면 ~ 이 행렬은 월드공간을 접선공간으로 변환하는 행렬입니다."
위에서 다른 분이 같은 부분을 질문 하셨는데 이해가 되질 않아서 제 생각과 함께 질문을 드리려 합니다.
VS에서 인자로 받는 T,B,N은 VS에서 물체공간행렬을 곱하지 않고 바로 월드 행렬을 곱하기 때문에 이미 탄젠트공간에서 물체공간으로 변환된 벡터라고 저는 가정했습니다. PS에서 받은 T,B,N은 이미 월드공간으로 변환됐으므로, 그것으로 행렬을 만들면 탄젠트공간 행렬 * 물체공간 행렬 * 월드공간 행렬 이 되어 어떠한 공간상의 벡터를 탄젠트공간->물체공간->월드공간 으로 변환 시키는 합성행렬이 되는것이 아닌가요? 그런데 책에는 그 반대로 월드->탄젠트 로 변환하는 행렬이라고 되어 있습니다. 제 추측하고 반대라서요. 가르침 부탁 드립니다.
음.. 이부분은 언제나 설명을 해도해도.. 이해를 해도해도 헷갈리는 부분이에요..(특히 제가 -_-;;)
이렇게 이야기해보죠... 일단 T B N 벡터는 삼각형에서 구하죠. N이 삼각형의 표면이 향하는 방향이고 B와 T는 그 표면을 따라 흐르는 두 벡터입니다.. .즉 이 세 벡터가 정의하는것은 새로운 공간이지요. 이걸 접선 공간이라 부릅니다. 따라서 이 때 T B N 벡터는 물체공간안에 있습니다. 삼각형을 기준으로 하니 당연하겠죠?
이 때 물체공간안에 있는 어떤 벡터에 이 행렬을 곱하면 물체공간 -> 탄젠트 공간으로 변환됩니다. (아마 이 부분이 윈드토커님이 저와 다르게 이해하고 계신 부분인듯 한데.... 이건 테스트 케이스를 만들어서 실제 곱해보시면 알겁니다.) TBN에 물체행렬 공간을 곱할 이유가 없는건 이미 TBN 벡터 자체가 물체공간안에 정의되어 있어서입니다.
근데 이걸 월드 -> 탄젠트 공간 변환에 사용하려면... T B N 벡터를 월드공간으로 변환해준뒤 행렬을 만들면 되는겁니다. 어차피 법선벡터를 구할때는 평행이동(translation) 값은 중요하지 않으니 그냥 월드행렬에서 회전값만을 가져요 T B N 벡터를 그만큼 회전시킨 뒤 그 결과값으로 행렬을 만들면 그게 월드공간 -> 탄젠트 공간으로 변환하는 행렬이 되는겁니다...
여전히 이해가 안되시면 또 댓글 달아주세요... (제가 잘못알고 있는걸수도 있으니... '_' 스스로 걱정되서 이 자료까지 다시 읽어봤답니다 ㅎㅎ.. http://www.gamasutra.com/view/feature/129939/messing_with_tangent_space.php?print=1 )
아.. 이미 해결하셨군요.. 제가 이사하느라 회사 옮기느라 바빠서 이제서야 좀 답글 달 정신이 났습니다..(라고 했지만 심시티 할 정신은 있었습니다..죄송합니다 .. 흐흐흑 -_-)
셰이더에서 복수 패스를 사용할 수도 있지만... 팩스나 테크닉이란게 사실은 별다른 의미가 없습니다. 그냥 정리정돈을 돕는 개념일뿐이고. .실제 GPU에 올리는 놈은 정점쉐이더와 픽셀쉐이더 쌍(pair)일 뿐이거든요.
패스가 2개라면.. 그냥 단순히 패스0번을 설정하고 메쉬를 그린다... 아니면 패스1번을 설정하고 메쉬를 그린다의 개념 정도거든요.. 따라서 파일 하나에 여러개 패스를 넣으신다면.. 코드에서 패스를 0~n을 다 훑으며 메쉬를 그리는 부분을 찾아.. 필요한 패스만 선택적으로 그리셔야 합니다. settechnique이나 setpass등의 함수가 분명 있을거에요... 혹시 해보셨는데도 안되시면 다시 연락주세요~
안녕하세요, 궁금한게 있어 글 남김니다. 책보고 나름 생각해서 diffuse map, normal map , specular map , shadow map까지 모두 같이 적용해서 나름 만족하고 있었는데 ㅎㅎ,, shadow map 에서 라이트 위치 ( 500,500,-500,1)를 조금 큰 값(예를들면 y를 1000)으로 변경 시키면 왜 그림자가 이상하게 질까요. 원인이 무엇인지 힌트좀 부탁드립니다.
게임따라 다른데.. 사실 해의 위치는 어디있어도 크게 상관은 없어요.. Project Matrix만 제대로 만들어주면요.. 두가지 팁을 드리자면..
1) Orthogonal(직교) 행렬을 사용해보세요. Perspective(원근투시)보다 컨트롤이 더 쉬워요.
2) 해가 어디에있는지와 상관없이... 근접평면(near plane)을 shadow caster(그림자를 드리우는 놈)바로 앞에 배치.. 즉...
해가 2000미터 높이에 있는데... 평면이 10미터에.. 그리고 그림자를 드리우는 놈이 50미터 높이에 있다면 near plane을 1500미터 정도로.. far plane을 2050 미터 정도로 해서 투영행렬을 만들어보세요. (LightProjMatrix를 말하는겁니다.)
영향을 줍니다. GPU하드웨어에 보면 텍스쳐 룩업을 책임지는 텍스처 유닛이란게 있는데 이게 캐시 메모리를 가지고 있습니다. 따라서 텍스처가 작으면 작을수록 캐시 메모리에서 곧바로 읽어올수 있으므로 당연히 더 빠릅니다. 512x512도 캐시에 다 들어간다면 성능의 차이는 크게 없겠지만 보통 텍스처 유닛의 캐시유닛은 매우 크기가 작지요..
1) VFX회사는 보통 자체 셰이딩 언어와 툴을 쓸 겁니다. 게임쪽에서는 HLSL이나 GLSL류로 셰이더를 작성하는데 어떤 툴로 작성하는지는 전혀 중요하지 않습니다. 저 개인적으로는 그냥 메모장에서 셰이더를 작성하니까요. -_-;; 렌더몽키를 사용해서 모든 테스트를 한 뒤 거기서 나온 HLSL을 좀 추려서 게임에 사용하는 사람들도 많이 봤습니다. 그외에 노드기반 셰이더 에디터도 존재하구요.
일단 셰이더 언어를 짜두면 그걸 게임을 실행할때 읽어와서 사용하는게 전부입니다. Visual Studio를 이용해서 작성한다면 그냥 Visual Studio를 텍스트 에디터로 사용하는 수준이 아닐까 하네요..
2) Displacement Map은 GPU Gems시리즈 중 하나에 나왔던 걸로 기억합니다. 솔직히 말씀드리면 제가 소개드린 책/논문 보다 쉽게 나온 자료를 본적이 없고 GPU Gems 쪽이 그나마 좀 오래되서 난이도가 낮다고 생각합니다.
책을 좋게 봐주셔서 감사합니다~ 2편을 쓸 생각은 아직 없습니다. 1편만한 책이 안나올거 같아어요.. 나중에 뭔가 확신있게 쓸수있는 내용이 있으면 쓰겠지만.. 아마 안그럴거 같군요.. 1편의 내용은 대학에서 3년을 강연한거라 "이건 좋은 책이 된다!"라고 자신감을 가지고 확실히 쓴거였어요 ㅎㅎ
네 보통 그래픽 하시는분들이 모델링 툴에서 TBN다 저장해서(정점정보로) 보내주십니다. 보통 플러그인을 쓰구요.. 손으로 한땀한땀 해주시는 분들은 못봤습니다.. 주로 exporter에서 해주는거 같아요. fbx exporter만 보시더라도 거기에 tangent space를 구워주는게 있었던듯~
저 링크를 읽기 귀찮으니 생략하고.. 일단 머가 헷갈리시는지는 알거 같으니 설명을 씁니다.
1) TBN은 World -> Tangent인가 Tangent->World인가?
둘답니다.. TBN행렬을 만드는 법은 두가지입니다..
Tx Ty Tz Bx By Bz Nx Ny Nz
또는
Tx Bx Nx Ty By Ny Tz Bz Nz
위 두 행렬은 사실 둘다 역행렬 관계죠.. 따라서 TBN을 어떻게 만들어주냐에 따라 월드->탄젠트 또는 탄젠트->월드가 됩니다.
고로 어떻게 말하던 맞는건데.. 전 제 설명이 오히려 이해하기 쉽다고 생각합니다. 표면상에 존재하는 좌표벡터들은 현재 월드(또는 물체) 좌표계에 있는거니까요.
2) 맥스플러그인에서 하는짓 맥스 플러그인에서 하는짓은 각 삼각형을 살펴본뒤 그 삼각형에서 직각으로 바깥쪽을 향하는 벡터를 N 그리고 표면을 따라 흐르는 두 직각인 좌표를 B와 T로 저장하는것 뿐입니다. 고로... 그 좌표를 TBN이라고 볼수도 TBN의 역이라 볼수도 있지만 (1번에서 이미 설명)... 그냥 제 방식대로 이해하시는게 좀더 편하리라 생각합니다 -_-a..
3) 물체가 회전할 경우 TBN좌표는 원래 물체에 종속되어 있으므로.. 버텍스 쉐이더에서 받아왔을때는 물체공간에 있습니다. 하지만 물체가 회전을 할수도 있으므로 그 회전 값을 받아들이기위해 TBN에 월드행렬을 곱하는겁니다. 일단 이 곱을 하고 나면 TBN벡터들이 월드공간에 있죠... 이걸로 TBN행렬을 만들면 그게 월드--> 탄젠트 변환이 되는겁니다... 그거의 역을 구하면 탄젠트--> 월드가 되는거구요.. 하지만 1)에서 말씀드렸다싶이 TBN을 만드는 방법에는 2가지가 있으므로.... TBN이 탄젠트->월드라고 설명하는 책이나 웹페이지도 있습니다. (역시 전 제 방법이 맞다고 우깁니다 ㅋㅋㅋㅋ)
포프님! 초면에 실례지만 MSAA-깊이버퍼재사용 부분에 관해서 여쭤볼게 있습니다. (디테일한 책 또한 아주 잘 보고 있습니다. 디테일 포프!)
msaa를 적용하기 위해서 d3d device를 D3DMULTISAMPLE_4_SAMPLES 옵션을 주어 생성하였습니다.
그리고 메인이 되는 scene을 백버퍼에 렌더링 하여서 msaa가 적용되게 하였습니다.
그리고 이후에 포스트이펙트를 적용하기 위해서
백버퍼의 내용을 텍스쳐에 복사한 후에 이 텍스쳐를 렌더타겟으로하여 포스트이펙트 처리를 합니다.
그런데 아웃라인을 딴다든가 하는 포스트이펙트에서 메인scene을 그릴 때 갱신된 z버퍼가 필요한데 포스트이펙트를 위해서 생성된 텍스쳐와 기본z버퍼의 샘플링type이 틀려서 문제가 되고 있습니다.
일단 해결은, z버퍼가 필요한 포스트이펙트는 렌더타겟을 백버퍼-기본z버퍼로 설정한후 렌더링된 백버퍼의 내용을 다시금 텍스쳐에 복사해서 사용하는 방법으로 해결은 하였습니다만,...
가장 되었으면 하는 해결책은 샘플링type(D3DMULTISAMPLE_4_SAMPLES)이 적용된 기본z버퍼를 샘플링type이 없는 z버퍼에 복사하는 것인데, 구글링, d3d help를 뒤져보니
Additional Restrictions for Depth and Stencil Surfaces
The source and destination surfaces must be plain depth stencil surfaces (not textures) (see IDirect3DDevice9::CreateDepthStencilSurface). Neither of the surfaces can be discardable. The entire surface must be copied (that is: sub-rectangle copies are not allowed). Format conversion, stretching, and shrinking are not supported. StretchRect cannot be called inside of a BeginScene/EndScene pair.
위와 같이 뎁쓰와 스텐실 서피스에 대해서는 포맷 변환이 불가능 하다고 하네요....
현재 생각으로는 msaa가 적용된 백버퍼를 사용할 경우(전제) 1.z버퍼 값이 필요없는 포스트이펙트 2.z버퍼의 값이 필요한 포스트이펙트의 경우 두가지를 분리하여서, 2에 해당하는 케이스는 렌더타겟으로 백버퍼-디폴트z버퍼를 셋팅하여서 렌더를 하는 방법등으로 해결 해야 하는 걸까요?
같은거에요. 근데 screen space reflection이 깊이 맵을 sampling하는 이유는 post-process 단계에서 (즉 화면공간에서) 리플렉션을 먹이는 기법이라.. 그때는 정점의 위치를 알수 없거든요. 고로 깊이 버퍼를 샘플링해서 거기서 각 픽셀의 위치를 계산한뒤 리플렉션을 하는것 뿐입니다.
사용하는 그래픽 솔루션에서 HLSL셰이더를 제공해서, 잘 모르는 초보지만 열심히 책 봤습니다. 한 번 봐서는 이해가 잘 안될 것 같네요. 여러 번 읽고 코드도 직접 작성해봐야겠어요.ㅎㅎ 혹시, 포프님 책 이후에 HLSL을 더 공부하기 위해서는 어떤 책이나 자료를 보는 게 좋을까요? appendix에 나와있는 GPU젬스 시리즈 링크는 안들어가지네요 ㅡㅡ;; 영문이라면 해외자료나 도서도 무관합니다. 고견부탁드려요 감사합니다ㅎ
안녕하세요. 책 보다가 궁금한 게 있어서 질문 드립니다. 2장의 정점셰이더/정점셰이더의 입력데이터 부분을 보면 float4에 대해서 4개의 성분을 가지는 벡터라고 되어 있는데요, x, y, z는 정점의 위치라는 걸 알겠는데 나머지 w는 무슨 성분인지 잘 모르겠습니다. -_-; 그냥 비워두는 건가요?
안녕하세요 포프님 책과 블로그로 공부하고 있는 초보 쉐이더 개발자입니다. :) 다름이 아니고 이번에 차량의 와이퍼 효과를 구현해야하는데요. 와이퍼로 차량 전면 유리의 빗물, 이물질들을 와이퍼로 제거하는 효과를 어떤 식으로 구현해야할까요? 가이드 라인을 제시해주시면 열심히 헤딩해보겠습니다.
안녕하세요.포프님. 최근에 포프님책으로 쉐이더입문한 프로그래머입니다. 꽤 오래된 글에 댓글을 다는 것이 좀 그렇기는 합니다만 공부중 정오표로 수정한 부분에 의문이 있어 이렇게 댓글을 답니다.
'열기준변환행렬'과 '행기준변환행렬'에 대한 부분인데 제 소견으론 기존에 포프님이 생각하셨던 것이 더 맞다고 봅니다.(위에 '몽상가'님께서 의문을 가지신 부분입니다.)
'행기준행렬'('행기준변환행렬'이 아닙니다.)이 'row major matrix'이고 '열기준행렬'이 'column major matrix'를 표현한 것이라면 3X3행렬을 기준으로 행기준행렬과 열기준행렬의 원소 순서는 아래와 같을 것입니다.
1) 행기준행렬
| Ax Ay Az | | Bx By Bz | | Cx Cy Cz |
2) 열기준행렬
| Ax Bx Cx | | Ay By Cy | | Az Bz Cz |
보통 행렬과 벡터 혹은 벡터와 행렬의 곱연산에서
1) 행기준행렬은
결과(Column Vector Result ) = 행기준행렬(row major Matrix) * 열벡터(Column Vector)
2) 열기준행렬은
결과(Row Vector Result ) = 행벡터(Row Vector ) * 열기준행렬(Column Major Matrix)
일단, 위의 '몽상가'님께서 보신 mul에 관한 MSDN의 코멘트는 mul(x, y)의 x의 인자를 벡터로 할 시에 그 벡터는 행벡터(row vector)로 처리하고 y의 인자를 벡터로 할 시에 열벡터(column vector)로 처리한다는 내용입니다.
즉, mul(행렬, 벡터)는 행기준행렬과 열벡터의 곱연산이며 mul(벡터, 행렬)은 행벡터와 열기준행렬의 곱연산이라고 할 수 있습니다.
행/열-기준벡터라는 말과 행/열-기준변환행렬이라는 말의 유래는 모르겠으나 검색해본바 국내의 몇몇 개인블로그에서 행/열-벡터를 행/열-기준벡터, 행/열-기준행렬을 열/행-기준변환행렬이라고 지칭하는데서 온 듯합니다. 하지만 선형대수학(linear algebra)에서 공식적으로 쓰이는 용어가 Row Vector는 행벡터, Column Vector는 열벡터, Row Major Matrix는 행기준행렬, Column Major Matrix는 열기준행렬이기도 하거니와 단순히 언어적으로 따져봐도 변화의 대상이 되는 벡터가 전혀 열에서 행으로, 행에서 열로 변화 하지 않음에도 기준변환행렬이라는 말을 쓰는 것에는 혼동의 요지가 있어 보입니다(공부하면서 했갈렸습니다 ㅠㅠ). 물론 벡터의 계( coordinate system)가 변화기는 하지만 이 경우에는 Transfer Matrix(변환행렬)이라는 용어가 따로 있고 이때의 의미는 월드행렬, 뷰행렬 등을 지칭한다는 보는 것이 더 맞지않나 싶습니다.
따라서 요는 기존에 포프님께서 정의하신바대로
1) 행기준행렬이면 행렬의 각 행과 열벡터를 곱한다.( 행렬 x 열벡터) 2) 열기준행렬이면 행렬의 각 열과 행벡터를 곱한다.( 행벡터 x 행렬)
로 하셨던 것이 더 맞지 않는가 하는 것입니다.
오래된 글에 다는 짧은 소견입니다만 한번 살펴봐주시고 제가 혼동하는 것이 있다면 말씀해주십시오.
ps. 쉐이더를 전혀 모르고 있었는데 포프님책으로 도움 많이 받고 있습니다. 앞으로도 좋은책 많이 집필해 주세요 ^^
그래서 아예 행기준 행렬/열기준 행렬이란 표현을 포기하고 핼기준 변환행렬(행벡터를 변환함) 열기준 변환행렬(열벡터 변환함)이라고 정의한겁니다.
일단 열기준/행기준 행렬은 곱셈순서와는 전혀 상관이 없는 개념입니다. 메모리에 각 요소들이 어떻게 배치되어있느냐를 결정할 뿐이죠. 어쩌다보니 opengl이 행렬*벡터 곱순서를 따르면서 행렬을 열기준으로 메모리에 저장하고 dx는 벡터*행렬의 순서로 곱하면서 행렬을 행기준으로 저장하다 보니... 거기서 생긴 혼동일 뿐이더군요.
따라서 행기준 벡터, 열기준 벡터라는 말은 이 책에서 나올 이유조차 없는 놈이구요.(메모리에 어떻게 저장되는지를 다루지 않는한...) 그래서 차라리 행기준변환행렬 열기준변환행렬이라는 표현을 쓴건데.. 그 역시 혼돈의 여지는 있는건 사실 같습니다.
셰이더 입문 책을 구입해서 샘플 파일을 좀 받으려는데요, 적어주신 한빛 미디어 사이트는 입력하면 이상한 성인 사이트로 접속이 되서 저자 블로그로 와서 받으려는데, 이곳의 링크로 클릭하면 알수 없는 일본사이트로 연결되어 샘플 파일을 어디서 받아야 하는지 잘 모르겠습니다. 확인 부탁 드려요
프로그래머 2년차에 접어드는 개발자입니다. 회사에서 유니티로만 작업하고 거의 2d게임만 만들다 보니 어느새 여기에 안주한거 같더군요 그러나최근 포프님이 만든 영상 올린거 보고 많은 깨닳음(?)을 얻어 언리얼을 공부하고 있습니다. 그리고 포프님의 동영상을 보다보니 클라이언트 프로그래머라면 셰이더는 필수 인거 같아 포프님이 지은 셰이더 입문 프로그래밍을 오늘 펼쳐보게 되었습니다. 일단 시작이지만 벌써부터 매우 느낌이 좋은거 같습니다. ^^ 그릭고 책을 펼친지 몇시간 되지 않았지만 지은이의 말이 자꾸 떠올라 DirextX를 제대로 공부해보고 싶어졌는데 Direx11으로 시작 할까 합니다 이유는 어제 포프님과 영천님이 DirectX12에 관해 이야기 하시는중 영천님이 Direx11으로 시작을 하면 좋다고 하여 DirexX11 으로 공부를 시작 해볼까하는데 어떻게 시작하는게 좋을까요?? 예제를 다운받아 소스를 분석하는게 좋을까요 아니면 책을보고 차근차근 나가는게 좋을까요? 그리고 책으로 시작하는게 좋다면 국내도서중..(영어에 약해서..)추천해주실만한 책을 혹시 있으신가요?
저도 노말매핑 부분에 TBN matrix를 만드는 과정에서 헷갈리는게 있어서 질문드립니다.
댓글에 저와 같은 고민을 찾다가 비슷한경우를 봐서 포프님의 답변을 보았는데요
아래는 포프님의 답변 내용입니다.
- 음.. 이부분은 언제나 설명을 해도해도.. 이해를 해도해도 헷갈리는 부분이에요..(특히 제가 -_-;;)
이렇게 이야기해보죠... 일단 T B N 벡터는 삼각형에서 구하죠. N이 삼각형의 표면이 향하는 방향이고 B와 T는 그 표면을 따라 흐르는 두 벡터입니다.. .즉 이 세 벡터가 정의하는것은 새로운 공간이지요. 이걸 접선 공간이라 부릅니다. 따라서 이 때 T B N 벡터는 물체공간안에 있습니다. 삼각형을 기준으로 하니 당연하겠죠?
이 때 물체공간안에 있는 어떤 벡터에 이 행렬을 곱하면 물체공간 -> 탄젠트 공간으로 변환됩니다. (아마 이 부분이 윈드토커님이 저와 다르게 이해하고 계신 부분인듯 한데.... 이건 테스트 케이스를 만들어서 실제 곱해보시면 알겁니다.) TBN에 물체행렬 공간을 곱할 이유가 없는건 이미 TBN 벡터 자체가 물체공간안에 정의되어 있어서입니다. -
위 답변에서 헷갈리는것들 질문좀 드리겠습니다ㅠㅠ
1.여기서 세번째 문단(?)에 물체공간 안에 있는 어떤 벡터에 "이 행렬"을 곱하면 이라고 하신부분의 행렬은 TBNMatrix = float3x3 (T, B, N) 를 말씀하시는건가요?
2.만약 맞다면 어째서 물체공간에서 접선공간으로 변환이 되는건가요?
탄젠트 바이노말 노말은 물체공간에 있던 벡터들인데 이 세벡터의 값으로 만들어진 회전행렬을 노말벡터값에 적용시키면 그게 접선공간 -> 물체공간 변환이지 않나요? 반대로 역행렬을 곱하면 물체 -> 접선공간이 아닌가요??
지금 이게 너무 헷갈려서 공부가 손에 잡히질 않습니다...ㅠ
윗분들은 답변을 보고 다 이해하시는데 저는 너무 헷갈립니다... 어느 부분이 틀린것인지 제가 잘못이해하는 부분을 알고싶습니다ㅠ 바쁘실텐데 죄송합니다..
TA 를 꿈꾸는 현직 3D 모델러입니다. 얼마전부터 집필하신 "셰이더 프로그래밍 입문 " 을 보면서 하나씩 따라해보고 있는데요. 궁금한 점이 하나 생겨서 이곳에 질문합니다. 책의 중반까지 보고 있는데 lightDir 를 계산하실 때에 정점좌표에서 라이트좌표를 빼서 방향벡터를 구하여 단위벡터로 만들어준 후에 dot 계산을 할때 또다시 -lightDir 을 해서 방향을 뒤집어주시는데요. (초반에 이것이 벡터의 밑둥을 서로 만나게 해주기 위함이다 라고 적혀있습니다)
그럼 아예 처음부터 lightDir 을 구할때 라이트좌표에서 정점좌표를 빼면 뒤집혀진 방향벡터를 구할 수 있지않을까.. 하는 생각이 들어서요. 제가 잘못생각한걸까요?
출판되길 기대하고 있었는데 이렇게 공개를 해주시다니 감사해요.
답글삭제이런 오픈 마인드 본받고 싶습니다. 감사합니다~!
답글삭제좋게 봐주셔서 감사합니다. ^_^
삭제출판사로부터 연락을 받았습니다. 편집이 마물되었다고.... 며칠안에 편집본 받아보고 크게 문제없으면 그렇게 진행합니다.. 이제 조만간 나오겠군요 ^_^
답글삭제혹시 아마존에 전자 출판을 해주실 의향은 없으신가요?
답글삭제출판권을 이미 한빛출판사가 가져간 관계로.... 제가 따로 전자책을 출판할 수 있는 권리가 없습니다. 여지껏 한빛에서 아마존에 전자출판한 책이 없는것 같으니.. 아마 안나오겠죠 -_-;
삭제아마존 개인출판으로는 한글책 등록이 불가능합니다-_-;
삭제강좌 정말 감사합니다.
답글삭제하나하나 보고 또 보면서 공부하고 있습니다.
출판은 언제즘 되나요?
꼭 사야겠습니다.
한빛 홈페이지를 보니 5월이라는군요!
삭제출판 날짜 정해졌나요?
답글삭제한빛 홈페이지에보니 5월 츌간예정으로 나와있군요. 정확한 날짜는 아직 모릅니다 ^^
삭제책을 기다리고 있는데요. 5월 출간예정이었는데.. 6월이 되었는데도 소식이 없는데...
답글삭제대략이라도 알 수 없을까요?
죽을 죄를 졌습니다. 저도 며칠전에 하도 안나오길래 출판사에 문의해보니 좀 늦어져서 7월 10일날 나온다고 합니다.
삭제블로그에 올려야지 생각만 하고 있다가 며칠 아프고 그뒤 며칠 아파서 까먹었습니다...
더 좋은 책이 나오기 위해 출판사에서 노력중이라 이해해주셨으면 고맙겠습니다.
다시한번 죄송합니다
별 말씀을요.. 사리 좀 쌓이고 간디와 친구를 먹은거 빼곤.... ㅎㅎㅎ
삭제하루에 3번씩 한빛에 들어가던걸... 음.. 7월 이후로 미뤄야겠습니다.
10일날 꼭 나오길 기대하겠습니다 ^^
출판사에서 온 이멜을 다시 읽어보니 7/10일 출간.. 7/11일~20일 인쇄배본.. 이라고 하는데.. 이게 무슨 차이인지 헷갈 -_-;
삭제저도 기다리고 있습니다.
답글삭제7월10일이면 한달이나 남았네요. 흑
그 대신 전신누드 화보집을 같이 넣어서 팔겠습.... -_-
삭제기..기대된다!
삭제변태들~ 흥~ -_-
삭제빨리 보고 싶어요 엉엉
답글삭제상세한 설명 감사합니다. 출신이 디자이너인지라 항상 프로그래밍 언어에 겁을먹고 있었는데 이참에 제대로 공부좀 해봐야 겠군요
답글삭제생각보다 쉐이더는 별로 어렵지 않습니다. 자잘한게 좀 있지만.. 일단 하나씩 해나가다보면 아티스트분들도 충분히 정복할수 있는 언어에요~ ^_^
삭제한빛출판사 라는 건 한빛미디어인가요?
답글삭제넹~
삭제쉐이더 기초공부를 하면서 많은 도움이 되고 있습니다.
답글삭제유니티에 쓰일 쉐이더를 공부하면서 보는데 아직은 어떻게 적용해야할지.. CG쪽은 어떤식으로 접근해야할지 잘 모르겠네요.
일단은 차근차근 하나하나 따라하면서 접근하고 있습니다 감사합니다!
유니티에서 쓰는 쉐이더는 자체 쉐이더였다고 기억해요. CG도 아니죠. (크로스 플랫폼을 지원하기 위해.. ) 뭐 최종적인 문법은 다 비슷합니다.. 일단 HLSL로 띄시고 나면 다른 쉐이더 언어로 옮기는건 어렵지 않습니다 ^_^
삭제한빛미디어에서 언제 출판 되나요~!!!
답글삭제말씀하신 7월10일이 지나도 도통 홈페이지에서 확인이 안되요
책 제목이 정확히 무엇인가요
목빠지게 기다리고 있다구요~!
궁금합니다....^^;;
최종 교정을 보고 있다는군요.. 그것만 끝나면 며칠안에 인쇄를 한답니다. 죄송합니다.. 한 10~15일만 더 기다려주세요 ^_^
삭제저도 기다리고 있습니다~~~
삭제매일매일 온라인서점에서 검색중...^^
(책제목좀 알려주세요~~)
"셰이더 프로그래밍 입문"이라고 알고 있습니다... (혹시 바뀌진 않겠죠? -_-) 한빛미디어에서 출판됩니다.
삭제포프님 드뎌 나오는군요.. ㅎㅎ
답글삭제5월에 나온다 하시길래,, 5월부터...계속 기달렸습니다..ㅋ
추카드립니다. ^^
예약주문 했으니 담주면 받을수 있겠네요..
너무 궁금하네요..^^
너무 늦어져서 죄송합니다 ^_^/
삭제드디어 나왔군요 지르러 갑니다. 5월부터 기다린 ㅎㅎ
답글삭제지르셨죠? ^_^
삭제이미 질렀다는 ㅋ
삭제축하드립니다 ^^ 바로 주문해야겠네요
답글삭제아 그리고 북미취업가이드 일본 스토어에도 올려주시면 안될까요??
감사합니다..
삭제북미취업가이드를 일본 스토어에 올리는 문제는 연두미디어 사장님께 전해드렸습니다...
좋은 책 감사드립니다^^*
답글삭제그리고 책을 읽다가 궁금한 것이 있습니다
CHAPTER 10 - 그림자 기법을 평정한 그림자매핑 단원에서 난반사광을 구할 때 float형을 쓰더라고요...이전단원까지는 float3를 쓰는데...형을 바꾸면 값이 짤려서 나오지않나요..?
(219페이지입니다)
현재 이삿짐을 싸버려서 책을 볼수 없는관계로..... 대충 생각나는대로 답변을 달아봅니다.
삭제난반사광은 어차피 코사인 함수일 뿐이므로 빛의 위치에 따른 난반사광의 차이는 float이 맞습니다. 거기다가 빛의 색상(RGB)를 곱한 결과를 저장하면 float3가 되는거죠. 즉 float만 쓰면 greyscale이 되는거고 거기다 색상(RGB)를 곱하면 float3가 되는겁니다.
이삿짐 때문에 현재 소스코드를 볼수 없지만 그림자 매핑에서 색을 입힐때는 픽셀쉐이더에서 마지막에 색상을 하나 곱하는게 아닌가 추측만 해봅니다~
아!!
답글삭제감사합니다^^ float만 쓰면 greyscale이 되는군요 ㅎㅎ
답변을 빨리달아주셧는데 늦게봐서 죄송합니다ㅠㅠㅠ
7장 이후는 언제부터 나오나여?
답글삭제아직 모르겠어요.. 생각보다 일이 커져서.. 대학 교재로도 채택되고 있어서... 고민중입니다..
삭제원래 생각으로는 책 판매량이 줄어들면 그때 공개해서 출판사에도 피해를 안주고 책이 절판되는 일이 있더라도 온라인으로 내용을 보존할 생각이었는데.. 이제 대학교재로 채택되서 계속 팔릴거 같고 그러면 출판사에서도 절판을 안시킬 거니까... 괜히 제가 온라인으로 공개해서 출판사에게 피해주고.. 그로 인해 절판까지 가는 일은 없게 하는게 나을거 같아서요. (생각보다 종이책으로 있는걸 좋아하시는분들이 너무 많으시더라구요.)
뭐든간에 고민중입니다. 출판사하고 계약조건상 제가 출간후 한 반년뒤에 온라인 공개는 가능한데.. 그럼으로 인해서 종이책이 사라지는 일까지 이어지는 일이 없었으면 해서요..
지금 현재 생각으로는 당분간 공개 안하는게 낫겠다 싶습니다. 자세한건 책 판매되는거 더 살펴보고 결정하겠습니다.
공개를 하면 책 들고 다닐 필요없이 편하게 온라인으로 볼 수 있어서...
삭제공개를 않하시고 e book 으로 판매를 하시는 것도 괜찮을듯...
셰이더로는 타카시 이마기레 책이 최고 였었는데(그 책도 설명이 쉽다고는 할 수 없지만...) 이제는 포프님책이 최고입니다.
전자책 판권은 한빛미디어에서 가지고 있습니다. 한빛쪽에 전자책 출판 의향이 있는지 한번 물어보겠습니다. (아마 전자책이 나오면 해적판이 쉽게 돌아다니므로 출판사에선 아직 꺼려하지 않나 싶네요..)
삭제제 책이 최고라니 감사합니다 ^^/ (저도 물론 그렇게 되려고 맘먹고 쓴거지만.. 독자님이 나서서 그래주시니 다행이네요 ^_^)
책 정말 잘 보고 있습니다.
답글삭제제게는 정말 주옥같은 내용들이더군요!
그런데 한가지 질문이 있어요..
랜더몽키로는 책에 나오는대로 따라하면 정말 잘 되는데
그걸 가지고 프레임웍을 따라하면 랜더몽키처럼 나오질 않는데
제가 잘못한걸까요....
물론 전부 다 그렇다는건 아니고 파트2의 챕터 5, 7 이 그렇습니다.
나머지는 아직 해 보질 못했네요.
으악..제가 샘플이 있는데도 불구하고
삭제멍청하게 질문을 했군요....
죄송합니다! 샘플과 비교분석을 해봐야 겠네요~
글은 지워주시길 바랍니다.
책 정말 잘 보고 있습니다. 최고예요!
그.. 글은 놔두겠습니다 ^_^/ 그래야 다른 사람들도 보고.."엇 샘플이 있군!" 하고 알아차리죠.. 어차피 익명으로 등록하셨으니 그래도 되죠 ^_^?
삭제Pope님 안녕하세요! 책 내용 중에 잘 안되는 부분이 있어서 질문 올립니다.
답글삭제책 88p 에 보면,
float3 rgb = albedo.rgb;
이 부분을 실제 픽셀 셰이더 함수에 넣고 돌리면 에러가 발생합니다.
float4 ps_main( PS_INPUT Input) : COLOR
{
float4 albedo = tex2D(DiffuseSampler, Input.mTexCoord);
return albedo.rgba;
}
위 main에서 어떻게 수정하여야,
float3 rgb = albedo.rgb;
이 코드가 적용되는지 궁금합니다.
(이리저리 해봐도 안되서 질문 남깁니다. 감사합니다.)
88 페이지에서 float3 rgb = albedo.rgb; 를 코드에 쳐넣으란 이야긴 아니었습니다. 이렇게도 할수 있다 라는걸 말씀드린거죠.
삭제근데 그 코드를 직접 쳐 넣으셔도 코드상에선 에러가 날 이유가 없어보이는데요. 에러메시지하고 에러가 나는 전체 소스코드를 올려주시면 왜 에러가 나는지 살펴보는데 더 도움이 될거 같습니다.
float3 ps_main( PS_INPUT Input) : COLOR
삭제{
float4 albedo = tex2D(DiffuseSampler, Input.mTexCoord);
return albedo.rgb;
}
이렇게 하였습니다.. COLOR type의 return은 반드시 float4 가 되어야 하지 않나요?
rgb의 값만을 리턴하기 위해 형 변환를 해보아도 error가 발생되네요...
(사실 저희가 Pope님의 책을 가지고 스터디를 하고 있습니다.
초보자로서, 이것저것 해보다가 안되서 질문을 드립니다. ^^;; )
네 픽셀셰이더에서는 반드시 float4를 반환해야 합니다. 그리고 float3 -> float4형으로의 변환은 지원하지 않습니다. 마지막 component(alpha또는 w)에 어떤 값을 대입해야하는지 모르기 때문이죠. 대신
삭제return float4(albedo.rgb, 1); 이런식으로 마지막 성분을 직접 지정해주는 방법으로 반환은 가능합니다.
책을 샀는데...프로젝트 돌리면
답글삭제\program files\microsoft directx sdk (august 2007)\include\d3d9.h(37): fatal error C1083: 포함 파일을 열 수 없습니다. 'stdlib.h': No such file or directory
이런 에러가 끝도 없이 생기네요. vs 2005만 쓰다보니 인클루드 관련된 문제인거 같긴 한데 명확하게 이유를 알수 없어요. 심지어는 전부 복붙해서 프로젝트 폴더 내에 붙여도 관련 참조 링크에러가 끝도 없이 뜨구요. 해결방법 알려주시면 감사하겠습니다 ㅠㅠ
그리고 stdlib.h는 directx관련 헤더가 아니라 visual studio와 함께 딸려오는 헤더인데요.. 그걸 못찾는거라면 비주얼 스튜디오 내에서 include path가 제대로 설정이 안된거 같은데요?
삭제Tools -> Options에 가셔서 VC++ Directories에서 stdlib.h 헤더파일있는 폴더 위치가 포함되어 있는지 확인해보세요...
p.s. 이왕이면 VS2010에 DirectX SDK 2010 6월판으로 업데이트 해서 쓰시지요. 어차피 둘다 공짜인데 안하실 이유가..... -_-
구글링으로 찾아낸 문제의 원인은 VS2005와 함께쓰던 DX2007 링크문제였습니다.
삭제이것저것 하루동안 온갖 삽질을 다하다 결국 해결법을 찾아냈습니다.
...
허탈하게도 2010 SP1을 깔면 그냥 바로 해결되어버리더군요.
답변 감사합니다.
드디어 구매 했습니다.
답글삭제온라인으로 제공되던 부분을 여러 번 반복해서 봤습니다. 책 사기전에 잊을까봐서요...
이제 그 다음 장을 아껴가며 보려고 합니다.
잔뜩 기대됩니다.
온라인으로 여러번 보신후에 구매하셨다니 제 기분이 더 좋습니다. 그만큼 도움이 된다고 느끼신거겠죠? ? 정열적으로 플밍하세요~ ^_^
삭제노멀맵핑 167 페이지에서요
답글삭제float3x3 TBN = float3x3(input.T, input.B, input.N ); //normalize()함수 생략
로 TBN 행렬을 만드는데요 이 행렬이 설명되어있기를
월드공간을 접선공간으로 변환하는 행렬이라고 나와있는데요
러면서 아래 tangentNormal(노멀맵에 있는법선)을 월드노멀로 변환할때
float3 worldNormal = mul(TBN,tangentNormal); 로 계산이 된다는 그을 볼 수있습니다
곱하는 순서가 바뀐건데요
제 짧은 생각으론 TBN 이 원래 접선공간에 있는 것을 월드공간으로 변환해주는것이 아닌가
하는 생각이 들어서인데요
노멀맵에 있는 노멀들의 대부분의 방향은 노멀 텍스쳐를 종이처럼 펼쳤을때는 다는 아니지만
파란색을 보이듯이 종이 윗부분으로 올라와있을것인데요
이 상태에서의 노멀맵에 있는 벡터들을 오브젝트에 각각 붙인다고 할때는
오브젝트의 표면 바깥쪽으로 붙게될텐데요
계속해서.. 노멀맵에 있는것들을 결론적으로 오브젝트의 각 정점기준으로 나있는
노멀/바이노멀/접선벡터 공간으로만 옮겨준다면 끝나는게 아닌가 싶어서요
역행렬(전치행렬) TBN을 계산하는것이아닌것으로요
만약 일반적인 직교기저행렬 A 에다가 벡터 X=(1,0,0)을 곱하면
.``````````|1,0,0|
X*A=(1,0,0)*|0,1,0| = (1,0,0)
.``````````|0,0,1|
이 나오지만 만약 TBN 의 3가지 벡터가 A를 Y축으로 90 도 돌아가있는 직교기저 행렬=B 이라
한다면
.``````````|0,0,-1|
X*B={1,0,0}*|0,1, 0| = {0,0,-1}
.``````````|1,0, 0|
이 되어서 B 행렬에 의해 법선맵에 있는 노멀들은 제대로 공간을 찾게 되는것이 아닌가해서요
역행렬을 곱해주는 연산 없이도요...
결론적으로 float3x3 TBN = float3x3(input.T, input.B, input.N ); //normalize()함수 생략
으로 만들어진 행렬이 왜 월드공간을 접선공간으로 변환하는 행렬인지가 궁금합니다~
p.s 의도치않게 조금 길어졌네요, 좋은하루 되세요~
167페이지에서 "이제 접선공간 안에 있는 법선을 월드공간으로 변환할 때 쓸 수 있는 TBN 행렬이 준비되었습니다." 라는 문장을 말씀하시는거죠? 사실 질문을 읽다보니 질문의 의도가 다음 둘중에 어떤건지 확실히 모르겠네요.
삭제1) TBN행렬이 왜 월드공간을 접선공간으로 변환하는건지요?
아니면
2) 왜 굳이 월드공간에서 계산을 하나요.. 접선공간에서 하면 되지 않나요?
그래서 둘다 답을 하겠습니다.
1)
일단 짧게 대답드리면 정헌님이 말씀하신대로 TBN 행렬은 월드공간 -> 접선공간으로 변환하는 행렬입니다.
하지만 제 책을 보시면 이렇게 되어있지요.
float3x3 TBN = float3x3(T,B,N);
TBN = transpose(TBN);
이제 접선공간 안에 있는 법선을 월드공간으로 변환할 때 쓸 수 있는 TBN 행렬이 준비되었습니다.
즉 TBN행렬 자체가 월드 -> 접선공간 변환을 하므로... 그것의 역행렬(전치행렬)을 구해서 곱하면 접선-> 월드가 된단 말이었습니다. 사실 TBN의 역행렬이 TBN의 전치행렬과 같아서 행렬을 만들 때 아래와 같이 만드는 경우도 많거든요
float3x3 = float3x3((float3)(T.x, B.x. N.x),
(float3)(T.y, B.y, N.y),
(float3)(T.z, B.z, N.z));
위의 형태는 책에서 나온 TBN을 전체한 것과 같지요.. 즉 접선->월드변환(사실 TBN은 탄젠트, 종법선, 노말을 모아서 만든 행렬이란 의미이므로 어떻게 표현해도 이게 틀리다곤 할 순 없습니다. 따라서 TBN은 접선 <--> 월드 공간변환을 하는 행렬이다.. 라고 해야 둘다 포함하는 케이스..이게 더 정확하죠..)
어쨌든 책에서 TBN이 이걸 접선->월드고안 변환이라고 할 떈 TBN을 이미 전치한 바로 윗줄의 TBN을 의미한 거였습니다. 혼란을 드렸다면 죄송합니다.
2)
다음챕터를 보시면 제가 왜 굳이 월드공간에서 계산을 했는지 나옵니다 ^_^
혹시 제가 질문을 잘못이해했다면 다시 댓글 남겨주세요~ ^_^/
float3x3 = float3x3((float3)(T.x, B.x. N.x),
삭제(float3)(T.y, B.y, N.y),
(float3)(T.z, B.z, N.z));
이것이 답이된것 같네요
이것때문에 노멀맵 생성이랑 이것저것 보면서 공부가 됐네요~
감사합니다 새해복 많이받으세요~~~~~
안녕하세요~ 다시 와보니 바로 윗글에 글 남긴 사람이네요 ㅎㅎㅎ
답글삭제Appendix A 까지 다 보고 코드로 적용해본다음 후기 올리려 왔답니다
지금으로부터 한.. 7일 전, 처음 이 책을 서점에서 목차를 봤던 기억이 나네요 ㅎㅎ
처음엔 그냥 셰이더 책 또 하나 나왔구나 라고 생각을 하고 지나쳤더랬죠
그런데 저 개인적으로 프로젝트를 진행하던 중이였습니다, 그동안 수학,물리를 공부해서
실질적으로 뭔가 보려고 했지만, 막상 시간이 지나다보니 셰이더를 넣어야겠다는 생각에
봉착하게 됐습니다, 그런데 2,3년 전 셰이더를 본적이 있긴 하지만 다시 시작해볼려고
하니깐 막상 주변엔 셰이더 관련 책이 있긴 하지만 셰이더 책들 분량이 대부분 많아
다시 보기에도 귀차니즘이 승리할 것 같아 그냥 필요한 부분만 보면서 넘어가자라는 식으로 하려고 했으나 원래 성격이 그렇지 못한지라 결국 다른 방법이 없을까 생각을 했죠
생각을 하던중 셰이더 프로그래밍 입문 책의 목차가 머리속에 사~~악 지나가더군요,
그때 드는 생각이 그래! 이거다! 라는 생각이 들어 바로 서점으로 튀어가서
한권 구입했더랬죠 ㅎㅎ
처음엔 챕터8 정도까지만 본 다음 다시 본래 프로젝트로 돌아가려 했지만
8 장을 vs로 코딩하던 중 드는 생각이
"어.. 이 책 뭔가 다르다" 는 생각이 들게 되더군요
처음 해본다면 오랜 시간 투자해야되는 여러가지 DX 설정들과 셰이더와의 상호
상태와 값과 그 의미들이 간단 명료하고 잘 연결 되어있다는 느낌을 받게 되더군요
결국 한챕터 더 보까? 더보까? 더 보까? 하다가 끝까지 보게 됐습니다
인터넷 뒤져가며 두꺼운 셰이더 책 뒤져가며 찾아 설정해야 되는 것들에 대한 시간
절약과 셰이더 소스코드들의 간략하면서도 이해가 잘가는 설명은
처음 앞뒤 뭐 대락 소개나 이런 저런것 빼면 2백 50~60 페이지 정도 되는 분량이
좀 적은거 아닌가? 조금 비싼거 아닌가? 라는 생각을 완전히 뒤바꿔 주더군요
기본적인 탄탄한 노하우가 담겨져 있는 책이라는 느낌이 들었습니다
게임관련 많은책을 보긴했지만 이렇게 직접 사이트에 찾아와 후기를 남기는건 처음이네요
또 질문 하나 하고싶어서 글을 남기기도 한건데요
Q:
대부분 프로그래머는 자신이 익힌 것을 잘 공개하려는 마인드를 갖고 있진 않다고
생각 하곤 합니다, 그런데..
사이트에 보면 이 책의 일부 챕터가 올라와있는것도 볼 수 있고 책 또한 기본적인
내용들을 담았다곤 했다고 하셨지만 노하우가 많이 묻어나온 책이라는걸 느낄 수가
있었습니다, 책을 보면서 이렇게 까지 이 한권의 책으로 도움을 받아도 되나
라는 생각을 하게 되었는데요, 왜 이리 적지 않은 부분을 공개한것인지 궁금하네요 ㅎㅎ
p.s 렌더몽키를 소스코드로 옮기는 과정은 감탄이 나오더군요 ㅎㅎ
스승으로 모셔도 될까요?? ㅎㅎㅎㅎ
일단 이 책이 도움이 되었다니 정말다행입니다. 몇만원하는 책 사셨는데 도움이 안되면 정말 죄송스럽지요 ㅎㅎ..
삭제다른 플머뷴들은 모르겠지만 제가 공개를 꺼려왔던건(한때 그랬죠) 제 지식에 대해 스스로 다신이 없어서였죠. 난 이렇게 알고있는데 그래서 다른 사람들에게 이렇다 말했는데.. 내가 그걸 잘못알고있는거여서 다른 사람에게 누를 끼치지 않을까... 하는 걱정이요... 근데 어느순간 뒤돌아보니 저보다도 허접한 지식을 사람들에게 전파하며 누를 끼치는 사람이 너무 많더라구요. 그래서 '아 , 차라리 내가 떠드는게 낫겠구나' 생각이 들아서 제가 아는건 다 공유하는 정신으로 가고 있습니다.
한 2010년부 그런것 같네요.
다른 사람이 제 지식을 다 가져가서 제 가치가 떨어지는건 걱정하지 않죠. 어차피 이미 알고있는 지식이나 재탕하며 살아나갈 생각은 없구요. 발전이 없는 제 모습이 보이면 언제라도 떠날거니까요.
이 셰이더책을 쓰게된 계기, 그리고 홈피에 다 공개하려고까지 했던 또다른 이유는 이 자료를 썩혀두기 싫어서 였습니다. 학교에서 12학기나 가르쳐봐서 이게 얼마나 좋은 내용인지(특히 초보자들에게) 확신이 있었거든요. 책으로 안나오면 그냥 블로그에 공개한단 생각으로 썼죠. 어차피 몇년지나면 필요없을지도 모르는 내용 너무 늦기전에 사람들에게 보여주려 한게 전부입니다. 실제 한빛하고 계약할때도.. 언제라도 나머지 챕터들을 제 홈피에 공개할수 있는 조건으로 했습니다. 단 한빛에서 그런조건에도 계약을 해주셨기에 최대한 출판사에 피해안가게 절판전에는 공개안할 생각이지만요...
절 스승으로 모시는건 저야 영광입니다.다만 전 정헌님을 제자라기보다는 동료 프그래 정도로 생각할 것 같습니다. 저도 정헌님께 배울점이 많을테니까요.
^_^
"발전이 없는 제 모습이 보이면 언제라도 떠날거니까요."
삭제뭔가 공감도 가면서 팍 꽂히는 문장입니다, 그냥 멋지심돠!!
그럼.. 포프형님으로 모시겠습니다 ㅎㅎㅎ 잘부탁드림돠~
앞으로 자주 들리겠슴다^^
책 잘 보고 있습니다.
답글삭제다름이 아니라 227쪽의 3번 째 줄에 보면 "UV 좌표는 (0, 1)입니다"라는 부분이 있는데 UV 좌표는 (0, 0)이 맞는 것 아닌가요?
또한 아래 공식 중에 UV 좌표를 XY 좌표로에서
y = -v * 2 - 1 이 아니라 y = -v * 2 + 1 이 맞지 않는지 문의 드립니다.
엇.. 그렇네요? 오류입니다..
삭제(0,0)과 +1이 맞습니다.... 정오표에 추가해야겠네요.. .감사합니다 ^_^/
작성자가 댓글을 삭제했습니다.
답글삭제안녕하세요. 잘 보고 있습니다.
삭제7장에서 법선, 종법선, 접선에 대해 행렬을 구성할 때 나오는 설명 중에, 열기준 또는 행기준에 대해 설명이 반대가 아닌가 해서요.
저도 이 부분이 항상 헷깔리는데, 일단 mul에 대해서 msdn에서 찾아보면 아래와 같은 설명이 나옵니다.
------------------ msdn mul ------------------------------
Item Description
x
[in] The x input value. If x is a vector, it treated as a row vector.
y
[in] The y input value. If y is a vector, it treated as a column vector.
------------------------------------------------------------
보면 y 쪽에다가 벡터를 넣으면 열 벡터로 처리한다는건데, 포프님의 책에선 행기준 벡터는 mul(행렬, 벡터), 열기준 벡터는 mul(벡터, 행렬) 이라고 적혀있었습니다.
제가 뭔가 한참 잘못이해하고 있는 것 같은데 한수 가르침 부탁드립니다. :D
오히려 제가 잘못이해하고 있었군요.. 몽상가 님 말씀이 맞으십니다... 제가 사용하던 표기법이 상당히..... 외계스러운 놈이었습니다 -_-;
삭제전 이렇게 정의하고 싶었거든요..
행기준행렬: 행렬의 각 행과 열벡터를 곱한다.. 즉 행렬 x 열벡터
열기준행렬: 행렬의 각 열과 행벡터를 곱한다.. 즉 행벡터 x 행렬
근데 이리저리 자료들을 찾아보니.. 몽상가님이 쓰시는 표기법이 일반적이네요.. 열벡터에 사용하는 행렬이 열기준 변환 행렬... 행벡터에 사용하는 행렬이 행기준 변환행렬.. 이라고 정의하는게 젤 나은거 같습니다..
제 잘못입니다.. 정오표에 올리고 다음판에서는 꼭 고치겠습니다 .
죄송합니다 ..ㅜ.ㅜ
안녕하세요. 좋은책 잘보고 있습니다.. ^^
답글삭제ShadowMapping중 CreateShadow에서
struct VS_OUTPUT
{
float4 mPosition : POSITION0;
float4 mClipPosition : TEXCOORD1; <= 여기
};
struct PS_INPUT
{
float4 mClipPosition : TEXCOORD1; <= 여기
};
TEXCOORD1로 하면 아무것도 안보이고, TEXCOORD0로 하면 하얀색에 물체가 보이는데요.
결과물이 왜 다르게 보이는건지 이해가 가지 않습니다. ㅜ.ㅜ 여기다가 질문을 올려도 되는지모르겠네요.. 감사합니다.
아마.. TEXCOORD0은 기본적으로 텍스처 랩모드가 WRAP으로 되어있꼬 TEXCOORD1은 CLAMP로 되어있어서 일거에요. Wrap과 clamp의 차이는 이러니까요
삭제u좌표가 1.5인경우.
wrap = 0.5가 됨
clamp = 1이 됨
이걸 바꾸는 법은 Texture Object를 더블클릭하면 그안에 D3DSAMP_ADDRESSU하고 D3DSAMP_ADDRESSV가 있습니다. 이게 아무값도 설정이 안되어있다면 필요에 따라 wrap이나 clamp를 하면 되죠..
근데 샤도우맵이나 CLAMP를 하셔야할듯...
안녕하세요? 셰이더 책을 공부하다 궁금한 부분이 있어서 글 남깁니다.
답글삭제167P의 "float3x3 생성자를 이용하면 ~ 이 행렬은 월드공간을 접선공간으로 변환하는 행렬입니다."
위에서 다른 분이 같은 부분을 질문 하셨는데 이해가 되질 않아서 제 생각과 함께 질문을 드리려 합니다.
VS에서 인자로 받는 T,B,N은 VS에서 물체공간행렬을 곱하지 않고 바로 월드 행렬을 곱하기 때문에 이미 탄젠트공간에서 물체공간으로 변환된 벡터라고 저는 가정했습니다.
PS에서 받은 T,B,N은 이미 월드공간으로 변환됐으므로, 그것으로 행렬을 만들면 탄젠트공간 행렬 * 물체공간 행렬 * 월드공간 행렬 이 되어 어떠한 공간상의 벡터를 탄젠트공간->물체공간->월드공간 으로 변환 시키는 합성행렬이 되는것이 아닌가요?
그런데 책에는 그 반대로 월드->탄젠트 로 변환하는 행렬이라고 되어 있습니다. 제 추측하고 반대라서요. 가르침 부탁 드립니다.
음.. 이부분은 언제나 설명을 해도해도.. 이해를 해도해도 헷갈리는 부분이에요..(특히 제가 -_-;;)
삭제이렇게 이야기해보죠... 일단 T B N 벡터는 삼각형에서 구하죠. N이 삼각형의 표면이 향하는 방향이고 B와 T는 그 표면을 따라 흐르는 두 벡터입니다.. .즉 이 세 벡터가 정의하는것은 새로운 공간이지요. 이걸 접선 공간이라 부릅니다. 따라서 이 때 T B N 벡터는 물체공간안에 있습니다. 삼각형을 기준으로 하니 당연하겠죠?
이 때 물체공간안에 있는 어떤 벡터에 이 행렬을 곱하면 물체공간 -> 탄젠트 공간으로 변환됩니다. (아마 이 부분이 윈드토커님이 저와 다르게 이해하고 계신 부분인듯 한데.... 이건 테스트 케이스를 만들어서 실제 곱해보시면 알겁니다.) TBN에 물체행렬 공간을 곱할 이유가 없는건 이미 TBN 벡터 자체가 물체공간안에 정의되어 있어서입니다.
근데 이걸 월드 -> 탄젠트 공간 변환에 사용하려면... T B N 벡터를 월드공간으로 변환해준뒤 행렬을 만들면 되는겁니다. 어차피 법선벡터를 구할때는 평행이동(translation) 값은 중요하지 않으니 그냥 월드행렬에서 회전값만을 가져요 T B N 벡터를 그만큼 회전시킨 뒤 그 결과값으로 행렬을 만들면 그게 월드공간 -> 탄젠트 공간으로 변환하는 행렬이 되는겁니다...
여전히 이해가 안되시면 또 댓글 달아주세요... (제가 잘못알고 있는걸수도 있으니... '_' 스스로 걱정되서 이 자료까지 다시 읽어봤답니다 ㅎㅎ.. http://www.gamasutra.com/view/feature/129939/messing_with_tangent_space.php?print=1 )
감사합니다. 설명 해 주신대로 생각해 보니 이해가 됩니다.
삭제책이 너무 좋습니다. 포프님의 다음 책도 기대하겠습니다.
다행입니다.. ^_^.. 혹시라도 제가 먼가 틀린게 아니면 어쩌나 걱정했는데....
삭제다음 책은 아직 계획에 없습니다.... 흑흑.. -_-
안녕하세요. 셰이더 프로그래밍 입문 책으로 열심히 공부하고 있는 학생입니다.
답글삭제공부하다가 질문이 있어 글을 올립니다.
ShadowMapping 예제를 책을 보면서 DirectX 프레임워크까지 했습니다.
그런데 실행을 해보니 물체는 나오는데 그림자가 생기지 않았습니다. 물체도
전체적으로 어둡게 나왔고요.
세이더 쪽에서 실수했나 싶어 올려 주신 파일로 교체해 본 결과
ApplyShadow 파일을 교체하니 정상적으로 출력이 되더군요.
그래서 ApplyShadow에 오타를 찾아 봤지만 못찾았어요.ㅠ
혹시나 해서 올려주신 파일의 코드를 복사해서 렌더몽키로 제 파일을 실행한후
붙여넣었지만 그래도 안됬습니다.ㅠ
반대로 제가 작성한 코드를 올려주신 파일에 렌더몽키에서 붙여넣었더니
정상적으로 출력이 되었습니다.
그래서 혹시 책에서 설명하신 방법인 렌더몽키에서 CreateShadow와 ApplyShadow를
같은 파일에서 작성하면 안되는 것인가요?
아니면 추가적인 설정을 해주어야 되는지 궁금합니다.
위의 글 작성한 학생입니다. 문제 해결 했습니다.ㅎ
답글삭제렌더몽키에서 Renderable Texture의 이름을 잘못 입력했었네요.ㅎㅎ..ㅠㅠㅠ
렌더몽키에서 정상 출력되어 여기에 문제가 있을 거라고는 생각지 못했었습니다.ㅠ
아무튼 이 책으로 셰이더 프로그래밍에 쉽게 입문할 수 있을 것 같습니다. 감사합니다.ㅎ
참, 질문이 있는데 책에 '실무에서 둘이상의 패스를 사용하는 일은 거의 없다'고 하셨는데,
이유가 궁금합니다.
ShadowMapping 예제를 하나의 셰이더에 복수 패스로 할 수는 없나요?
제가 작성해 보았는데 물체가 보이지 않았습니다.ㅠㅠ
아.. 이미 해결하셨군요.. 제가 이사하느라 회사 옮기느라 바빠서 이제서야 좀 답글 달 정신이 났습니다..(라고 했지만 심시티 할 정신은 있었습니다..죄송합니다 .. 흐흐흑 -_-)
삭제셰이더에서 복수 패스를 사용할 수도 있지만... 팩스나 테크닉이란게 사실은 별다른 의미가 없습니다. 그냥 정리정돈을 돕는 개념일뿐이고. .실제 GPU에 올리는 놈은 정점쉐이더와 픽셀쉐이더 쌍(pair)일 뿐이거든요.
패스가 2개라면.. 그냥 단순히 패스0번을 설정하고 메쉬를 그린다... 아니면 패스1번을 설정하고 메쉬를 그린다의 개념 정도거든요.. 따라서 파일 하나에 여러개 패스를 넣으신다면.. 코드에서 패스를 0~n을 다 훑으며 메쉬를 그리는 부분을 찾아.. 필요한 패스만 선택적으로 그리셔야 합니다. settechnique이나 setpass등의 함수가 분명 있을거에요... 혹시 해보셨는데도 안되시면 다시 연락주세요~
안녕하세요 ~
답글삭제3d를 공부하고 있는 학생 입니다
view port 변환이 어디에서 일어나는지 궁금합니다.
쉬이더 기준으로 볼때 vertex shader -> 뷰포트 변환 -> 라스터라이즈 -> pixel shader 순으로 처리가 되는건지
따로 vertex shader 에선 뷰포트 변환 행렬을 곱하지 않고 pixel shader 에서도 하지 않아 그 중간쯤인거 같은데
좀 더 상세한 정보를 알려주시면 감사하겠습니다 ^^
그럼 ~
(솔직히 말씀드리면 저도 생각을 안해본 거라.... 확실친 않지만..) 말씀 해주신대로 라스터라이저 전에 뷰포트 변환이 되야 맞는듯 합니다.
삭제즉 vertex shader에서 projection transformation까지 해결해주면 그담에 뷰포트변환과 라스터라이즈는 fixed 파이프라인에서 한뒤에... 픽셀쉐이더를 하나씩 호출하는거죠...
위키를 뒤져보니 그게 맞는것 처럼도 나와있네요...
http://en.wikipedia.org/wiki/Graphics_pipeline#Viewport_transformation
우선 답글 고맙습니다. 하나더 질문이 있는데요
삭제화면 해상도(1024*960)에 맞는 color buffer(1024*960) 생성은 projection transformation 인가요? 아님 viewport transformation 인가요?
실제로 카메라로 찍은 3차원 공간을 디바이스 해상도로 맵핑 할 때 위 메트릭스 중 어떤 메트릭스가 영향을 미치는지 알고 싶습니다.
감사합니다 ^^
viewport transformation에 가까운듯요... Projection 공간에서는 픽셀의 개념이 아예 없거든요..
삭제뭐 사실 viewport 크기도 0~1사이로 정의하지만.... 거기에 현재 설정된 렌더타겟의 width와 height를 곱한뒤 각 픽셀마다 픽셀쉐이더를 불러주는거니까요...
안녕하세요, 궁금한게 있어 글 남김니다.
답글삭제책보고 나름 생각해서 diffuse map, normal map , specular map , shadow map까지 모두 같이 적용해서 나름 만족하고 있었는데 ㅎㅎ,,
shadow map 에서 라이트 위치 ( 500,500,-500,1)를 조금 큰 값(예를들면 y를 1000)으로 변경 시키면 왜 그림자가 이상하게 질까요.
원인이 무엇인지 힌트좀 부탁드립니다.
그림자가 어떻게 이상해지는지 딱히 말씀을 안해주셨지만.. -_- 힌트를 드리자면.. 이미 책에서도 밝혀뒀듯이.. 세팅을 많이 타서가 전부입니다...
삭제조명에 사용하는 투영행렬을 잘 조절하면 그런걸 그나마 해결할수 있습니다. 특히 near/far 평면과 fov(또는 너비/높이)가 가장 큰 영향을 미치겠죠...
아무래도 세팅을 이것저것 다이렉트 프레임워크에서 수정해봐야겠네요. 물체마다 비슷한 길이의 그림자를 갖게 하려면 높은 곳에 조명이 있어야 할거 같은데 실제 게임에서는 어느정도 높이에 위치하게 하나요?
삭제게임따라 다른데.. 사실 해의 위치는 어디있어도 크게 상관은 없어요.. Project Matrix만 제대로 만들어주면요.. 두가지 팁을 드리자면..
삭제1) Orthogonal(직교) 행렬을 사용해보세요. Perspective(원근투시)보다 컨트롤이 더 쉬워요.
2) 해가 어디에있는지와 상관없이... 근접평면(near plane)을 shadow caster(그림자를 드리우는 놈)바로 앞에 배치.. 즉...
해가 2000미터 높이에 있는데... 평면이 10미터에.. 그리고 그림자를 드리우는 놈이 50미터 높이에 있다면 near plane을 1500미터 정도로.. far plane을 2050 미터 정도로 해서 투영행렬을 만들어보세요. (LightProjMatrix를 말하는겁니다.)
안녕하세요.
답글삭제텍스처 관련해서 질문이 있습니다. 구글링 하다 원하는 대답을 찾지 못해 여기다 질문 합니다. ^^;;
하나의 모델링에 텍스쳐를 입힐 때 저해상도 또는 고해상도(ex. 128*128 vs 512 * 512)를 맵핑 할때
어느쪽이 랜더 퍼포먼스에 더 빠른 결과를 가져오는지 알고 싶습니다.
메모리 사용에 대한 부분을 제외 한 순수 랜더링 할 때의 처리 속도에 해상도가 영향을 주나용?
제 생각엔 별 영향을 안줄거 같은데;;
답변 주시면 고맙습니다.
감사합니다 ~
영향을 줍니다. GPU하드웨어에 보면 텍스쳐 룩업을 책임지는 텍스처 유닛이란게 있는데 이게 캐시 메모리를 가지고 있습니다. 따라서 텍스처가 작으면 작을수록 캐시 메모리에서 곧바로 읽어올수 있으므로 당연히 더 빠릅니다. 512x512도 캐시에 다 들어간다면 성능의 차이는 크게 없겠지만 보통 텍스처 유닛의 캐시유닛은 매우 크기가 작지요..
삭제캐시에 안들어가면 gpu 메모리에서 이걸 읽어와야하므로 느린겁니다. ^_^
법선 맵핑 관련 질문이 있습니다.
답글삭제픽셀셰이더에서 TBN 행렬을 만든 후에 전치를 하고
mul(TBN, tangentNormal)을 하도록 설명 되어 있습니다.
그런데 이때 TBN행렬을 전치하지 않고 mul(tangentNormal, TBN)을
해도 같은 결과가 나올 거라고 생각합니다.
그렇다면 불필요한 연산을 하지 않아도 되는데,
혹시 제가 놓치고 있는 부분이 있다면 가르쳐 주시기 바랍니다.
놓치시는거 없습니다. 그렇게 하셔도 결과는 같아요.. 책에서는 이론을 설명할때 역행렬 설명하고 그랬으므로 그거와 일치시키려고 일부로 전치한것 뿐입니다. ^_^
삭제설명을 위해서 일부로 한 것이라는
삭제포프님의 의도를 놓쳤었군요.
답변 달아주셔서 감사합니다.ㅎ
안녕하세요.
답글삭제저는 3D artist 입니다.
텍스쳐 & 라이팅을 하고 있는데,
3D 프로그램과 여러 렌더러로 final image 는 만들어 내지만
뭔가 코어는 모르고 겉 핥기만 하는것 같아서 쉐이딩 공부를 하는 중입니다.
책이 저같은 코딩 초보들이 보기에도 아주 자세하고 하나하나 알려주셔서 공부하기 딱 좋아요.
잘 보고 있습니다. 감사합니다.
근데 질문이 2가지 있습니다.
1)
실제 VFX 회사나, 게임회사에서 렌더 몽키를 쓰는건 아니잖아요?
그럼 HLSL 을 실제 회사에서는 어떻게 적용하는 건지요.
visual studio 를 쓰는 건가요?
지금 C++ 과 direct X 도 같이 공부하고는 있는데 아직 잘은 모릅니다.
실무에서는 어떻게 쓰이는지 확실히 개념이 안잡히네요.
visual studio 에서 바로 HLSL 을 작성하지는 않나요?
지금은 아티스트지만 이렇게 공부해서 최종적으로는 shading writer 가 되고 싶거든요.
어떻게 실무에서 쓰이게 방향을 잘 잡고 공부해야 하는지 궁금합니다.
2)
그리고 이 책에는 displacement map 을 적용하는 법은 안나오는데요,
이 책 이후에 더 advanced 하게 공부하려면 어떤 방법이 있을까요?
책 말미에 알려주신 논문들은 아직 제가 보기엔 수준이 높아서요.
감사합니다.
1)
삭제VFX회사는 보통 자체 셰이딩 언어와 툴을 쓸 겁니다. 게임쪽에서는 HLSL이나 GLSL류로 셰이더를 작성하는데 어떤 툴로 작성하는지는 전혀 중요하지 않습니다. 저 개인적으로는 그냥 메모장에서 셰이더를 작성하니까요. -_-;; 렌더몽키를 사용해서 모든 테스트를 한 뒤 거기서 나온 HLSL을 좀 추려서 게임에 사용하는 사람들도 많이 봤습니다. 그외에 노드기반 셰이더 에디터도 존재하구요.
일단 셰이더 언어를 짜두면 그걸 게임을 실행할때 읽어와서 사용하는게 전부입니다. Visual Studio를 이용해서 작성한다면 그냥 Visual Studio를 텍스트 에디터로 사용하는 수준이 아닐까 하네요..
2)
Displacement Map은 GPU Gems시리즈 중 하나에 나왔던 걸로 기억합니다. 솔직히 말씀드리면 제가 소개드린 책/논문 보다 쉽게 나온 자료를 본적이 없고 GPU Gems 쪽이 그나마 좀 오래되서 난이도가 낮다고 생각합니다.
답변 감사드립니다.
답글삭제프로그램에 대해서 잘 모르는 초짜다 보니,
실제로 어떻게 쓰이는지 궁금했습니다.
렌더 몽키를 쓰기도 하고, 메모장으로 만들기도 하는군요. 신기하네요.
아직 초보이고, 혼자 공부하다 보니까,
포프김 님 책처럼 하나하나 알려주고 따라하게끔 해주는 책이 저는 공부하기 좋더라구요.
감사히 잘 보면서 공부하고 있습니다.
혹시 쉐이더 관련 2편 을 내실 생각은 없으신지요 :
책이 너무 좋아서요 : )
책을 좋게 봐주셔서 감사합니다~ 2편을 쓸 생각은 아직 없습니다. 1편만한 책이 안나올거 같아어요.. 나중에 뭔가 확신있게 쓸수있는 내용이 있으면 쓰겠지만.. 아마 안그럴거 같군요.. 1편의 내용은 대학에서 3년을 강연한거라 "이건 좋은 책이 된다!"라고 자신감을 가지고 확실히 쓴거였어요 ㅎㅎ
삭제안녕하세요. 책을 읽고 있는 독자입니다 ^^
답글삭제챕터 7 장을 읽고 있는데요 이해 안되는 부분이 있어서요.
버텍스 쉐이더에서 Input.mNormal, Input.mTangent, Input.mBinormal 을 gWorldMatrix 를 곱하여
위 TBN 값(로컬 벡터)을 월드 좌표로 변환해 주는 부분에서
(float3*3)gWorldMatrix 로 강제 캐스팅해서 TBN 을 월드 좌표로 변환 해주는데요
float3*3 으로 변환 한다는 건 월드 변환 메트릭스 (TRS) 중 Translate (이동) 은 빼고
회전과 확대만으로도 월드 좌표 변환이 가능하다는 것 같아서 혼돈이 옵니다.
왜 TBN 은 Input.mPosition 같이 곱하지 않나요?...
알려주시면 정말 감사하겠습니다 ^^
vector는 방향을 나타내는 데이터입니다. 위치의 개념 자체가 없지요. 일례로 오른쪽을 손가락으로 가리키신 뒤 방에서 이리저리 걸어다녀보세요.. 회전을 하지 않는한 가리키는 방향은 절대 변하지 않습니다.
삭제그게 바로 벡터를 표현할때 (x,y,z,0)을 쓰는 이유입니다. 이걸 곱하면 행렬에서 위치는 어차피 0으로 곱해버리므로 위치가 절대 반영되지 않습니다. 그와 반대로 위치를 표현할때는 (x,y,z,1)을 씁니다.
대답이 되었으리라 믿습니다 ^_^ 열심히 공부하시고 책도 널리널리 광고해주세요~
작성자가 댓글을 삭제했습니다.
답글삭제안녕하세요 ^^ , 질문이 있어 글을 올립니다~
삭제책에 보면 TBN 값을 베텍스 쉐이더의 입풋 값 시멘틱 지정하여 읽고 있습니다
그런데 이걸 3d max 같은 모델링 툴을 이용하여 읽어 온다고 할 때 그래픽 하시는 분들이 버텍스에 TBN 값을
지정할 수 있나요?
궁금하여 검색 하던 중 아래와 같은 글이 있어 생각해보니
http://forums.cgsociety.org/showthread.php?t=407814
노멀 값은 기본 기능으로 설정할 수 있으며 나머지 (tangent, binormal) 값은 멕스 스크립트로 플러그인화 해 데이터를 설정할 수 있는거 같습니다. 보면 실제 업무에서 이런식으로 TBN 값을 설정하는지 아니면 다른 방법이 있는지 궁금합니다.
감사합니다. 새해 복 많이 받으세요 ^^
네 보통 그래픽 하시는분들이 모델링 툴에서 TBN다 저장해서(정점정보로) 보내주십니다. 보통 플러그인을 쓰구요.. 손으로 한땀한땀 해주시는 분들은 못봤습니다.. 주로 exporter에서 해주는거 같아요. fbx exporter만 보시더라도 거기에 tangent space를 구워주는게 있었던듯~
삭제즐거운 연말~
TBN 메트릭스가 이해해 보려 문서를 찾던 중
답글삭제http://www.blacksmith-studios.dk/projects/downloads/tangent_matrix_derivation.php
위 글을 읽었습니다.
이 글을 보면 TBN 메트릭스는 탄젠트 스페이스를 월드 좌표로 변환 해주는 행렬로 이것을 통하여
TBN 의 역행렬을 구함으로서 라이트 디렉션 같은 월드 좌표 방향 벡터를 탄젠트 스페이스로 변환 하여
픽셀 쉐이더 단에서 계산 하는거 같은데용..
또 제가 이해한 부분이 맞다면 처음 정한 TBN 값의 물체가 회전을 할 경우 TBN 값을 다시 계산해야 하며
(물체의 좌표가 변하여) 재계산에 다른 계산량이 얼마다 다라고 설명하고 있는 거 같습니당...
여기서 혼돈이 일어나는 부분은
책에서 시멘텍을 통하여 읽어 들이는 TBN 값은 물체 공간 -> 월드 공간 변환
즉 TBN 의 역형렬(탄젠트 -> 월드) 값으로 시멘택을 통하여 읽어 온다고 생각하는게 맞는지 궁금합니다.
위 링크의 TBN 은 탄젠트 영역을 월드 좌표로 책의 TBN 은 월드 좌표를 탄젠트 영역으로 변환 한다고 하여
혼돈이 옴니당..
또 드는 생각은 바로 위 질문의 멕스 플러그인도 그러한 (TBN 의 역행렬 ) 로 정점 정보를 저장해서 보내주는지
아니면 아예 제가 위 링크를 이해한 "TBN 은 탄젠트 영역을 월드 영역으로 변환 해주는 행렬이다" 란 것 자체가
잘못 이해한건지 그렇다면 무엇 착각하고 있는지 알려주시면 정말 감사합니다.
새해 복 많이 받으세요 ~ ^^
저 링크를 읽기 귀찮으니 생략하고.. 일단 머가 헷갈리시는지는 알거 같으니 설명을 씁니다.
삭제1) TBN은 World -> Tangent인가 Tangent->World인가?
둘답니다.. TBN행렬을 만드는 법은 두가지입니다..
Tx Ty Tz
Bx By Bz
Nx Ny Nz
또는
Tx Bx Nx
Ty By Ny
Tz Bz Nz
위 두 행렬은 사실 둘다 역행렬 관계죠.. 따라서 TBN을 어떻게 만들어주냐에 따라 월드->탄젠트 또는 탄젠트->월드가 됩니다.
고로 어떻게 말하던 맞는건데.. 전 제 설명이 오히려 이해하기 쉽다고 생각합니다. 표면상에 존재하는 좌표벡터들은 현재 월드(또는 물체) 좌표계에 있는거니까요.
2) 맥스플러그인에서 하는짓
맥스 플러그인에서 하는짓은 각 삼각형을 살펴본뒤 그 삼각형에서 직각으로 바깥쪽을 향하는 벡터를 N 그리고 표면을 따라 흐르는 두 직각인 좌표를 B와 T로 저장하는것 뿐입니다. 고로... 그 좌표를 TBN이라고 볼수도 TBN의 역이라 볼수도 있지만 (1번에서 이미 설명)... 그냥 제 방식대로 이해하시는게 좀더 편하리라 생각합니다 -_-a..
3) 물체가 회전할 경우
TBN좌표는 원래 물체에 종속되어 있으므로.. 버텍스 쉐이더에서 받아왔을때는 물체공간에 있습니다. 하지만 물체가 회전을 할수도 있으므로 그 회전 값을 받아들이기위해 TBN에 월드행렬을 곱하는겁니다. 일단 이 곱을 하고 나면 TBN벡터들이 월드공간에 있죠... 이걸로 TBN행렬을 만들면 그게 월드--> 탄젠트 변환이 되는겁니다... 그거의 역을 구하면 탄젠트--> 월드가 되는거구요.. 하지만 1)에서 말씀드렸다싶이 TBN을 만드는 방법에는 2가지가 있으므로.... TBN이 탄젠트->월드라고 설명하는 책이나 웹페이지도 있습니다. (역시 전 제 방법이 맞다고 우깁니다 ㅋㅋㅋㅋ)
포프님!
답글삭제초면에 실례지만
MSAA-깊이버퍼재사용 부분에 관해서 여쭤볼게 있습니다.
(디테일한 책 또한 아주 잘 보고 있습니다. 디테일 포프!)
msaa를 적용하기 위해서
d3d device를 D3DMULTISAMPLE_4_SAMPLES 옵션을 주어 생성하였습니다.
그리고 메인이 되는 scene을 백버퍼에 렌더링 하여서 msaa가 적용되게 하였습니다.
그리고 이후에 포스트이펙트를 적용하기 위해서
백버퍼의 내용을 텍스쳐에 복사한 후에
이 텍스쳐를 렌더타겟으로하여 포스트이펙트 처리를 합니다.
그런데 아웃라인을 딴다든가 하는 포스트이펙트에서
메인scene을 그릴 때 갱신된 z버퍼가 필요한데
포스트이펙트를 위해서 생성된 텍스쳐와 기본z버퍼의 샘플링type이 틀려서 문제가 되고 있습니다.
일단 해결은,
z버퍼가 필요한 포스트이펙트는 렌더타겟을 백버퍼-기본z버퍼로 설정한후 렌더링된
백버퍼의 내용을 다시금 텍스쳐에 복사해서 사용하는 방법으로 해결은 하였습니다만,...
가장 되었으면 하는 해결책은
샘플링type(D3DMULTISAMPLE_4_SAMPLES)이 적용된 기본z버퍼를
샘플링type이 없는 z버퍼에 복사하는 것인데, 구글링, d3d help를 뒤져보니
Additional Restrictions for Depth and Stencil Surfaces
The source and destination surfaces must be plain depth stencil surfaces (not textures) (see IDirect3DDevice9::CreateDepthStencilSurface).
Neither of the surfaces can be discardable.
The entire surface must be copied (that is: sub-rectangle copies are not allowed).
Format conversion, stretching, and shrinking are not supported.
StretchRect cannot be called inside of a BeginScene/EndScene pair.
위와 같이 뎁쓰와 스텐실 서피스에 대해서는
포맷 변환이 불가능 하다고 하네요....
현재 생각으로는
msaa가 적용된 백버퍼를 사용할 경우(전제)
1.z버퍼 값이 필요없는 포스트이펙트
2.z버퍼의 값이 필요한 포스트이펙트의 경우
두가지를 분리하여서, 2에 해당하는 케이스는 렌더타겟으로 백버퍼-디폴트z버퍼를 셋팅하여서 렌더를
하는 방법등으로 해결 해야 하는 걸까요?
조언 부탁드립니다.
예전 하드웨어에선 안되었었지만 요즘 왠만한 그래픽 카드에선 depth buffer를 셰이더의 input 텍스처로 사용가능합니다. 고로 다음과 같은 짓을 하면 되죠
삭제1) dof할때 msaa적용된 depth 텍스처를 셰이더로 불러와서 그냥 셰이더 lookup을 한다.
또는
2) dof 하기전에 msaa적용된 depthbuffer를 불러와서 msaa적용 안된 depthbuffer를 만들어낸다.... (한마디로 fullscreen pass 한번 더 돌려주기)
안녕하세요 ~!
답글삭제책에서 환경 매핑 부분 잘 읽었습니다.
책의 내용 외 환경 매핑 관련 dx9 예제를 살펴 보았습니다.
실시간으로 환경맵을 그려주고 백버퍼로 실장면을 그릴때 환경맵을 가져와 색을 섞는 부분을 확인하였습니다.
그런데 이 방법과 screen space reflection 과는 어떤 차이가 있는지 궁금합니다.
screen space reflection 의 경우 깊이 버퍼의 내용을 사용하는거 같던데 dx9 예제는
환경 매핑을 할때 깊이 값은 전혀 사용하지 않아 둘간의 차이점이 있어 보이지만
무엇이 다른지 알려주시면 정말 감사하겠습니다. ^^;;
같은거에요. 근데 screen space reflection이 깊이 맵을 sampling하는 이유는 post-process 단계에서 (즉 화면공간에서) 리플렉션을 먹이는 기법이라.. 그때는 정점의 위치를 알수 없거든요. 고로 깊이 버퍼를 샘플링해서 거기서 각 픽셀의 위치를 계산한뒤 리플렉션을 하는것 뿐입니다.
삭제전혀 다르지 않아요...
답변 정말 감사드립니다.
답글삭제ssr 은 큐브맵을 사용 안하나요?
답글삭제안한다면 장면을 랜더링 한 이미지 (2D) 로 장면의 특정 부분에 reflection 을 먹인다고 볼 수 있을거 같은데요.
그 방법이 아무리 생각해도 모르겠습니다.
예를 들어 장면 바닥에 물이 절반정도 엎질러 있고 벽면에 그림들이 있다고 한다면
무슨 기준으로 장면 이미지로 부터 벽면의 특정 부분(잘라서?)을 바닥에 엎질러진 물에 투영을 시킬 수 있나요?
반대로 큐브맵을 쓴다고 한다면 바닥 물 모양의 메쉬를 랜더링 할때 물모양의 메쉬 버텍스에 시야벡터+노멀 값을
전달하여 픽셀 쉐이더가 반사 벡터를 구하여 투영할 색깔을 큐브맵으로부터 얻어와 색을 입혀 과정 자체가 심플하다고
생각합니다.
이래저래 책도 찾아보고 웹도 검색해 보았지만 전혀 ssr 에 대한 계산 방법이 감이 안와 염치 불구 질문 올립니다.
또한 ssr 이 디버드 랜더링 할 때 이득이 있다고 하는데 ssr 계산 흐름을 안다면 자연히 이해 될거 같습니다.
감사합니다. !
큐브맵 사용할수도 안할수도 있습니다.
삭제ssr과 일반 환경매핑의 다른점은 어디서 노말과 픽셀 위치를 구하는거밖에 없어요.
- 일반환경매핑: 버텍스 위치 -> 보간 -> 픽셀 위치, 노말맵(탄젠트) -> TBN변환 -> 노말(월드)
- ssr: 깊이맵(화면공간) + xy위치(화면공간) -> 픽셀 위치, scene normal(화면공간, gbuffer) -> InvWorldViewMatrix -> 노말(월드)
예전엔 언리얼 데모중에 Image Based Reflection인가 그게 있었는데 그게 아마 이런 비슷한거 하는걸꺼에요 단 2D 이미지 한장으로. 그 2D이미지는 레벨 에디터에서 미리 캡춰한다 합니다.
안녕하세요!
답글삭제이제 공부를시작하려고 준비중입니다만,
amd에서 이제 더이상 렌더몽키를 다운받을수 없게 되었더군요..
어찌해야될가요?
AMD 웹사이트 가보니 아직 다운 받을 수 있는데요? 아마 못찾으신거 같아요. 링크는 여기..
삭제http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/rendermonkey-toolsuite/
사용하는 그래픽 솔루션에서 HLSL셰이더를 제공해서, 잘 모르는 초보지만 열심히 책 봤습니다. 한 번 봐서는 이해가 잘 안될 것 같네요. 여러 번 읽고 코드도 직접 작성해봐야겠어요.ㅎㅎ 혹시, 포프님 책 이후에 HLSL을 더 공부하기 위해서는 어떤 책이나 자료를 보는 게 좋을까요? appendix에 나와있는 GPU젬스 시리즈 링크는 안들어가지네요 ㅡㅡ;; 영문이라면 해외자료나 도서도 무관합니다. 고견부탁드려요 감사합니다ㅎ
답글삭제GPU Pro란 책이 매년 나오고 있죠..(부록에 써놨던거 같은데 -_-a)
삭제GLSL로 할 수 있는것 중에 HLSL로 못하는건 없습니다
답글삭제안녕하세요...
답글삭제탄젠트공간 행렬에 대해 질문 드립니다.
벡터가 원래 행렬과 곱해지면 좌표계 공간이 바뀌지 않습니까?
이걸 더 확장해보면
탄젠트공간 행렬의 기저벡터를
1. 로컬로 두고 행렬을 구성할수도 있고, --- A
2. 월드로 두고 행렬을 구성할수도 있고, --- B
3. 뷰공간으로 두고 행렬을 구성할수도 있을거 같습니다 -- C
A, B, C 같은식으로 생각해서
탄젠트공간 행렬를 계산 하는게 맞는건가요?
네 맞죠. 기저벡터는 실제 메쉬에서 오는거니까..
삭제1. 메쉬에서 온 정점정보(노말,탄젠트,바이노말)을 전혀 변환하지 않고 탄젠트행렬을 만들면 그건 tangent -> local로 변환하는 행렬...
2. 정점정보를 월드로 변환한뒤 만들면 tangent -> world 공간으로 변환하는 행렬
3. 뷰공간까지 변환한뒤 만들면 tangent -> view공간 변환 행렬입니다.
오잉 책샀는데 여기 와보니 책에서 나온 내용이 다 나와있네요-ㅅ-;; 돈도 없어서 큰 맘먹고 샀는데. 으악...~~
답글삭제전부라뇨. 절반밖에 안나와있습니다.
삭제안녕하세요. 책 보다가 궁금한 게 있어서 질문 드립니다. 2장의 정점셰이더/정점셰이더의 입력데이터 부분을 보면 float4에 대해서 4개의 성분을 가지는 벡터라고 되어 있는데요, x, y, z는 정점의 위치라는 걸 알겠는데 나머지 w는 무슨 성분인지 잘 모르겠습니다. -_-; 그냥 비워두는 건가요?
답글삭제책에 쓴다고 했었는데 안써놨던가요? (각주일지도 몰라요. 제가 까먹고 안넣었을수도 있고 ㅎㅎ)
삭제사실 수학적인 이유가 뭐던간에 이렇게 이해하시면 편합니다. xyz로 나타낼수 있는 놈에는 두가지가 있습니다
1) 방향벡터
2) 위치벡터
이때 이 벡터들을 회전한다고 생각해보죠. 방향과 위치 모두 회전을 해야 합니다.
그럼 이 벡터들을 평행이동 시킨다면요? 위치는 이동을 하지만 방향은 어디로 이동하던간에 변하지 않죠. 따라서 방향벡터는 변하지 않아야 합니다.
그런데 행렬을 곱할 때는 공식하나로 하고 싶거든요? 그러면 마지막 성분 w를 0으로 하냐 1로 하나야 따라 변환행렬에 있는 평행이동 값을 적용시킬수도 아닐수도 있지요.
자 그럼 방향벡터와 위치벡터중에 어떤 놈의 w가 0이 되어야 하는지 아시겠죠? (실제 공식써가면서 몇번 곱해보시면 아실겁니다.)
책으로 사서 블로그로 공부하네요 ㅎㅎ. 초보자도 물흐르듯 진도가 나갈수 있어서 너무 좋네요~
답글삭제안녕하세요 포프님 책과 블로그로 공부하고 있는 초보 쉐이더 개발자입니다. :) 다름이 아니고 이번에 차량의 와이퍼 효과를 구현해야하는데요. 와이퍼로 차량 전면 유리의 빗물, 이물질들을 와이퍼로 제거하는 효과를 어떤 식으로 구현해야할까요? 가이드 라인을 제시해주시면 열심히 헤딩해보겠습니다.
답글삭제빗물 이물질들이 와이퍼에 쓸려가는것만이 아니라 그냥 사라지는걸 구현하는 거라면...
삭제와이퍼의 이동궤적에 따라 텍스처 채널 하나에 0~255까지 그라데이션으로 칠한뒤.. 타이머를 통해서 c --> hlsl로 0~254까지의 값을 전달하면서 이 보다 작은 픽셀값을 가진 픽셀을 지워줄거 같군요(알파블렌딩)
255의 값을 가진 부분은 절대 안지워진다거나 하면 되고요....
앗 답글 감사드립니다. 혼자 헤딩해보다가 스텐실을 이용해서 어찌어찌 구현했네요. 말씀하신 방법으로도 한번 다시 구현해봐야겠습니다. :)
삭제안녕하세요.포프님. 최근에 포프님책으로 쉐이더입문한 프로그래머입니다. 꽤 오래된 글에 댓글을 다는 것이 좀 그렇기는 합니다만 공부중 정오표로 수정한 부분에 의문이 있어 이렇게 댓글을 답니다.
답글삭제'열기준변환행렬'과 '행기준변환행렬'에 대한 부분인데 제 소견으론 기존에 포프님이 생각하셨던 것이 더 맞다고 봅니다.(위에 '몽상가'님께서 의문을 가지신 부분입니다.)
'행기준행렬'('행기준변환행렬'이 아닙니다.)이 'row major matrix'이고 '열기준행렬'이 'column major matrix'를 표현한 것이라면 3X3행렬을 기준으로 행기준행렬과 열기준행렬의 원소 순서는 아래와 같을 것입니다.
1) 행기준행렬
| Ax Ay Az |
| Bx By Bz |
| Cx Cy Cz |
2) 열기준행렬
| Ax Bx Cx |
| Ay By Cy |
| Az Bz Cz |
보통 행렬과 벡터 혹은 벡터와 행렬의 곱연산에서
1) 행기준행렬은
결과(Column Vector Result ) = 행기준행렬(row major Matrix) * 열벡터(Column Vector)
2) 열기준행렬은
결과(Row Vector Result ) = 행벡터(Row Vector ) * 열기준행렬(Column Major Matrix)
일단, 위의 '몽상가'님께서 보신 mul에 관한 MSDN의 코멘트는 mul(x, y)의 x의 인자를 벡터로 할 시에 그 벡터는 행벡터(row vector)로 처리하고 y의 인자를 벡터로 할 시에 열벡터(column vector)로 처리한다는 내용입니다.
즉, mul(행렬, 벡터)는 행기준행렬과 열벡터의 곱연산이며 mul(벡터, 행렬)은 행벡터와 열기준행렬의 곱연산이라고 할 수 있습니다.
행/열-기준벡터라는 말과 행/열-기준변환행렬이라는 말의 유래는 모르겠으나 검색해본바 국내의 몇몇 개인블로그에서 행/열-벡터를 행/열-기준벡터, 행/열-기준행렬을 열/행-기준변환행렬이라고 지칭하는데서 온 듯합니다.
하지만 선형대수학(linear algebra)에서 공식적으로 쓰이는 용어가 Row Vector는 행벡터, Column Vector는 열벡터, Row Major Matrix는 행기준행렬, Column Major Matrix는 열기준행렬이기도 하거니와 단순히 언어적으로 따져봐도 변화의 대상이 되는 벡터가 전혀 열에서 행으로, 행에서 열로 변화 하지 않음에도 기준변환행렬이라는 말을 쓰는 것에는 혼동의 요지가 있어 보입니다(공부하면서 했갈렸습니다 ㅠㅠ).
물론 벡터의 계( coordinate system)가 변화기는 하지만 이 경우에는 Transfer Matrix(변환행렬)이라는 용어가 따로 있고 이때의 의미는 월드행렬, 뷰행렬 등을 지칭한다는 보는 것이 더 맞지않나 싶습니다.
따라서 요는 기존에 포프님께서 정의하신바대로
1) 행기준행렬이면 행렬의 각 행과 열벡터를 곱한다.( 행렬 x 열벡터)
2) 열기준행렬이면 행렬의 각 열과 행벡터를 곱한다.( 행벡터 x 행렬)
로 하셨던 것이 더 맞지 않는가 하는 것입니다.
오래된 글에 다는 짧은 소견입니다만 한번 살펴봐주시고 제가 혼동하는 것이 있다면 말씀해주십시오.
ps. 쉐이더를 전혀 모르고 있었는데 포프님책으로 도움 많이 받고 있습니다. 앞으로도 좋은책 많이 집필해 주세요 ^^
솔직히 말하면 둘다 틀립니다. (저도 이 책 쓰고나서야 알았어요... )
삭제그래서 아예 행기준 행렬/열기준 행렬이란 표현을 포기하고 핼기준 변환행렬(행벡터를 변환함) 열기준 변환행렬(열벡터 변환함)이라고 정의한겁니다.
일단 열기준/행기준 행렬은 곱셈순서와는 전혀 상관이 없는 개념입니다. 메모리에 각 요소들이 어떻게 배치되어있느냐를 결정할 뿐이죠. 어쩌다보니 opengl이 행렬*벡터 곱순서를 따르면서 행렬을 열기준으로 메모리에 저장하고 dx는 벡터*행렬의 순서로 곱하면서 행렬을 행기준으로 저장하다 보니... 거기서 생긴 혼동일 뿐이더군요.
따라서 행기준 벡터, 열기준 벡터라는 말은 이 책에서 나올 이유조차 없는 놈이구요.(메모리에 어떻게 저장되는지를 다루지 않는한...) 그래서 차라리 행기준변환행렬 열기준변환행렬이라는 표현을 쓴건데.. 그 역시 혼돈의 여지는 있는건 사실 같습니다.
차라리 다 빼고 문장으로 풀어서 설명하고 싶어요 -_-;
추가로 앞의 댓글에서 빠진 질문 하나만 더 드려요.(한번에 썻어야 하는데 죄송합니다 ㅠㅠ)
답글삭제앞 질문이 용어적인 부분에서 온 혼동에 대한 것이라면 이 질문은 계산 결과에 대한 것 인데요.
일단 'TBN행렬'과 'xyz벡터'의 연산 결과는 어차피 mul(행렬 ,벡터)든지 mul(벡터, 전치행렬')든지 같을 것입니다.
그럼 최종결과는 둘 중 어느 것인가요?
1)
Rx = (Tx * x) + (Bx * x) + ( Nx * x)
Ry = (Ty * y) + (By * y) + ( Ny * y)
Rz = (Tz * z) + (Bz * z) + ( Nz * z)
2)
Rx = (Tx * x) + (Ty * y) + ( Tz * z)
Ry = (Bx * x) + (By * y) + ( Bz * z)
Rz = (Nx * x) + (Ny * y) + ( Nz * z)
Rx = (Tx * x) + (Bx * y) + ( Nx * z)
삭제Ry = (Ty * x) + (By * y) + ( Ny * z)
Rz = (Tz * x) + (Bz * y) + ( Nz * z)
이죠.
계산 결과를 알고나니 행기준/열기준 표현을 쓰셨던게 이해가 갔네요. 보다 쉬운 전달을 위한 고육지책이셨군요ㅋ. 머리에 업데이트 된 김에 다시 한번 처음부터 정독하겠습니다. 감사합니다.^_^
삭제셰이더 입문 책을 구입해서 샘플 파일을 좀 받으려는데요, 적어주신 한빛 미디어 사이트는 입력하면 이상한 성인 사이트로 접속이 되서 저자 블로그로 와서 받으려는데, 이곳의 링크로 클릭하면 알수 없는 일본사이트로 연결되어 샘플 파일을 어디서 받아야 하는지 잘 모르겠습니다. 확인 부탁 드려요
답글삭제한빛미디어 사이트를 검색해서 들어가니 예제소스 링크가 아래와 같이 되어 있네요.
삭제www.hanbit.co.kr/exam/1949/ <-- 이곳이 예제파일 주소가 맞네요.
책에서는..
www.hand.co.kr/exam/1949 라고 나와 있습니다... 중요한 예제파일 주소에 오타가 있네요.
이거 몇페이지죠? 29쪽에 있는 링크에는 hanb.co.kr이라고 제대로 들어가 있는데.. 혹시 다른 페이지에 이게 또 나오면서 잘못 들어간게 있다면 정오표에 올리겠습니다.
삭제그리고 제 홈페이지에서 링크를 걸어놓은 사이트는 github입니다. (언어는 설정따라 어느 언어도 나올거라 생각) 거기에 보면 소스코드를 따로 받던가 아니면 한번에 zip파일로 받을수도 있습니다.
놀랍게도 책을 사고 이 글을 발견 하였다.
답글삭제프로그래머 2년차에 접어드는 개발자입니다.
답글삭제회사에서 유니티로만 작업하고 거의 2d게임만 만들다 보니
어느새 여기에 안주한거 같더군요 그러나최근 포프님이 만든 영상 올린거 보고
많은 깨닳음(?)을 얻어 언리얼을 공부하고 있습니다. 그리고 포프님의 동영상을 보다보니
클라이언트 프로그래머라면 셰이더는 필수 인거 같아 포프님이 지은 셰이더 입문 프로그래밍을
오늘 펼쳐보게 되었습니다. 일단 시작이지만 벌써부터 매우 느낌이 좋은거 같습니다. ^^ 그릭고 책을 펼친지 몇시간 되지 않았지만 지은이의 말이 자꾸 떠올라 DirextX를 제대로 공부해보고 싶어졌는데 Direx11으로 시작 할까 합니다 이유는 어제 포프님과 영천님이 DirectX12에 관해 이야기 하시는중 영천님이 Direx11으로 시작을 하면 좋다고 하여 DirexX11 으로 공부를 시작 해볼까하는데 어떻게 시작하는게 좋을까요?? 예제를 다운받아 소스를 분석하는게 좋을까요 아니면 책을보고 차근차근 나가는게 좋을까요? 그리고 책으로 시작하는게 좋다면 국내도서중..(영어에 약해서..)추천해주실만한 책을 혹시 있으신가요?
글이 쓰다보니 약간 두서 없고 길어졌네요 그래도 답변 부탁드려요
dx11에도 그런지 모르겠지만 dx9의 공식 문서에는 tutorial이 있었지요... 그거 따라하면서 첨 배우고... 그 담에는 책 한권 보시는건 나쁘지 않습니다. 아직도 그런지 모르겠지만 예전엔 용책이 좋았습니다 -_-
삭제(그냥 dx11책이 많이 나오지 않았을테니 온라이 서점 들어가신 뒤..가장 서평높은 책을 보시면 되지 않을까 싶습니다..)
제가 한글책을 안본지 워낙 오래되서... 자세한 대답을 드리지 못하는 점 죄송합니다.
아니요 답변 감사합니다 ^^
삭제멘토라 생각하고 열심히 따라가겠습니다
안녕하세요 dx9으로 공부를 하고있는 학생입니다.
답글삭제한가지 질문을 할려고합니다.
제가 디퍼드라이팅에 이해도가 떨어지는거같아 질문을 할려고합니다.
디퍼드라이팅에서 한 라이트가 특정 오브젝트에만 빛을 받게 하고싶습니다.
제가 생각한 방법이 G버퍼에서 노말을 렌더링 할때
이 알파값을 안써서 이 알파에다가 해당 오브젝트가 영향받을 라이트 인덱스를 넣어서
라이트렌더할때 인덱스 확인해서 해당인덱스에다가만 출력하는 방식을 생각하고 구현을 했습니다.
제 주위에서는 왜 그렇게했냐는 비판만있고 좋은 제안을 말을 안하는대 포프님이 보시기에 제방법이 많이 안좋은 방법인가요??
픽셀마다 인덱스 비교를하지만 제가 생각한 최선의 방법이 이방법입니다 ㅠㅜ 혹시 더 좋은 방법이있으면 길이라도 알려주시면 알아보고 공부하겠습니다.
그렇게 하는 법도 한 방법이고.. 아니면
삭제그렇게 특별하게 처리해야할 물체만 forward rendering으로 그린다거나... alpha대신에 stencil buffer이용하는게 더 빠를거 같네요.
앗 답변을 달아주셨군용 ㅠㅜ
삭제감사합니다. ㅎㅎ 알려주신대로 전부다 알아보면서 해보겠습니다.
안녕하세요. 포프님 책으로 공부하고 있는 학생입니다.
답글삭제저도 노말매핑 부분에 TBN matrix를 만드는 과정에서 헷갈리는게 있어서 질문드립니다.
댓글에 저와 같은 고민을 찾다가 비슷한경우를 봐서 포프님의 답변을 보았는데요
아래는 포프님의 답변 내용입니다.
-
음.. 이부분은 언제나 설명을 해도해도.. 이해를 해도해도 헷갈리는 부분이에요..(특히 제가 -_-;;)
이렇게 이야기해보죠... 일단 T B N 벡터는 삼각형에서 구하죠. N이 삼각형의 표면이 향하는 방향이고 B와 T는 그 표면을 따라 흐르는 두 벡터입니다.. .즉 이 세 벡터가 정의하는것은 새로운 공간이지요. 이걸 접선 공간이라 부릅니다. 따라서 이 때 T B N 벡터는 물체공간안에 있습니다. 삼각형을 기준으로 하니 당연하겠죠?
이 때 물체공간안에 있는 어떤 벡터에 이 행렬을 곱하면 물체공간 -> 탄젠트 공간으로 변환됩니다. (아마 이 부분이 윈드토커님이 저와 다르게 이해하고 계신 부분인듯 한데.... 이건 테스트 케이스를 만들어서 실제 곱해보시면 알겁니다.) TBN에 물체행렬 공간을 곱할 이유가 없는건 이미 TBN 벡터 자체가 물체공간안에 정의되어 있어서입니다.
-
위 답변에서 헷갈리는것들 질문좀 드리겠습니다ㅠㅠ
1.여기서 세번째 문단(?)에 물체공간 안에 있는 어떤 벡터에 "이 행렬"을 곱하면 이라고 하신부분의 행렬은 TBNMatrix = float3x3 (T, B, N) 를 말씀하시는건가요?
2.만약 맞다면 어째서 물체공간에서 접선공간으로 변환이 되는건가요?
탄젠트 바이노말 노말은 물체공간에 있던 벡터들인데 이 세벡터의 값으로 만들어진 회전행렬을 노말벡터값에 적용시키면 그게 접선공간 -> 물체공간 변환이지 않나요? 반대로 역행렬을 곱하면 물체 -> 접선공간이 아닌가요??
지금 이게 너무 헷갈려서 공부가 손에 잡히질 않습니다...ㅠ
윗분들은 답변을 보고 다 이해하시는데 저는 너무 헷갈립니다... 어느 부분이 틀린것인지 제가 잘못이해하는 부분을 알고싶습니다ㅠ 바쁘실텐데 죄송합니다..
1. 네.
삭제2. 테스트 케이스를 직적 만들어서 곱해보시길 바랍니다. 때로는 실험을 통해서 구체적인 사례들이 맞는지 틀린지를 확인하는게 이해에 더 빠를 데가 있습니다.
안녕하세요. 혹시 DX9 버전 이후에 추가된 지오메트리 쉐이더나 hull 쉐이더 같은 내용을 추가해서 2판을 발매하실 계획은 없으신가요?
답글삭제아직 계획은 없습니다. (고민은 많이 해봤는데 생각보다 수요가 없을거 같아서....)
삭제포프님 안녕하세요? 유튜브 구독자이자 팬중에 한사람입니다.
답글삭제최근에 셰이더프로그래밍에 관심이 생겨 포프님 책을사서 공부를 시작하려는데요.
렌더몽키 받는 부분에서 해당 주소로 가니까 다운로드 받을수 있는 곳을 못찾겠더군요..
(링크 - http://developer.amd.com/rendermonkey-toolsuite/rendermonkey-toolsuite-ide-features/)
이제 다운받을 수 없는건지 아니면 제가 못찾는거면 받을수 있는 곳 링크좀 부탁드립니다.
여기에 올려놓았습니다.
삭제https://1drv.ms/u/s!ArnTIqazDXx0gxku_vXEfsFvTi1C
감사합니다!
삭제책을 사놓고 한동안 등한시하다 이제 보았는데 렌더몽키 찾는데 한참해매다 겨우 찾았는데 여기 있었군요! 그래도... 원링크 남겨둡니다 ㅠㅠ
삭제http://gpuopen.com/archive/gamescgi/rendermonkey-toolsuite/
안녕하세요 포프님.
답글삭제TA 를 꿈꾸는 현직 3D 모델러입니다. 얼마전부터 집필하신 "셰이더 프로그래밍 입문 " 을 보면서 하나씩 따라해보고 있는데요. 궁금한 점이 하나 생겨서 이곳에 질문합니다. 책의 중반까지 보고 있는데 lightDir 를 계산하실 때에 정점좌표에서 라이트좌표를 빼서 방향벡터를 구하여 단위벡터로 만들어준 후에 dot 계산을 할때 또다시 -lightDir 을 해서 방향을 뒤집어주시는데요. (초반에 이것이 벡터의 밑둥을 서로 만나게 해주기 위함이다 라고 적혀있습니다)
그럼 아예 처음부터 lightDir 을 구할때 라이트좌표에서 정점좌표를 빼면 뒤집혀진 방향벡터를 구할 수 있지않을까.. 하는 생각이 들어서요. 제가 잘못생각한걸까요?
답변 부탁드립니다. 읽어주셔서 감사합니다