2014-10-07 8 views
3

일부 스프라이트 기반 게임을하고 있습니다. Z-주문 스프라이트를 들어 대안이
1) 올바른 순서로 그려 기본적으로 - 일괄 처리에 대한 골칫거리가 될 수
2) 직교 투영과 깊이 테스트를 사용 - 반투명과 번잡 할 수 있습니다 내가 2를 선호하고

) 그러나 I 3D 애니메이션을 쉽게 구현할 수 있도록 투시 투영을하고 싶습니다. 카드를 3d 등으로 뒤집어 쓴다. 그렇게하면 객체가 카메라와 다른 거리에 있기 때문에 z 버퍼의 차이로 인해 스프라이트의 크기가 조정될 수있다.
투영을 취소하기 위해 거리에 따라 스프라이트 크기를 조정하는 방법에 대해 생각했습니다. 그러나 그때 나는 "평평하지 않은"2 차원 장면 위에 3D 애니메이션 객체에 간섭을 줄 것입니다.

정식 2D 장면으로 이동하고 두 번째 단계에서 드문 3D 애니메이션을 "복제 된"개체와 함께 사용하는 것이 정상적인 방법이라고 생각합니다. 그러나 누군가 다른 생각을 가지고 있을까요?

투시 투영 및 왜곡없는 z 버퍼를 사용하는 OpenGL 스프라이트 장면. 가능한?



mikkokoos 해결책을 주도 대답합니다. 추가 깊이 값을 통해 버텍스 쉐이더는 클립 공간에서 모든 버텍스의 z 좌표를 조정하여 다른 깊이 레이어로 푸시 할 수 있습니다. 실제 3D 좌표는 z = 0에 머무를 수 있습니다. 클립 공간을 변경하면 원근감 문제가 없어 지므로 원근 투영을 장면에서 사용할 수 있습니다.
스프라이트 평면에 수직이 아닌 다른 카메라 각도를 허용하려면 스프라이트 정점을 고정 레이어로 푸는 대신 "layerOffset * layerIdx"로 조정해야합니다. 따라서 모든 레이어에 대해 정점은 카메라에 한 걸음 더 밀착됩니다.

참고 : 고정 레이어를 사용하면 xy 평면이 반드시 중앙에 있지 않으므로 올바른 클립 공간 좌표를 찾는 것이 매우 까다로운 일입니다.

열린 질문 : 클립 공간의 해상도? 클립 공간에서 가장 작은 차이점은 무엇입니까? 푸시 된 sprite와 실제 3D 요소간에 가능한 간섭이 있습니까? 평면 스프라이트가 3d 객체를 초과하여 굴지 않도록하려면 스프라이트가 아닌 모든 평면 객체는 사용 된 최대 레이어 오프셋으로 푸시되어야합니다. 카메라 앞의 사용 가능한 공간에서 레이어 오프셋을 계산하는 것이 좋습니다.

달성 : 전망 투영 된 3D 장면에서 2 차원 평면에 스프라이트가 구성됩니다. 스프라이트는 셰이더에서 계산 된 조각 깊이를 기준으로 차단됩니다. 그리기는 여전히 텍스처 배치로 수행 할 수 있습니다.

주 2 : 아직 일괄 처리 된 두 번의 실행을 고려합니다. 첫 번째 것은 조정 된 깊이를 가진 2 차원 스프라이트이고, 두 번째는 스프라이트 또는 스프라이트 평면에 "부착"되지 않은 객체입니다. 깊이 버퍼 inbetween를 지우고 보이지 않는 스프라이트면을 클리핑에 추가합니다.
사진을 (무대 뒤에있는 물체가 허용되지 않은 경우) :
http://www.imagebam.com/image/109f6e356918267
http://www.imagebam.com/image/a2085f356918275

+1

투영 후 깊이를 직접 쓸 수 있습니다. https://www.opengl.org/sdk/docs/man/html/gl_FragDepth.xhtml 명확히하기 : 동일한 깊이에 투시 투영을 사용하여 개체를 렌더링하십시오. 그 후에 gl_FragDepth를 사용하여 객체를 올바른 순서로 배치하십시오. – dari

+0

젠장, 내 실수 야. 나는 OpenGL ES 2.0에 대해 언급 했어야했다. Afaik에는 gl_FragDepth가 지원되지 않습니다. 죄송합니다! 더 일찍 말해야 했어. 어쨌든 고마워! –

+0

'glPolygonOffset'을 사용하여 투시 투영을 사용하십시오. https://www.opengl.org/sdk/docs/man/html/glPolygonOffset.xhtml – dari

