2013-07-08 4 views
1

나는 freeglut을 사용하여 몇 가지 OpenGL 프로그래밍을 시도하고있다. 3D 공간에서 움직이는 물체 (혜성/비행기)를 가정 해 보겠습니다.이 구름에 의해 추적되는 경로를 포인트 클라우드 (비행기에서 남겨진 흰 흔적을 나타냄)로 렌더링하고 싶습니다.opengl : 혜성과 그것으로 추적되는 경로를 어떻게 표시하나요?

내 문제는 비행기로 이동하기 위해 glutDispFunc가 호출 될 때마다 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)를 사용하여 화면을 지울 필요가 있다는 것입니다. 키보드 기능을 사용하여 비행기의 위치를 ​​변경하고 있습니다. 그러나 나는 또한 분명 화면이

포인트의 수가 증가로 심각한 성능 저하를 초래
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

를 사용하지만를 표시 할 수 있습니다으로 시도 비행기 moves.I로 축적에 이동 점의 거대한 숫자를 표시해야 움직이는 비행기뿐만 아니라 포인트 클라우드. 누구나 그러한 시나리오를 어떻게 처리 할 수 ​​있는지 알고 있습니까?

답변

6

예, 화면을 지우고 매번 다시 그립니다. 그것이 얼마나 많은 게임 엔진이 작동하는지입니다.

그러나 나는 또한 당신은 아마 너무 많은 입자를 그리기 위해 노력하고

를 사용하여 명확 화면 시도 moves.I 비행기로 축적에 이동 점의 거대한 숫자를 표시해야합니다. 100 개의 입자 (또는 수백, 그러나 천 미만)는 혜성 흔적을 그리기에 충분해야합니다. 200 개 (BIG) 입자 만 있으면 매우 설득력있는 구름을 만들 수 있습니다.

또한 혜성 흔적을 그리는 데 포인트가 필요하지 않습니다. 알파 블렌딩을 사용하면 삼각형을 사용하여 반투명 광선 - 사브르 유사 선을 쉽게 그릴 수 있습니다.

라이트 세이버와 같은, 플라즈마 등 (예를 들어, RGB 255, 10, 10)을 백색의 작은 색조 색상을 사용해야 불꽃 같은, 전통적 여기 glBlendFunc(GL_SRC_ALPHA, GL_ONE)

가 사용 그려 몇 가지 예입니다. 예는 사용해야하는 삼각형 메쉬를 보여줍니다. 숫자는 알파를 나타냅니다. 0 - 완전 투명, 1 - 완전 불투명. 슬래시는 필요한 경우 삼각 측량을 나타냅니다."|"

빛나는 라인

0--0--0--0 
| \| | /| 
0--1--1--0 
| /| | \| 
0--0--0--0 

repeat 
0--0 
| | 
1--1 
| | 
0--0 
to add more segments 

0--0--0--0 
| \| | /| 
0--1--1--0 
| | | | 
0--1--1--0 
| /| | \| 
0--0--0--0 
repeat 
0--0 
| | 
1--1 
| | 
1--1 
| | 
0--0 
to add more segments. 

당신은 혜성 흔적을 위해 그런 일을 사용할 수있는 두꺼운 빛나는 라인 : -와 ""얼굴 가장자리를 나타냅니다. 스파크 등을 위해 작은 입자를 몇 개 추가하십시오. 텍스처도 잊지 마세요. 텍스처를 사용하면 텍스처가없는 지오메트리를 사용하여 모든 것을 그리려는 것보다 더 많은 세부 사항을 쉽게 추가 할 수 있습니다.

--edit--

은 "연기에 매우 큰 질감 입자를 사용할 필요가

어떤 종류의 연기를 구현하려면 ...

  1. 비행기의 흰색 흔적 "/"흐린 "질감. google 이미지에 google "smoke particle texture"를 사용하면 내가 말하는 것을 볼 수 있습니다.
  2. "큰"입자는 일반적으로 포인트 스프라이트를 사용하여 그려지 지 않습니다 (가까운 거리에서 화면보다 커질 수 있기 때문에). "광고판"이 필요합니다. 빌보드는 항상 카메라를 바라 보는 광장입니다.
  3. 연기 질감의 색상 채널은 완전히 흰색이어야합니다 (정점 색상을 사용하여 개별 입자에 색상을 지정할 수 있음). 그리고 "smoke"는 알파에 칠해 야합니다.
  4. 연기 입자는 그릴 때 깊이로 정렬해야하며 가장 가까운 곳에서 가까운 곳으로 렌더링해야합니다 (카메라에서). 삽입 정렬 알고리즘은 "부분적으로 정렬 된"데이터와 잘 맞습니다.
  5. 연기 입자는 깊이 쓰기 기능을 사용하지 않도록 설정해야합니다 (정확하게 기억하는 경우 glDepthMask(0)).
  6. 연기 입자는 블렌드를 사용해야합니다.
  7. 그러나 연기 내에 화염이있는 경우 불꽃은 glBlendFunc(GL_SRC_ALPHA, GL_ONE)을 사용해야합니다. 화염 입자는 섞어서 (즉, 입자와 함께 깊이로 정렬하여) 또는 연기 후 (입자 시스템을 별도로 사용하는 경우)에 그려야합니다.
  8. 연기를 사실적으로 만들려면 모든 입자에 작은 초기 속도를 지정하고 천천히 시간의 경과에 따라 크기를 늘리며 더 투명하게 만듭니다. 입자가 완전히 투명 해지면 입자 시스템에서 제거하십시오.
  9. 반투명 알파 혼합 표면을 그릴 때는 알파 테스트를 활성화하고 알파 == 0 인 픽셀을 잘라냅니다. 이렇게하면 렌더링 속도가 빨라집니다. (중요한 것은, 적당한 하드웨어에서도 너무 많은 연기 입자가있는 프레임 속도를 없앨 수 있기 때문입니다.)
  10. 많은 광고판 연기 입자를 사용하면 특히 매우 가깝기 때문에 값 비쌀 수 있습니다. 따라서이 연기와 입자가 많은 부분을 채우기를 원한다면 가 크고 눈높이에 떠 다니고 전체 화면 영역을 반투명 표면으로 여러 번 덮으면 여러 가지 체적 안개 기술을 연구하려고 할 수 있습니다.
  11. 행렬을 사용하여 개별 입자를 이동하지 마십시오. 한 통화 당 하나의 입자를 그려서는 안됩니다. 한 번에 모두 그려보십시오.이 방법은 훨씬 빠릅니다.
