1. 3D Direct Application
1.1 Particle System
1.1.1 GPU Particle System
- 입자 시스템은 시간이 흐름에 따라 새 입자들을 방출하거나 기존 입자들을 파괴
- 동적 정점 버퍼에 입자들을 담고 CPU에 입자들을 생성하거나 파괴
- 스트림 출력 전용 패스를 이용하면 생성/파괴 갱신 주기를 전적으로 GPU에서 수행하는 것이 가능
1.1.1.1 Particle Effect
- 특정한 입자 시스템의 구체적인 행동방식은 하나의 효과파일로 구현, 각 입자 시스템마다 서로 다른 효과파일이 있는 것
- 입자를 방출하고 파괴하고 그리는 구체적인 방법은 입자 시스템마다 다르기 때문에 개별적인 효과 파일 사용
- 비 입자는 땅에 닿으면 파괴해야하는 반면 불 입자는 방출 몇 초 후에 파괴하는 것이 자연스러움
- 연기 입자는 시간이 흐르면 희미해지는 것이 자연스럽지만, 비 입자는 그렇지 않음
- 연기 입자 크기는 시간이 흐름에 따라 커질 수 있지만, 비는 그렇지 않음
- 비를 본뜰 때 선 기본도형이 적합, 불이나 연기 입자에는 빌보드 사각형이 적합
- 비에 대해 점을 선으로 확장하는 기하 셰이더, 불이나 연기에 대해 점을 사각형으로 확장하는 기하 셰이더 적용
- 비 입자와 연기 입자의 초기 위치 및 속도가 같지 않음
- 입자 시스템의 이러한 세부사항들을 효과 파일로 구현할 수 있는 것은 셰이더 코드에서 입자를 생성하고 파괴하고 갱신하는 것이 가능한 덕분, 이러한 셰이더 기반 설계에서 새 입자 시스템을 추가하는 것이 아주 편함
1.1.1.2 Emitter Particle
- 입자를 방출하는 역할을 하는 특별한 종류의 입자인 방출기 입자를 생성, 화면에 그려지지 않을 수도 있음
- 다른 입자들을 생성할 수 있다는 점, 지금까지 흐른 시간이 일정 지점에 도달하면 새 입자를 방출 가능
- 시간의 흐름에 따라 입자들이 방출
1.2 Fire Particle System
1.2.1 Stream Output Shader
[maxvertexcount(2)]
void StreamOutGS(point Particle gin[1], inout PointStream<Particle> ptStream)
- 스트림 출력 전용 셰이더는 새 입자의 방출과 기존 입자의 파괴만 담당
- 입자 시스템마다 입자의 생성/파괴 규칙이 다를 것이므로 이 부분의 구현 역시 입자 시스템마다 다를 필요가 있음
- 입자 시스템의 입자를 Delta Time에 따라 생성 주기를 확인
- 처음 정점이 생성될 때 Emitter Particle, 즉 방출기 입자를 생성하여 입자에 대해 생성하고 항상 하나를 유지
gin[0].Age += gTimeStep;
if (gin[0].Type == PT_EMITTER)
{
if (gin[0].Age > 0.005f)
{
float3 vRandom = RandUnitVec3(0.0f);
vRandom.x *= 0.5f; vRandom.z *= 0.5f;
Particle p;
p.InitialPosW = gEmitPosW.xyz; p.InitialVelW = 4.0f * vRandom;
p.SizeW = float2(3.0f, 3.0f); p.Age = 0.0f; p.Type = PT_FLARE;
ptStream.Append(p);
gin[0].Age = 0.0f;
}
ptStream.Append(gin[0]);
}
- 여기서 입자를 유지할 조건들을 지정하여 입자 생성 주기를 설정, 구체적인 조건은 입자 시스템마다 다를 수 있음
else if (gin[0].Age <= 1.0f) ptStream.Append(gin[0]);
1.2.1 Rendering Shader
[maxvertexcount(4)]
void DrawGS(point VertexOut gin[1], inout TriangleStream<GeoOut> triStream)
- S/O 단계에서 방출기 입자를 생성하고 방출기 입자는 그리지 않고 입자들을 생성
if (gin[0].Type != PT_EMITTER) { /* Emitter Particle X */ }
- 빌보드가 카메라를 향하게 하는 세계 행렬을 계산
float3 look = normalize(gEyePosW.xyz - gin[0].PosW);
float3 right = normalize(cross(float3(0, 1, 0), look));
float3 up = cross(look, right);
- 사각형을 구성하는 삼각형 띠 정점들을 계산
float halfWidth = 0.5f * gin[0].SizeW.x; float halfHeight = 0.5f * gin[0].SizeW.y;
float4 v[4];
v[0] = float4(gin[0].PosW + halfWidth * right - halfHeight * up, 1.0f);
v[1] = float4(gin[0].PosW + halfWidth * right + halfHeight * up, 1.0f);
v[2] = float4(gin[0].PosW - halfWidth * right - halfHeight * up, 1.0f);
v[3] = float4(gin[0].PosW - halfWidth * right + halfHeight * up, 1.0f);
- 이 정점들을 세계 공간으로 변환하고 하나의 삼각형 띠로서 출력
GeoOut gout;
[unroll]
for (int i = 0; i < 4; ++i)
{
gout.PosH = mul(v[i], gViewProj); gout.Tex = gQuadTexC[i]; gout.Color = gin[0].Color;
triStream.Append(gout);
}
1.3 Rain Particle System
1.3.1 Stream Output Shader
[maxvertexcount(6)]
void StreamOutGS(point Particle gin[1], inout PointStream<Particle> ptStream)
- 위 방식처럼 생명 주기 및 방출기 입자를 생성
gin[0].Age += gTimeStep;
if (gin[0].Type == PT_EMITTER) { /* Create Emitter Particle */ }
- 새 입자를 방출할 시간을 설정하여 지난 경우 카메라 위쪽에 빗방울들을 분포
- 입자들의 세부사항을 설정 & 방출할 시간을 재설정하고 방출기 입자 하나는 항상 유지하도록 설정
if (gin[0].Age > 0.002f)
{
for (int i = 0; i < 5; ++i)
{
float3 vRandom = 35.0f * RandVec3((float)i / 5.0f); vRandom.y = 20.0f;
Particle p;
p.InitialPosW = gEmitPosW.xyz + vRandom; p.InitialVelW = float3(0.0f, 0.0f, 0.0f);
p.SizeW = float2(1.0f, 1.0f); p.Age = 0.0f; p.Type = PT_FLARE;
ptStream.Append(p);
}
gin[0].Age = 0.0f;
}
ptStream.Append(gin[0]);
- 위와 같이 여기서 입자를 유지할 조건들을 지정, 구체적인 조건은 입자 시스템마다 다를 수 있음
else if (gin[0].Age <= 3.0f) ptStream.Append(gin[0]);
1.3.2 Rendering Shader
[maxvertexcount(2)]
void DrawGS(point VertexOut gin[1], inout LineStream<GeoOut> lineStream)
- 렌더링용 기하 셰이더에서 점을 선으로 확장
- 방출기 입자는 그리지 않고 선분이 가속도 방향으로 기울어지게 설정
if (gin[0].Type != PT_EMITTER)
{
float3 p0 = gin[0].PosW; float3 p1 = gin[0].PosW + 0.07f * gAccelW;
GeoOut v0;
v0.PosH = mul(float4(p0, 1.0f), gViewProj); v0.Tex = float2(0.0f, 0.0f);
lineStream.Append(v0);
GeoOut v1;
v1.PosH = mul(float4(p1, 1.0f), gViewProj); v1.Tex = float2(1.0f, 1.0f);
lineStream.Append(v1);
}
'C++ Algorithm & Study > Game Math & DirectX 11' 카테고리의 다른 글
[Direct11] 44. 3D Direct Application - Shadow Mapping #2 (0) | 2023.07.03 |
---|---|
[Direct11] 43. 3D Direct Application - Shadow Mapping #1 (0) | 2023.07.03 |
[Direct11] 41. 3D Direct Application - Particle System #1 (0) | 2023.07.03 |
[Direct11] 40. 3D Direct Application - Terrian Rendering #2 (0) | 2023.06.30 |
[Direct11] 39. 3D Direct Application - Terrian Rendering #1 (0) | 2023.06.30 |