답변

2

도움이되기를 바랍니다, 미친 아이디어 버텍스 쉐이더는 :

gl_Position.z=(u_zOffset-1.0)*gl_Position.w; 

이 메시를 "결합", 그래서 당신의 메시가 더 복잡하고 사용 된 DepthFunc에 따라 경우, 대신 범위가 할 수 있습니다. u_zRange가 2F/(number_of_layers)이다

gl_Position.z=((1.0+(gl_Position.z/gl_Position.w))*u_zRange+u_zOffset-1.0)*gl_Position.w; 

및 u_zOffset는 u_zRange * layer_id이다 : (가시 범위는 -1에서 1까지이다). 레이어 0이 가장 가깝습니다.

EDIT : 요약 : 카메라에서 동일한 거리에있는 모든 것을 MVP 행렬에 넣은 다음 정점 셰이더에서 Z 값을 수정하여 화면에서 정렬합니다.

+0

좋아, 이것은 당황스럽게 간단한 해결책처럼 보입니다. 그러나 나는 완전히 이해하는지 잘 모르겠습니다. 프래그먼트 쉐이더의 같은 투영 평면에서 모든 평면을 특정 범위 내에서 눌러야한다고 제안하는 것이 아닙니다. gl_Position에 대한 호출이 결과 파편의 깊이 값에 영향을 미치지 않아 z- 순서가 깨지지 않습니까? –

+0

그 지점에서 클립 공간에 있습니다 ([this] (http://www.songho.ca/opengl/gl_transform.html) 참조) 화면에 평평하게 보이지 않습니다 (정상/조명 등 계산은 영향을받지 않았다). 이것이하는 일은 OpenGL에서 원하는 것을 얻기 위해 z 버퍼에 영향을 미칩니다. 그래서 우리는 그것을 깨뜨리지 않고 "고쳐"있습니다. – mikkokoo

+0

당신은 물론 맞습니다. 그렇다면 어떻게 3D 변환을 처리 할 수 ​​있을까요? 스프라이트 패치에 3dTransform을 적용하여 2D 평면을 따라 스틱을 만들면 이에 따라 z 좌표를 "오프셋"해야합니까? 어떻게 클립 공간의 모든 변경 사항이 정렬되지 않은 스프라이트의 렌더링을 방해하지 않는지 확인합니까? –

1

난 당신이 개발하는 게임의 종류를 알고, 그리고 어떻게 당신의 시스템에 적합하지만, 당신이있을 다음에 무엇을 사용 가능성을 고려 투영?

일반적으로 표시해야하는 객체가 3D로 애니메이션을 적용해야하는 객체와 같지 않은 경우 첫 번째 객체에는 오 토 그래피 투영을 사용하고 두 번째 객체에는 투시 투영을 사용하지 않는 이유는 무엇입니까?

실제로 겹치기는해도 일종의 트릭을 펼칠 수 있습니다 (일반 선형 전환이 아니라면 ...).) 오르토 그래픽 투영법은 적절한 매개 변수를 사용하여 애니메이트하기 직전의 원근법으로 대체됩니다 (그러나이 경우 마일리지는 다를 수 있으며 수학을하지 않았다고 고백합니다 ...).

은 아마 그럼에도 불구하고 나는이 당신은 모든 스프라이트를 렌더링하는 원근 투영을 사용하고 마지막에 gl_Position.z를 대체 할 각 균일 한 플로트 "깊이"를 가질 수

+1

예, 그게 내가 계획 한 것입니다. (내가 mikkokoos 대답을 읽을 때까지) 개체가 동일합니다. 그래서 내가 클론을 언급했다. 예 : 2D 카드 게임이지만, 카드를 뽑거나 뒤집을 때 3D 애니메이션이 필요합니다. 또는 타일 격자를 배경으로하고 모든 타일을 뒤집어 쓰거나 입자처럼 폭발 시키길 원합니다. –

+0

내가 생각했던 거의 동일한 사용 시나리오 (예 : Magick the Gathering 또는 나 같은 향수의 경우 Rick Dangerous 2 http : //www.mobygames.com/game/rick-dangerous-2 :)). 그의 (아주 좋은) 대답에 대한 mikkokoos 명성, 비록 killjoy가되기 위해서, 원근감 사용과 반올림 오류로 인해 원하지 않는 스케일링이 발생하는지 궁금합니다. . [죄송합니다. Nexus5 MALI에서 음영 처리 작업을하고 있지만 최근 비관적 인 상황에 처하게되어서는 안됩니다. : /] – Rick77