+0

답변 해 주셔서 감사합니다. 당신의 생각은 정말 멋지지만, 제가 깨닫게 된 것은 당신이 실수하지 않는다면 혜성의 짧은 꼬리를 보여 주려고한다는 것입니다. 내가 원했던 것은 영원히 남겨진 비행기의 흰 흔적과 같은 것이 었습니다. 내가 줄 수있는 또 다른 예는 페인팅 애플리케이션입니다. 그리는 동안 움직이는 페인트 브러시와 페인트 흔적을 표시 할 수 있어야합니다. 당신이 내가 전달하려는 것을 이해했으면 좋겠다. 나는 당신의 노력과 상세한 대답에 정말로 감사한다. 나는 그것이 미래에 나를 도울 것이라고 확신한다!! –

+0

완벽! 감사... –

1

이미 사용하고 있지 않다면 glDrawArrays를 사용하여 그려야합니다. glDrawArrays는 점의 배열을 취해 하나의 함수 호출로 모든 것을 그립니다. 즉각적인 드로잉 API (glBegin 및 glEnd)보다 훨씬 빠릅니다. 이처럼 설정할 수 있습니다

float points[100][3]; 
int pointsCount = 0; 
glEnableClientState(GL_VERTEX_ARRAY); 
glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), points); 

을 그리고, 객체가 점 (예를 들어, 모든 프레임은), 당신은 배열에 위치를 추가 할 수 있습니다 "생산"각 시간 :

points[pointsCount][0] = object.x; 
points[pointsCount][1] = object.y; 
points[pointsCount][2] = object.z; 
pointsCount++; 

을 그리고를 다음과 같이 그립니다.

glDrawArrays(GL_POINTS, 0, pointsCount); 

물론 배열이 채워지면 작업을 수행해야합니다.

또한 VBO가있어 속도는 더 빨라질 수 있지만 고급 기능입니다.

편집 : 예,이 방법으로 모든 것을 다시 그려야합니다. 나는 여전히 glBegin/End보다 꽤 많은 포인트로 퍼포먼스를 방해하지 않을 것이라고 말하고 싶다. answers here에 따르면 glBufferData를 사용하여 버퍼의 크기를 조정할 수 있지만 현재 데이터를 배열에 저장하고 크기를 조정하면 다시 전송해야 할 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 방금 Vertex Arrays와 VBO에 대해 읽었습니다. 그래서 모든 프레임을 지우고 모든 것을 다시 그려야한다는 말입니까? 버텍스 배열과 VBO를 사용하면 성능을 저해하지 않을 것입니다. 또한 VBO에서 GL_DYNAMIC_DRAW_ARB를 사용하여 버퍼를 업데이트 할 수 있다고 읽었습니다. 그러나 나는 버퍼의 크기를 증가시키는 방법을 이해할 수 없었다. 좀 더 자세한 정보를 제공해 주시겠습니까? –

1

예, 대부분의 게임은 화면을 지우고 프레임마다 다시 그려서 작동합니다. 그러나 프레임 당 더 적은 작업을 수행 할 수도 있습니다. 흔적 외에 화면에 다른 것이 있습니까? 이 흔적은 얼마나 오래 있어야합니까?시간이 지남에 따라 일정한 길이를 유지해야합니까 (마우스 트레일과 같이 시간이 지남에 따라 페이드 아웃되는 것과 반대)?

트레일을 페이드 아웃 할 수 있다면 버퍼 피드백을 사용할 수 있습니다. 이 기법은 문제의 화면 (또는 객체 + 흔적) 위에 반투명 쿼드를 렌더링하여 꼬리의 가장 먼 부분을 배경색으로 사라지게합니다. 그런 다음 개체가 새 위치에서 그려져 꼬리의 가장 밝은 부분을 다시 만듭니다. 이것은 꽤 일반적인 데모/시각화 효과이며 매우 작은 프레임 당 드로잉 오버 헤드로 정말 멋진 테일을 만들 수 있습니다.

아마도 이것이 정확히 필요한 것은 아닙니다. (@ SigTerm의 답변에 대한 의견이 필요하다는 점을 분명히하기 전에 필자가 썼습니다.) 다른 사람이 이런 종류의 "흔적"을 필요로하기 때문에 여기에 남겨 두겠습니다. .

관련 문제