입자 시스템용 점 스프라이트
포인트 스프라이트는 입자 시스템을 구축하는 데 가장 적합한 선택입니까?
최신 버전의 OpenGL과 최신 그래픽 카드 드라이버에 포인트 스프라이트가 있습니까?아니면 vbo와 glsl을 이용해서 할까요?
포인트 스프라이트는 입자 시스템에 매우 적합합니다.그러나 이들은 VBO 및 GLSL과 아무런 관련이 없으며, 이는 이들이 완전히 직교하는 특징임을 의미합니다.포인트 스프라이트를 사용하든 사용하지 않든 간에 항상 VBO를 사용하여 기하학적 구조를 업로드해야 합니다. 포인트든, 미리 만들어진 스프라이트든, 무엇이든 말입니다. 그리고 이 기하학적 구조를 쉐이더 세트(물론 현대 OpenGL에서는)를 통해 입력해야 합니다.
, 스프라이트는 잘의 고정 으로 지원되지는 , , OpenGL 에서되며.지원되지 않는 점 감쇄 기능은 카메라와의 거리에 따라 점의 크기를 조정할 수 있는 점 감쇄 기능이며, 이 작업은 정점 쉐이더 내부에서 수동으로 수행해야 합니다.으로 특수 입력 변수를.gl_PointCoord
(즉, 현재 조각이 전체 점의 [0,1]-제곱의 위치에 있음을 나타냅니다).)예를 들어, 기본 포인트 스프라이트 파이프라인은 다음과 같이 보일 수 있습니다.
...
glPointSize(whatever); //specify size of points in pixels
glDrawArrays(GL_POINTS, 0, count); //draw the points
정점 셰이더:
uniform mat4 mvp;
layout(location = 0) in vec4 position;
void main()
{
gl_Position = mvp * position;
}
프래그먼트 셰이더
uniform sampler2D tex;
layout(location = 0) out vec4 color;
void main()
{
color = texture(tex, gl_PointCoord);
}
그리고 그게 다에요.물론 이러한 쉐이더는 질감이 있는 스프라이트의 가장 기본적인 그림을 그릴 뿐이지만 추가 기능의 시작점이 됩니다.를 들어, 스프라이트와 의 거리를 된 세계 다를어하고면해) 합니다.glEnable(GL_PROGRAM_POINT_SIZE)
gl_PointSize
버텍스 쉐이더에서:
uniform mat4 modelview;
uniform mat4 projection;
uniform vec2 screenSize;
uniform float spriteSize;
layout(location = 0) in vec4 position;
void main()
{
vec4 eyePos = modelview * position;
vec4 projVoxel = projection * vec4(spriteSize,spriteSize,eyePos.z,eyePos.w);
vec2 projSize = screenSize * projVoxel.xy / projVoxel.w;
gl_PointSize = 0.25 * (projSize.x+projSize.y);
gl_Position = projection * eyePos;
}
이렇게 하면 모든 점 스프라이트가 동일한 세계 공간 크기를 갖게 됩니다(따라서 픽셀 단위의 화면 공간 크기가 달라집니다).
그러나 포인트 스프라이트는 현대 OpenGL에서 완벽하게 지원되지만 단점이 있습니다.가장 큰 단점 중 하나는 그들의 클리핑 행동입니다.점은 중심 좌표에서 잘라냅니다(클립은 래스터화 전에 수행되므로 점이 "확장"되기 전에 수행되기 때문입니다).따라서 점의 중심이 화면 밖에 있으면 보기 영역에 도달할 수 있는 나머지 부분이 표시되지 않으므로 최악의 경우 점이 화면의 절반 밖으로 나오면 갑자기 사라집니다.그러나 이는 점 스프라이트가 너무 큰 경우에만 눈에 띄는(또는 성가신) 현상입니다.어쨌든 그것들이 아주 작은 입자이고 각각 몇 개의 픽셀 이상을 덮지 않는다면, 이것은 큰 문제가 되지 않을 것이고, 저는 여전히 입자 시스템을 포인트 스프라이트의 표준 사용 사례로 간주할 것입니다. 단지 그것들을 큰 광고판에 사용하지 마십시오.
하지만 이것이 문제라면, 현대의 OpenGL은 CPU에 모든 스프라이트를 개별 쿼드로 미리 구축하는 순진한 방식 외에도 포인트 스프라이트를 구현할 수 있는 많은 다른 방법들을 제공합니다. 여전히 포인트로 가득 찬 버퍼(즉, GPU 기반 입자 엔진에서 나올 가능성이 높은 방식)로 렌더링할 수 있습니다.그러면 실제로 쿼드 지오메트리를 생성하려면 단일 지점에서 쿼드를 생성할 수 있는 지오메트리 쉐이더를 사용할 수 있습니다.먼저 정점 셰이더 내부에서 모델 뷰 변환만 수행합니다.
uniform mat4 modelview;
layout(location = 0) in vec4 position;
void main()
{
gl_Position = modelview * position;
}
그러면 기하학 쉐이더가 나머지 작업을 수행합니다.점 위치와 일반 [0,1]-쿼드의 네 모서리를 결합하고 클립 공간으로 변환을 완료합니다.
const vec2 corners[4] = {
vec2(0.0, 1.0), vec2(0.0, 0.0), vec2(1.0, 1.0), vec2(1.0, 0.0) };
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
uniform mat4 projection;
uniform float spriteSize;
out vec2 texCoord;
void main()
{
for(int i=0; i<4; ++i)
{
vec4 eyePos = gl_in[0].gl_Position; //start with point position
eyePos.xy += spriteSize * (corners[i] - vec2(0.5)); //add corner position
gl_Position = projection * eyePos; //complete transformation
texCoord = corners[i]; //use corner as texCoord
EmitVertex();
}
}
프래그먼트 쉐이더에서는 당연히 커스텀 쉐이더를 사용할 것입니다.texCoord
대신에 다양한gl_PointCoord
텍스쳐링의 경우는 더 이상 실제 포인트를 그리지 않기 때문에.
또는 다른 가능성(그리고 더 빠를 수도 있음)은 기하학 쉐이더가 느린 것으로 평판이 난 것으로 기억하기 때문에 인스턴스 렌더링을 사용하는 것입니다.이렇게 하면 단일 일반 2D 쿼드(즉, [0,1]-제곱)의 정점을 포함하는 추가 VBO와 점 위치만을 포함하는 양호한 이전 VBO가 있습니다.그런 다음 VBO 지점에서 개별 인스턴스의 위치를 소싱하면서 이 단일 쿼드를 여러 번(인스턴스) 그리는 작업을 수행합니다.
glVertexAttribPointer(0, ...points...);
glVertexAttribPointer(1, ...quad...);
glVertexAttribDivisor(0, 1); //advance only once per instance
...
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count); //draw #count quads
그리고 정점 쉐이더에서 점별 위치를 실제 코너/쿼드 위치(그 정점의 질감 좌표이기도 함)와 조합합니다.
uniform mat4 modelview;
uniform mat4 projection;
uniform float spriteSize;
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 corner;
out vec2 texCoord;
void main()
{
vec4 eyePos = modelview * position; //transform to eye-space
eyePos.xy += spriteSize * (corner - vec2(0.5)); //add corner position
gl_Position = projection * eyePos; //complete transformation
texCoord = corner;
}
이는 지오메트리 쉐이더 기반 접근법과 동일하며, 세계 공간 크기가 일관된 적절히 잘린 점 스프라이트와 동일합니다.실제 포인트 스프라이트의 화면 공간 픽셀 크기를 모방하려면 계산에 더 많은 노력을 기울여야 합니다.그러나 이것은 연습으로 남겨져 있으며 포인트 스프라이트 쉐이더에서 스크린으로의 전환과는 정반대가 될 것입니다.
언급URL : https://stackoverflow.com/questions/17397724/point-sprites-for-particle-system
'source' 카테고리의 다른 글
푸시 대 이동 비용(스택 대 메모리 근처), 함수 호출 오버헤드 (0) | 2023.10.08 |
---|---|
디브의 내용물을 포장하지 않는 방법? (0) | 2023.10.08 |
팬더 데이터 프레임을 시리즈로 변환 (0) | 2023.10.08 |
"while true"는 파이썬에서 무엇을 의미합니까? (0) | 2023.10.08 |
두 jQuery 결과를 결합하는 방법 (0) | 2023.10.08 |