안녕하세요 깃갤 성님들.
오목 게임과 같이 격자와 원을 사용해야하는 상황에서
어떻게 opengl에서 렌더링해야하나 고민해봤습니다.
* 틀린 내용이 있다면 가감없이 지적해주시면 감사하겠습니다.
* 본글은 카메라가 xz평면을 바라보도록 세팅하고 작성되었습니다.
* 윈도우 라이브러리로는 glfw를 사용하였습니다.
1. 원 렌더링
아래의 링크를 참고하였습니다.
https://blog.lapingames.com/draw-circle-glsl-shader/
첨부된 링크에서는 2가지 방식을 소개합니다.
a) 정다각형의 변수를 늘려서 원인것처럼 보이게 하기 (쉐이더 없이 메인어플리케이션에서 처리)
b) 쉐이더를 끼고서 fs에서 처리 (smoothstep을 이용)
문제는 도저히 b방식을 이해하는데 실패하여
잠시미뤄두고 a를 택하기로 했습니다.
num (정다각형 변의수) 만큼
vector를 reserve해두고 pushback하는 식으로 구현했습니다.
opengl이 구조체뿐만 아니라 vector도 문제없이
glBufferData에 주소값을 넘길 수 있게 해주더라구요...!
2. 격자 렌더링
왼쪽-위부터 시작해서
가로로 한줄씩 내려가는 식으로 for문을 돌려 데이터를 넣었습니다.
격자의 특성상 겹치는 vertex가 많으므로 indexed drawing을 하였습니다.
glDrawElements 호출시 primitive타입을 GL_LINES로 주기 때문에,
연속되는 가로 2줄을 잡아가면서 (row1, row2)
하나의 격자사각형을 시계반대방향으로 라인렌더링 하는 식으로 그렸습니다.
3. screen -> world 좌표변환
목표는 현재 마우스커서의 viewport좌표를
격자가 놓여있는 xz평면 상의 world좌표로 변환하는 것입니다.
따라서 마우스좌표를 얻어와야합니다.
glfw에서는 다양한 콜백을 셋업할 수 있도록 해줍니다.
그중하나인 `glfwSetCursorPosCallback`은
마우스 커서의 포지션(xposIn, yposIn) 을 가져올 수 있도록 해줍니다.
world -> view -> clip -> ndc -> viewport의 변환과정을 통해
마우스 좌표를 얻어온 것이므로 그 역순으로 따라가며
변환을 해주면 됩니다.
a) screen mouse 좌표를 ndc로 변환
upper-left를 (0,0)으로 하고 bottom-right을 (1,1)로 하는 좌표계에서
중심을 (0,0)으로 하고 width, height모두 구간 [-1, 1] 에 대응되는
ndc (normalized device coordinate) 를 위와같은 선형변환으로 얻어옵니다.
b) projection * view 의 역행렬 연산
wolrd에서 clip으로 넘기기 위해 view, projection을 곱했으니 ndc에 역행렬을 곱해주면 됩니다.
glm에서 제공하는 glm::inverse를 이용했습니다.
위 연산으로 얻은 worldMousePos를 model 행렬에 던져주기만 하면 됩니다.
긴글 읽어주셔서 감사합니다.
오늘도 화이팅하세용~!
난 격자를 shader로 했는데
좀만 더 자세히 설명해주실수있을까용...? *-* fragment shader에서 따로 line에 대한 처리를 하는 테크닉이 있는건가요?
https://github.com/martin-pr/possumwood/wiki/Infinite-ground-plane-using-GLSL-shaders
http://asliceofrendering.com/scene%20helper/2020/01/05/InfiniteGrid/
https://madebyevan.com/shaders/grid/
헐. 감사합니다 ㅠㅠ
https://madebyevan.com/
이분 블로그가
esbuild하고 waterjs 만드신 분이었네요 ㄷㄷ;