카드 게임에서 카드에 그림자 효과를 그리는 데 어떤 렌더링 기법을 사용해야합니까?


13

이와 같은 그림자를 만드는 데 어떤 유형의 음영 알고리즘이 사용될 수 있습니까? 여기에 이미지 설명을 입력하십시오

내가 만들고있는 것은 비슷하지만 모두 OpenGL에 의해 구동되는 2D 드로잉 API로 수행되므로 Z 좌표가 없습니다.

또한 손 자체의 경우 여기에 표시된 것과 같은 음영 느낌을 얻고 싶습니다. 여기에 이미지 설명을 입력하십시오

나는 그에 가까운 그늘을 만드는 방법을 잘 모르겠습니다.

카드의 수는 바뀌어야하고 카드는 테이블에 던져져 어떤 종류의 라이트 맵도 사용할 수 없습니다.

어떤 종류의 알고리즘을 조사해야합니까 (알아야 할 블러와는 별도로)

감사

최신 정보

2D 카드 게임을 만들고 있습니다. 카드에서 그림자 효과 오프셋을 추가하고 싶습니다.

여기에 이미지 설명을 입력하십시오

내가 생각하는 방식은 다음과 같습니다.

  • 백 버퍼와 같은 크기의 텍스처를 유지하십시오.
  • 그 텍스처에 임시 카드로 어두운 사각형을 그립니다.

  • 그 질감을 흐리게합니다.

  • 그 질감에 내 카드를 그립니다.
  • 카드에 추가 조명을하십시오.
  • 이 텍스처를 백 버퍼에 그립니다.

내 질문은 :

  • 이것이 올바른 방법입니까?

  • 텍스처로 렌더링하지 않고 (
    백 버퍼보다 ​​큰 비트 맵 을 유지) 할 수있는 방법이 있습니까?

  • 최대 텍스처 크기가
    백 버퍼 크기를 초과 하지 않는다고 가정하는 것이 안전 합니까? (
    백 버퍼 가 2000x3000이면
    그 크기의 비디오 메모리에 텍스처를 만들 수 있다고 말하는 것이 안전 합니까?

감사


1
두 번째 문제에 대한 미학적 요점 : 실제로 카드를 손에 들고 있다면 불가능합니다 . 서로 옆에 눌려진 카드는 서로 눈에 띄게 그림자가되지 않습니다. 당신이 그들을 많이 잡고 있지 않는 한 아닙니다 . 그 이미지에 묘사 된 방식대로 카드를 실제로 붙잡을 수는 없습니다. 이 카드들은 몇 밀리미터로 분리 된 것처럼 보입니다. 그들은 서로 평평하지 않습니다. 난 그냥 걱정하지 않을 것입니다.
Nicol Bolas

답변:


18

모두가이 문제에 대해 너무 복잡한 해결책을 제시하고 있다고 생각합니다

여기에 이미지 설명을 입력하십시오

먼저, 여기에 (a)로 묘사 된 카드 (또는 원하는 그림)가 있습니다. 다음으로 복사본을 가져와 검은 색으로 채우고 가우시안 블러를 실행합니다 (b). 이 모든 것은 포토샵이나 좋아하는 미술 도구에서 발생합니다.

다음으로 게임 내에서 카드를 그리려면 먼저 곱하기 (또는 알파) 블렌드로 흐릿한 검은 색 이미지를 그린 다음 약간의 방향으로 오프셋 한 다음 그 위에 카드를 그립니다. 보일라

더 많은 속임수를 위해 그림자와 카드 렌더를 번갈아 가며 (d)와 같은 효과를 얻거나 먼저 (e)와 같이 모든 그림자를 그린 다음 카드를 그립니다. 여전히 분리되어 있습니다 =)

그림자가 더 미묘하고 투명한 그림자를 만들기 위해 순수한 검정색 (또는 전체 알파)을 사용하지 않는 것이 가장 좋습니다.


2
게임 밖에서 그림자를 내기 +1 한 단계 더 나아가 장면에 빛이있는 경우 그림자가 배치되는 위치를 수정할 수도 있습니다.
FrenchyNZ

+1, 멋진 일러스트. 또한 E의 경우 테이블에 짙은 그림자를 렌더링하고 스텐실이있는 카드의 반 밝기를 사용할 수 있습니다. 더 복잡해 지지만 효과는 더
나아질

2

첫 번째는 너무 어렵지 않습니다. 손에 든 카드에 알파 채널을 렌더링하면 (카드가있는 픽셀의 경우 검정색, 투명의 경우 흰색과 같이 단순 할 수 있음) 알파 채널에서만 원하는 흐림 효과를 수행 할 수 있습니다. 그런 다음 오프셋하여 테이블의 조명을 제어합니다. (아마 Z- 버퍼가없는 경우 먼저 알파 채널을 화면 밖으로 어둡게 렌더링 한 다음 마스크로 표를 수행해야합니다. 렌더링 한 다음 한 다음 실제 카드 렌더링해야합니다.)

두 번째는 SSAO (screen-space ambient occlusion)와 비슷합니다. 이 기술에는 Z 좌표가 필요합니다. 그러나 카드간에 다양한 각도가 없다면 (Z 버퍼가 없으면 추측 할 것입니다) 각각에 대해 그림자를 렌더링하여 꽤 좋은 근사치를 할 수 있습니다 카드. 그러나 모든 비행기는 그 위에있는 모든 비행기에 대해 흐린 알파 채널이 필요하며 테이블에 많은 카드가 있으면 렌더링 패스가 상당히 많을 수 있습니다.


SSAO는 과잉입니다 =) 애니메이션 예제를 보지 않고 어떤 섀도 잉 기법을 사용하는지 말하기는 매우 어렵습니다. 카드가 항상 순서대로 떨어져 서로 간격을 두는 경우 그림자를 미리 렌더링하는 것이 가장 쉽지만 게임이 실제로 작동하는 것을 알 수는 없습니다.
Patrick Hughes

0

그림자 맵을 만들 수 없습니까? 장면을 fbo로 렌더링합니다. 깊이 값만 저장하고 그림자를 렌더링해야하는지 여부를 확인하기 위해 셰이더에서 일반 깊이 값 검사를 수행하십시오.


Z 버퍼를 사용하지 않고 '깊이'가 없습니다.
jmasterx

0

다음 프로세스에는 오프 스크린 렌더 타겟이 필요하지 않습니다. 그러나 그렇게하면 먼저 테이블을 작성해야한다는 요구 사항이 생깁니다 . 또는 적어도 테이블이 그려지기 전에 테이블이 덮을 픽셀에 아무것도 그려지지 않습니다. 또한 테이블 자체는 겹치지 않는 하나의 단일 이미지 여야합니다.

또한 프레임 버퍼에는 알파 구성 요소가 필요합니다.

  1. 카드의 그레이 스케일 이미지를 얻습니다. 가장자리 주변을 흐릿하게하여 크기를 확장 할 수 있습니다. 이것은 당신의 그림자 카드 이미지입니다. 이것은 단일 채널 이미지입니다. 셰이더에서이 텍스처에 액세스 할 때 알파 구성 요소에 단일 값을 입력해야합니다. 이것은 셰이더 또는 다른 곳에서 수행 할 수 있습니다.

    이미지에서 0.0 값은 그림자가 없음을 의미합니다. 이미지에서 1.0 값은 총 그림자를 의미 합니다. 즉, 완전히 검은 색을냅니다. 가장 어두운 색으로 0.5 정도의 값을 원할 것입니다.

  2. 알파가 0 으로 설정되도록 화면을 지우십시오 .

  3. 각 카드에 대해 무언가 (또는 적어도 테이블 아래에 렌더링 될 것)를 렌더링 하기 전에 카드의 실제 위치에서 오프셋 된 퍼지 텍스처를 렌더링하십시오 (동일한 방향으로). 셰이더의 색상 출력은 다음과 같아야합니다 (이에 대한 혼합 구성은 OpenGL 용어로).

    glBlendEquation(GL_MAX);

    이 블렌드 모드는 겹치는 그림자가 더 어둡거나 밝아지지 않도록 유지하는 데 사용됩니다. 해당 픽셀에 기록 된 가장 어두운 값만 가져옵니다. 충분히 좋아 보일 것입니다.

    컬러 쓰기 마스크를 사용하여 컬러 쓰기를 해제해야합니다.

  4. 테이블을 렌더링하십시오. 그렇게 할 때 다음과 같이 블렌딩을 설정해야합니다.

    glBlendEquation(GL_ADD);
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);

제한이 너무 제한적인 경우 렌더링 대상을 사용해야합니다. 이것은 다음과 같이 수행됩니다.

  1. 이전과 같이 섀도 카드 이미지를 만듭니다.

  2. 먼저 그림자를 렌더링하십시오. 섀도 프레임 버퍼를 바인딩합니다 (하드웨어가 그중 하나에 렌더링 할 수있는 경우 단일 채널 이미지 만 필요). 값을 0으로 지우십시오.

  3. 각 카드에 대해 그림자 카드 이미지를 렌더링하고 이전과 같이 오프셋합니다. 셰이더는 출력 색상의 네 가지 구성 요소 모두에 동일한 값을 써야합니다. 블렌드 모드는 다시이어야합니다 glBlendEquation(GL_MAX).

  4. 일반 프레임 버퍼로 다시 전환하십시오. 그림자가되고 싶은 모든 것을 그립니다.

  5. 이제 렌더링 한 그림자 이미지로 전체 화면 쿼드를 그립니다. 셰이더는 그림자 이미지에서 가져온 텍셀을 출력의 알파에 저장해야합니다. RGB는 관련이 없습니다. 블렌드 모드는 다음과 같아야합니다.

    glBlendEquation(GL_ADD);
    glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

첫 번째 방법에서는 5 단계 : 블렌딩 비활성화 및 카드 렌더링을 잊어 버린 것 같습니다. 또한 첫 번째 방법으로는 OP의 두 번째 스크린 샷에서 볼 수 있듯이 카드 간 그림자를 얻을 수 없습니다.
Nathan Reed

@NathanReed : 나는 스스로 물건을 끄는 방법을 알고 있다고 생각했습니다. 또한 질문 아래의 의견에서 지적했듯이 "카드 간 그림자"는 의미가 없습니다.
Nicol Bolas

1
실제로 실제로 카드를 보관하는 방법을 나타내지는 않지만 멋지게 보입니다! 카드가 첫 번째 샷에서와 같이 테이블 위에 떠 다니는 것은 실제로 "이해가되지 않습니다"
Nathan Reed

0

스텐실 버퍼를 사용하겠습니다. 그것을 1로 지우고 (바람직하게는 깊이를 지우는 동시에) 테이블을 그립니다. 그런 다음 스텐실 테스트를 활성화하고 모호한 사각형 텍스처를 사용하여 그림자를 그립니다. . (나는 이것을 완전히 테스트하지는 않았지만 비슷하고 잘 작동하는 코드에서 파생되었습니다 . 매개 변수를 조정해야 할 수도 있습니다 ). 그런 다음 다른 모든 것을 그립니다.

전화는 다음과 같습니다.

glEnable (GL_STENCIL_TEST);
glStencilFunc (GL_EQUAL, 1, 2);
glStencilOp (GL_KEEP, GL_KEEP, GL_INCR);

// draw shadow textures

glDisable (GL_STENCIL_TEST);

이로 인해 문제가 발생할 수있는 유일한 시간은 약간 겹치는 흐린 가장자리가 두 개있는 경우입니다. 그렇지 않으면 기본 OpenGL 1.1이 제공하는 것 이상의 모든 것을 필요로하지 않으며 모든 하드웨어에서 작동합니다 (아마도 오래된 3DFX 카드를 기대할 것입니다.

성능이 중요하지 않은 게임에서 잘 작동하는 두 번째 대안은 glCopyTexSubImage2D입니다. 그것은 백 버퍼보다 ​​작은 텍스처에서도 작동하며 모든 하드웨어에서도 잘 지원됩니다 (OpenGL 1.1의 일부이며 Doom 3에서 사용되었으므로 지원이 매우 좋을 것으로 기대할 수 있습니다).

기본 설정은 다음과 같습니다.

  • 맑은 색을 검은 색으로.
  • 깊이 쓰기를 비활성화합니다 (이 방법에는 깊이 버퍼가 필요하지 않으므로 해당 부분을 사용하지 않으므로 무시할 수 있습니다).
  • 텍스처와 같은 치수로 뷰포트를 설정합니다.
  • 카드를 흰색으로 채워진 도형으로 그립니다.
  • 텍스처에 glCopyTexSubImage2D.
  • 뷰포트를 전체 창 크기로 다시 전환합니다.
  • 평소대로 테이블을 그립니다.
  • 셰이더를 사용하여 텍스쳐를 풀 스크린 블렌드 쿼드로 그립니다.
  • 다른 모든 것을 그립니다.

그것은 또한 잘 작동해야합니다. 스텐실 버퍼 방법보다 약간 GPU 집약적이지만 겹치는 경우를 올바르게 처리합니다. 말한 것처럼 저의 게임에서도 로우 엔드에서도 GPU 성능을 얻을 수 있다고 생각합니다 카드.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.