๊ณ ๊ธ ๋ ๋๋ง ๊ธฐ๋ฒ์ ์ํ ์ ์ ์์ฑ ์บก์ฒ๋ฅผ ๋ค๋ฃจ๋ ๋ฐฐ๋ฆฌ์ด๋ง์ ์ด์ฉํ WebGL ํธ๋์คํผ ํผ๋๋ฐฑ ์ดํด ๋ฐ ๊ตฌํ์ ๋ํ ์ข ํฉ ๊ฐ์ด๋์ ๋๋ค.
WebGL ํธ๋์คํผ ํผ๋๋ฐฑ ๋ฐฐ๋ฆฌ์ด๋ง: ์ ์ ์์ฑ ์บก์ฒ ์์ธ ๊ฐ์ด๋
ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ ์ ์ ฐ์ด๋์ ์ถ๋ ฅ์ ์บก์ฒํ์ฌ ํ์ ๋ ๋๋ง ํจ์ค์ ์ ๋ ฅ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ๊ฐ๋ ฅํ WebGL ๊ธฐ๋ฅ์ ๋๋ค. ์ด ๊ธฐ์ ์ GPU์์ ์ง์ ๊ด๋ฒ์ํ ๊ณ ๊ธ ๋ ๋๋ง ํจ๊ณผ ๋ฐ ์ง์ค๋ฉํธ๋ฆฌ ์ฒ๋ฆฌ ์์ ์ ์ํํ ์ ์๊ฒ ํด์ค๋๋ค. ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ค์ํ ์ธก๋ฉด ์ค ํ๋๋ "๋ฐฐ๋ฆฌ์ด๋ง"์ด๋ผ๊ณ ํ๋ ์บก์ฒํด์ผ ํ๋ ์ ์ ์์ฑ์ ์ง์ ํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๋ ๊ฒ์ ๋๋ค. ์ด ๊ฐ์ด๋๋ ๋ฐฐ๋ฆฌ์ด๋ง์ ์ฌ์ฉํ ์ ์ ์์ฑ ์บก์ฒ์ ์ค์ ์ ๋ WebGL ํธ๋์คํผ ํผ๋๋ฐฑ์ ๋ํ ํฌ๊ด์ ์ธ ๊ฐ์๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํธ๋์คํผ ํผ๋๋ฐฑ์ด๋ ๋ฌด์์ ๋๊น?
์ผ๋ฐ์ ์ผ๋ก WebGL ๋ ๋๋ง์ ์ ์ ๋ฐ์ดํฐ๋ฅผ GPU๋ก ๋ณด๋ด๊ณ ์ ์ ๋ฐ ํ๋๊ทธ๋จผํธ ์ ฐ์ด๋๋ฅผ ํตํด ์ฒ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ ํฝ์ ์ ํ๋ฉด์ ํ์ํ๋ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค. ํด๋ฆฌํ ๋ฐ ์๊ทผ ๋ถํ ํ ์ ์ ์ ฐ์ด๋์ ์ถ๋ ฅ์ ์ผ๋ฐ์ ์ผ๋ก ํ๊ธฐ๋ฉ๋๋ค. ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ด๋ฌํ ํจ๋ฌ๋ค์์ ๋ณ๊ฒฝํ์ฌ ์ด๋ฌํ ํฌ์คํธ ์ ์ ์ ฐ์ด๋ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ๋ก์ฑ์ ๋ฒํผ ๊ฐ์ฒด์ ๋ค์ ์ ์ฅํ ์ ์๋๋ก ํฉ๋๋ค.
์ ์ ๋ฌผ๋ฆฌ๋ฅผ ์๋ฎฌ๋ ์ด์ ํ๋ ค๋ ์๋๋ฆฌ์ค๋ฅผ ์์ํด ๋ณด์ธ์. CPU์์ ์ ์ ์์น๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ์ ๋ฐ์ดํธ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ ํ๋ ์์์ ๋ ๋๋งํ๊ธฐ ์ํด GPU๋ก ๋ค์ ๋ณด๋ผ ์ ์์ต๋๋ค. ํธ๋์คํผ ํผ๋๋ฐฑ์ GPU์์ (์ ์ ์ ฐ์ด๋๋ฅผ ์ฌ์ฉํ์ฌ) ๋ฌผ๋ฆฌ ๊ณ์ฐ์ ์ํํ๊ณ ์ ๋ฐ์ดํธ๋ ์ ์ ์์น๋ฅผ ๋ฒํผ๋ก ์ง์ ์บก์ฒํ์ฌ ๋ค์ ํ๋ ์ ๋ ๋๋ง์ ์ฌ์ฉํ ์ ์๋๋ก ํ์ฌ ๋ณด๋ค ํจ์จ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฅผ ํตํด CPU ์ค๋ฒํค๋๋ฅผ ์ค์ด๊ณ ํนํ ๋ณต์กํ ์๋ฎฌ๋ ์ด์ ์ ๊ฒฝ์ฐ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฃผ์ ๊ฐ๋
- ์ ์ ์ ฐ์ด๋: ํธ๋์คํผ ํผ๋๋ฐฑ์ ํต์ฌ์ ๋๋ค. ์ ์ ์ ฐ์ด๋๋ ๊ฒฐ๊ณผ๊ฐ ์บก์ฒ๋๋ ๊ณ์ฐ์ ์ํํฉ๋๋ค.
- ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์: ์บก์ฒํ๋ ค๋ ์ ์ ์ ฐ์ด๋์ ์ถ๋ ฅ ๋ณ์์ ๋๋ค. ์ด๋ ๋ฒํผ ๊ฐ์ฒด์ ๋ค์ ๊ธฐ๋ก๋๋ ์ ์ ์์ฑ์ ์ ์ํฉ๋๋ค.
- ๋ฒํผ ๊ฐ์ฒด: ์บก์ฒ๋ ์ ์ ์์ฑ์ด ๊ธฐ๋ก๋๋ ์คํ ๋ฆฌ์ง์ ๋๋ค. ์ด๋ฌํ ๋ฒํผ๋ ํธ๋์คํผ ํผ๋๋ฐฑ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค.
- ํธ๋์คํผ ํผ๋๋ฐฑ ๊ฐ์ฒด: ์ ์ ์์ฑ ์บก์ฒ ํ๋ก์ธ์ค๋ฅผ ๊ด๋ฆฌํ๋ WebGL ๊ฐ์ฒด์ ๋๋ค. ๋์ ๋ฒํผ์ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๋ฅผ ์ ์ํฉ๋๋ค.
- ํ๋ฆฌ๋ฏธํฐ๋ธ ๋ชจ๋: ์ ์ ์ ฐ์ด๋์์ ์์ฑ๋ ํ๋ฆฌ๋ฏธํฐ๋ธ(์ , ์ , ์ผ๊ฐํ) ์ ํ์ ์ง์ ํฉ๋๋ค. ์ด๋ ์ฌ๋ฐ๋ฅธ ๋ฒํผ ๋ ์ด์์์ ์ค์ํฉ๋๋ค.
WebGL์์ ํธ๋์คํผ ํผ๋๋ฐฑ ์ค์
ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฌ์ฉํ๋ ํ๋ก์ธ์ค์๋ ๋ช ๊ฐ์ง ๋จ๊ณ๊ฐ ํฌํจ๋ฉ๋๋ค.
- ํธ๋์คํผ ํผ๋๋ฐฑ ๊ฐ์ฒด ์์ฑ ๋ฐ ๊ตฌ์ฑ:
gl.createTransformFeedback()์ ์ฌ์ฉํ์ฌ ํธ๋์คํผ ํผ๋๋ฐฑ ๊ฐ์ฒด๋ฅผ ๋ง๋ญ๋๋ค. ๊ทธ๋ฐ ๋ค์gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback)์ ์ฌ์ฉํ์ฌ ๋ฐ์ธ๋ฉํฉ๋๋ค. - ๋ฒํผ ๊ฐ์ฒด ์์ฑ ๋ฐ ๋ฐ์ธ๋ฉ:
gl.createBuffer()์ ์ฌ์ฉํ์ฌ ๋ฒํผ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ์บก์ฒ๋ ์ ์ ์์ฑ์ ์ ์ฅํฉ๋๋ค.gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, index, buffer)์ ์ฌ์ฉํ์ฌ ๊ฐ ๋ฒํผ ๊ฐ์ฒด๋ฅผgl.TRANSFORM_FEEDBACK_BUFFER๋์์ ๋ฐ์ธ๋ฉํฉ๋๋ค. `index`๋ ์ ฐ์ด๋ ํ๋ก๊ทธ๋จ์ ์ง์ ๋ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์์ ์์์ ํด๋นํฉ๋๋ค. - ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์ ์ง์ :
์ด๊ฒ์ ์ค์ํ ๋จ๊ณ์ ๋๋ค. ์ ฐ์ด๋ ํ๋ก๊ทธ๋จ์ ๋งํฌํ๊ธฐ ์ ์ WebGL์ ์บก์ฒํด์ผ ํ๋ ์ ์ ์ ฐ์ด๋์ ์ถ๋ ฅ ๋ณ์(๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์)๋ฅผ ์๋ ค์ผ ํฉ๋๋ค.
gl.transformFeedbackVaryings(program, varyings, bufferMode)์ ์ฌ์ฉํฉ๋๋ค.program: ์ ฐ์ด๋ ํ๋ก๊ทธ๋จ ๊ฐ์ฒด์ ๋๋ค.varyings: ๋ฌธ์์ด ๋ฐฐ์ด์ ๋๋ค. ๊ฐ ๋ฌธ์์ด์ ์ ์ ์ ฐ์ด๋์ ์๋ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์์ ์ด๋ฆ์ ๋๋ค. ์ด๋ฌํ ๋ณ์์ ์์๋ ์ค์ํฉ๋๋ค. ๋ฒํผ ๋ฐ์ธ๋ฉ ์ธ๋ฑ์ค๋ฅผ ๊ฒฐ์ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.bufferMode: ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๊ฐ ๋ฒํผ ๊ฐ์ฒด์ ๊ธฐ๋ก๋๋ ๋ฐฉ์์ ์ง์ ํฉ๋๋ค. ์ผ๋ฐ์ ์ธ ์ต์ ์gl.SEPARATE_ATTRIBS(๊ฐ ๋ฐฐ๋ฆฌ์ด๋ง์ ๋ณ๋์ ๋ฒํผ๋ก ์ด๋) ๋ฐgl.INTERLEAVED_ATTRIBS(๋ชจ๋ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๋ ๋จ์ผ ๋ฒํผ์ ์ธํฐ๋ฆฌ๋ธ๋จ)์ ๋๋ค.
- ์
ฐ์ด๋ ์์ฑ ๋ฐ ์ปดํ์ผ:
์ ์ ๋ฐ ํ๋๊ทธ๋จผํธ ์ ฐ์ด๋๋ฅผ ๋ง๋ญ๋๋ค. ์ ์ ์ ฐ์ด๋๋ ์บก์ฒํ๋ ค๋ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๋ฅผ ์ถ๋ ฅํด์ผ ํฉ๋๋ค. ํ๋๊ทธ๋จผํธ ์ ฐ์ด๋๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ๋ผ ํ์ํ ์๋ ์๊ณ ํ์ํ์ง ์์ ์๋ ์์ต๋๋ค. ๋๋ฒ๊น ์ ์ ์ฉํ ์ ์์ต๋๋ค.
- ์
ฐ์ด๋ ํ๋ก๊ทธ๋จ ๋งํฌ:
gl.linkProgram(program)์ ์ฌ์ฉํ์ฌ ์ ฐ์ด๋ ํ๋ก๊ทธ๋จ์ ๋งํฌํฉ๋๋ค. ํ๋ก๊ทธ๋จ์ ๋งํฌํ๊ธฐ *์ ์*gl.transformFeedbackVaryings()์ ํธ์ถํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. - ํธ๋์คํผ ํผ๋๋ฐฑ ์์ ๋ฐ ์ข
๋ฃ:
์ ์ ์์ฑ ์บก์ฒ๋ฅผ ์์ํ๋ ค๋ฉด
gl.beginTransformFeedback(primitiveMode)์ ํธ์ถํฉ๋๋ค. ์ฌ๊ธฐ์primitiveMode๋ ์์ฑ๋๋ ํ๋ฆฌ๋ฏธํฐ๋ธ ์ ํ(์:gl.POINTS,gl.LINES,gl.TRIANGLES)์ ์ง์ ํฉ๋๋ค. ๋ ๋๋ง ํgl.endTransformFeedback()์ ํธ์ถํ์ฌ ์บก์ฒ๋ฅผ ์ค์งํฉ๋๋ค. - ์ง์ค๋ฉํธ๋ฆฌ ๊ทธ๋ฆฌ๊ธฐ:
gl.drawArrays()๋๋gl.drawElements()์ ์ฌ์ฉํ์ฌ ์ง์ค๋ฉํธ๋ฆฌ๋ฅผ ๋ ๋๋งํฉ๋๋ค. ์ ์ ์ ฐ์ด๋๊ฐ ์คํ๋๊ณ ์ง์ ๋ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๊ฐ ๋ฒํผ ๊ฐ์ฒด์ ์บก์ฒ๋ฉ๋๋ค.
์: ์ ์ ์์น ์บก์ฒ
์ ์ ์์น ์บก์ฒ์ ๊ฐ๋จํ ์๋ก ์ด๋ฅผ ์ค๋ช ํด ๋ณด๊ฒ ์ต๋๋ค. ์๋์ ์ค๋ ฅ์ ๋ฐ๋ผ ์ ์ ์์น๋ฅผ ์ ๋ฐ์ดํธํ๋ ์ ์ ์ ฐ์ด๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
์ ์ ์ ฐ์ด๋ (particle.vert)
#version 300 es
in vec3 a_position;
in vec3 a_velocity;
uniform float u_timeStep;
out vec3 v_position;
out vec3 v_velocity;
void main() {
vec3 gravity = vec3(0.0, -9.8, 0.0);
v_velocity = a_velocity + gravity * u_timeStep;
v_position = a_position + v_velocity * u_timeStep;
gl_Position = vec4(v_position, 1.0);
}
์ด ์ ์ ์
ฐ์ด๋๋ a_position๊ณผ a_velocity๋ฅผ ์
๋ ฅ ์์ฑ์ผ๋ก ์ฌ์ฉํฉ๋๋ค. ๊ฐ ์
์์ ์๋ก์ด ์๋์ ์์น๋ฅผ ๊ณ์ฐํ์ฌ ๊ฒฐ๊ณผ๋ฅผ v_position๊ณผ v_velocity ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์์ ์ ์ฅํฉ๋๋ค. `gl_Position`์ ๋ ๋๋ง์ ์ํด ์๋ก์ด ์์น๋ก ์ค์ ๋ฉ๋๋ค.
JavaScript ์ฝ๋
// ... WebGL ์ปจํ
์คํธ ์ด๊ธฐํ ...
// 1. ํธ๋์คํผ ํผ๋๋ฐฑ ๊ฐ์ฒด ์์ฑ
const transformFeedback = gl.createTransformFeedback();
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback);
// 2. ์์น ๋ฐ ์๋์ ๋ํ ๋ฒํผ ๊ฐ์ฒด ์์ฑ
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, particlePositions, gl.DYNAMIC_COPY); // ์ด๊ธฐ ์
์ ์์น
const velocityBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, velocityBuffer);
gl.bufferData(gl.ARRAY_BUFFER, particleVelocities, gl.DYNAMIC_COPY); // ์ด๊ธฐ ์
์ ์๋
// 3. ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์ ์ง์
const varyings = ['v_position', 'v_velocity'];
gl.transformFeedbackVaryings(program, varyings, gl.SEPARATE_ATTRIBS); // ํ๋ก๊ทธ๋จ์ ๋งํฌํ๊ธฐ *์ ์* ํธ์ถํด์ผ ํฉ๋๋ค.
// 4. ์
ฐ์ด๋ ์์ฑ ๋ฐ ์ปดํ์ผ (๊ฐ๋จํ๊ฒ ์๋ต๋จ)
// ...
// 5. ์
ฐ์ด๋ ํ๋ก๊ทธ๋จ ๋งํฌ
gl.linkProgram(program);
// ํธ๋์คํผ ํผ๋๋ฐฑ ๋ฒํผ ๋ฐ์ธ๋ฉ
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, positionBuffer); // v_position์ ๋ํ ์ธ๋ฑ์ค 0
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, velocityBuffer); // v_velocity์ ๋ํ ์ธ๋ฑ์ค 1
// ์์ฑ ์์น ๊ฐ์ ธ์ค๊ธฐ
const positionLocation = gl.getAttribLocation(program, 'a_position');
const velocityLocation = gl.getAttribLocation(program, 'a_velocity');
// --- ๋ ๋๋ง ๋ฃจํ ---
function render() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.useProgram(program);
// ์์ฑ ํ์ฑํ
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, velocityBuffer);
gl.vertexAttribPointer(velocityLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(velocityLocation);
// 6. ํธ๋์คํผ ํผ๋๋ฐฑ ์์
gl.enable(gl.RASTERIZER_DISCARD); // ๋์คํฐํ ๋นํ์ฑํ
gl.beginTransformFeedback(gl.POINTS);
// 7. ์ง์ค๋ฉํธ๋ฆฌ ๊ทธ๋ฆฌ๊ธฐ
gl.drawArrays(gl.POINTS, 0, numParticles);
// 8. ํธ๋์คํผ ํผ๋๋ฐฑ ์ข
๋ฃ
gl.endTransformFeedback();
gl.disable(gl.RASTERIZER_DISCARD); // ๋์คํฐํ ๋ค์ ํ์ฑํ
// ๋ฒํผ ์ค์ (์ ํ ์ฌํญ, ์ ์ ๋ ๋๋งํ๋ ค๋ ๊ฒฝ์ฐ)
// ์๋ฅผ ๋ค์ด ์
๋ฐ์ดํธ๋ ์์น ๋ฒํผ๋ฅผ ๋ค์ ๋ ๋๋งํฉ๋๋ค.
requestAnimationFrame(render);
}
render();
์ด ์์์:
- ์ ์ ์์น์ ์๋์ ๋ํด ๊ฐ๊ฐ ํ๋์ฉ ๋ ๊ฐ์ ๋ฒํผ ๊ฐ์ฒด๋ฅผ ๋ง๋ญ๋๋ค.
v_position๊ณผv_velocity๋ฅผ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๋ก ์ง์ ํฉ๋๋ค.- ์์น ๋ฒํผ๋ฅผ ์ธ๋ฑ์ค 0์, ์๋ ๋ฒํผ๋ฅผ ํธ๋์คํผ ํผ๋๋ฐฑ ๋ฒํผ์ ์ธ๋ฑ์ค 1์ ๋ฐ์ธ๋ฉํฉ๋๋ค.
- ์ ์ ์์ฑ ๋ฐ์ดํฐ๋ง ์บก์ฒํ๊ณ ์ด ํจ์ค์์ ์๋ฌด๊ฒ๋ ๋ ๋๋งํ์ง ์์ผ๋ฏ๋ก
gl.enable(gl.RASTERIZER_DISCARD)๋ฅผ ์ฌ์ฉํ์ฌ ๋์คํฐํ๋ฅผ ๋นํ์ฑํํฉ๋๋ค. ์ด๋ ์ฑ๋ฅ์ ์ค์ํฉ๋๋ค. gl.drawArrays(gl.POINTS, 0, numParticles)๋ฅผ ํธ์ถํ์ฌ ๊ฐ ์ ์์ ๋ํด ์ ์ ์ ฐ์ด๋๋ฅผ ์คํํฉ๋๋ค.- ์ ๋ฐ์ดํธ๋ ์ ์ ์์น์ ์๋๊ฐ ๋ฒํผ ๊ฐ์ฒด์ ์บก์ฒ๋ฉ๋๋ค.
- ํธ๋์คํผ ํผ๋๋ฐฑ ํจ์ค ํ ์ ๋ ฅ ๋ฐ ์ถ๋ ฅ ๋ฒํผ๋ฅผ ์ค์ํ๊ณ ์ ๋ฐ์ดํธ๋ ์์น๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ ์๋ฅผ ๋ ๋๋งํ ์ ์์ต๋๋ค.
๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์: ์ธ๋ถ ์ฌํญ ๋ฐ ๊ณ ๋ ค ์ฌํญ
`gl.transformFeedbackVaryings()`์ `varyings` ๋งค๊ฐ๋ณ์๋ ์บก์ฒํ๋ ค๋ ์ ์ ์ ฐ์ด๋์ ์ถ๋ ฅ ๋ณ์ ์ด๋ฆ์ ๋ํ๋ด๋ ๋ฌธ์์ด ๋ฐฐ์ด์ ๋๋ค. ์ด๋ฌํ ๋ณ์๋ ๋ค์ ์กฐ๊ฑด์ ์ถฉ์กฑํด์ผ ํฉ๋๋ค.
- ์ ์ ์
ฐ์ด๋์์
out๋ณ์๋ก ์ ์ธ๋์ด์ผ ํฉ๋๋ค. - ์ ์ ์
ฐ์ด๋ ์ถ๋ ฅ๊ณผ ๋ฒํผ ๊ฐ์ฒด ์คํ ๋ฆฌ์ง ๊ฐ์ ์ผ์นํ๋ ๋ฐ์ดํฐ ์ ํ์ด ์์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๊ฐ
vec3์ธ ๊ฒฝ์ฐ ํด๋น ๋ฒํผ ๊ฐ์ฒด๋ ๋ชจ๋ ์ ์ ์ ๋ํดvec3๊ฐ์ ์ ์ฅํ ์ ์์ ๋งํผ ์ปค์ผ ํฉ๋๋ค. - ์ฌ๋ฐ๋ฅธ ์์๋ก ๋์ด ์์ด์ผ ํฉ๋๋ค. `varyings` ๋ฐฐ์ด์ ์์๋ ๋ฒํผ ๋ฐ์ธ๋ฉ ์ธ๋ฑ์ค๋ฅผ ๋ํ๋ ๋๋ค. ์ฒซ ๋ฒ์งธ ๋ฐฐ๋ฆฌ์ด๋ง์ ๋ฒํผ ์ธ๋ฑ์ค 0์, ๋ ๋ฒ์งธ ๋ฐฐ๋ฆฌ์ด๋ง์ ์ธ๋ฑ์ค 1์ ๊ธฐ๋ก๋ฉ๋๋ค.
๋ฐ์ดํฐ ์ ๋ ฌ ๋ฐ ๋ฒํผ ๋ ์ด์์
์ฌ๋ฐ๋ฅธ ํธ๋์คํผ ํผ๋๋ฐฑ ์๋์ ์ํด์๋ ๋ฐ์ดํฐ ์ ๋ ฌ์ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๋ฒํผ ๊ฐ์ฒด์์ ์บก์ฒ๋ ์ ์ ์์ฑ์ ๋ ์ด์์์ `gl.transformFeedbackVaryings()`์ `bufferMode` ๋งค๊ฐ๋ณ์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
gl.SEPARATE_ATTRIBS: ๊ฐ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๋ ๋ณ๋์ ๋ฒํผ ๊ฐ์ฒด์ ๊ธฐ๋ก๋ฉ๋๋ค. ์ธ๋ฑ์ค 0์ ๋ฐ์ธ๋ฉ๋ ๋ฒํผ ๊ฐ์ฒด์๋ ์ฒซ ๋ฒ์งธ ๋ฐฐ๋ฆฌ์ด๋ง์ ๋ํ ๋ชจ๋ ๊ฐ์ด ํฌํจ๋๊ณ , ์ธ๋ฑ์ค 1์ ๋ฐ์ธ๋ฉ๋ ๋ฒํผ ๊ฐ์ฒด์๋ ๋ ๋ฒ์งธ ๋ฐฐ๋ฆฌ์ด๋ง์ ๋ํ ๋ชจ๋ ๊ฐ์ด ํฌํจ๋ฉ๋๋ค. ์ด ๋ชจ๋๋ ์ผ๋ฐ์ ์ผ๋ก ์ดํดํ๊ณ ๋๋ฒ๊ทธํ๊ธฐ๊ฐ ๋ ๊ฐ๋จํฉ๋๋ค.gl.INTERLEAVED_ATTRIBS: ๋ชจ๋ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๋ ๋จ์ผ ๋ฒํผ ๊ฐ์ฒด์ ์ธํฐ๋ฆฌ๋ธ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ ๊ฐ์ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์,v_position(vec3)๊ณผv_velocity(vec3)๊ฐ ์๋ ๊ฒฝ์ฐ ๋ฒํผ์๋vec3(์์น),vec3(์๋),vec3(์์น),vec3(์๋) ๋ฑ์ ์ํ์ค๊ฐ ํฌํจ๋ฉ๋๋ค. ์ด ๋ชจ๋๋ ํนํ ์บก์ฒ๋ ๋ฐ์ดํฐ๊ฐ ํ์ ๋ ๋๋ง ํจ์ค์์ ์ธํฐ๋ฆฌ๋ธ๋ ์ ์ ์์ฑ์ผ๋ก ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ ํน์ ์ฌ์ฉ ์ฌ๋ก์ ๋ ํจ์จ์ ์ผ ์ ์์ต๋๋ค.
์ผ์นํ๋ ๋ฐ์ดํฐ ์ ํ
์ ์ ์
ฐ์ด๋์ ์๋ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์์ ๋ฐ์ดํฐ ์ ํ์ ๋ฒํผ ๊ฐ์ฒด์ ์คํ ๋ฆฌ์ง ํ์๊ณผ ํธํ๋์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๋ฅผ out vec3 v_color๋ก ์ ์ธํ๋ ๊ฒฝ์ฐ ๋ฒํผ ๊ฐ์ฒด๊ฐ ๋ชจ๋ ์ ์ ์ ๋ํด vec3 ๊ฐ(์ผ๋ฐ์ ์ผ๋ก ๋ถ๋ ์์์ ๊ฐ)์ ์ ์ฅํ ์ ์์ ๋งํผ ํฐ์ง ํ์ธํด์ผ ํฉ๋๋ค. ๋ฐ์ดํฐ ์ ํ์ด ์ผ์นํ์ง ์์ผ๋ฉด ์๊ธฐ์น ์์ ๊ฒฐ๊ณผ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
๋์คํฐ๋ผ์ด์ ํ๊ธฐ ์ฒ๋ฆฌ
์ด๊ธฐ ํจ์ค์์ ์ ์ ์์ฑ ๋ฐ์ดํฐ๋ฅผ ์บก์ฒํ๋ ๋ฐ๋ง ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ(์๋ฌด๊ฒ๋ ๋ ๋๋งํ์ง ์์) gl.beginTransformFeedback()์ ํธ์ถํ๊ธฐ ์ ์ gl.enable(gl.RASTERIZER_DISCARD)๋ฅผ ์ฌ์ฉํ์ฌ ๋์คํฐํ๋ฅผ ๋นํ์ฑํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด GPU๊ฐ ๋ถํ์ํ ๋์คํฐํ ์์
์ ์ํํ์ง ์์ ์ฑ๋ฅ์ด ํฌ๊ฒ ํฅ์๋ ์ ์์ต๋๋ค. ํ์ ํจ์ค์์ ๋ฌด์ธ๊ฐ๋ฅผ ๋ ๋๋งํ๋ ค๋ ๊ฒฝ์ฐ gl.endTransformFeedback()์ ํธ์ถํ ํ gl.disable(gl.RASTERIZER_DISCARD)๋ฅผ ์ฌ์ฉํ์ฌ ๋์คํฐํ๋ฅผ ๋ค์ ํ์ฑํํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค.
ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฌ์ฉ ์ฌ๋ก
ํธ๋์คํผ ํผ๋๋ฐฑ์ ๋ค์๊ณผ ๊ฐ์ WebGL ๋ ๋๋ง์์ ๋ค์ํ ์์ฉ ํ๋ก๊ทธ๋จ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- ์ ์ ์์คํ : ์์์ ์ค๋ช ํ ๊ฒ์ฒ๋ผ ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ ์ ์์น, ์๋ ๋ฐ ๊ธฐํ ์์ฑ์ GPU์์ ์ง์ ์ ๋ฐ์ดํธํ๋ ๋ฐ ์ด์์ ์ด๋ฉฐ ํจ์จ์ ์ธ ์ ์ ์๋ฎฌ๋ ์ด์ ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
- ์ง์ค๋ฉํธ๋ฆฌ ์ฒ๋ฆฌ: ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฌ์ฉํ์ฌ ๋ฉ์ฌ ๋ณํ, ์ธ๋ถํ ๋๋ ๋จ์ํ์ ๊ฐ์ ์ง์ค๋ฉํธ๋ฆฌ ๋ณํ์ GPU์์ ์ ์ฒด์ ์ผ๋ก ์ํํ ์ ์์ต๋๋ค. ์ ๋๋ฉ์ด์ ์ ์ํด ์บ๋ฆญํฐ ๋ชจ๋ธ์ ๋ณํํ๋ ๊ฒ์ ์์ํด ๋ณด์ธ์.
- ์ ์ฒด ์ญํ: GPU์์ ์ ์ฒด ํ๋ฆ์ ์๋ฎฌ๋ ์ด์ ํ๋ ๊ฒ์ ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฌ์ฉํ์ฌ ์ํํ ์ ์์ต๋๋ค. ์ ์ฒด ์ ์ ์์น์ ์๋๋ฅผ ์ ๋ฐ์ดํธํ ๋ค์ ๋ณ๋์ ๋ ๋๋ง ํจ์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฒด๋ฅผ ์๊ฐํํฉ๋๋ค.
- ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์ : ์ผ๋ฐ์ ์ผ๋ก ์ ์ ์์ฑ์ ์ ๋ฐ์ดํธํด์ผ ํ๋ ๋ชจ๋ ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์ ์ ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ์ท ์๋ฎฌ๋ ์ด์ , ๊ฐ์ฒด ์ญํ ๋๋ ๊ธฐํ ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ ํจ๊ณผ๊ฐ ํฌํจ๋ ์ ์์ต๋๋ค.
- ์ ๊ตฌ๋ฆ ์ฒ๋ฆฌ: ์๊ฐํ ๋๋ ๋ถ์์ ์ํด ์ ๊ตฌ๋ฆ์์ ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ ์บก์ฒํฉ๋๋ค. ์ฌ๊ธฐ์๋ GPU์์ ํํฐ๋ง, ํํํ ๋๋ ํน์ง ์ถ์ถ์ด ํฌํจ๋ ์ ์์ต๋๋ค.
- ์ฌ์ฉ์ ์ ์ ์ ์ ์์ฑ: ๋ค๋ฅธ ์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฒ์ ๋ฒกํฐ ๋๋ ํ ์ค์ฒ ์ขํ์ ๊ฐ์ ์ฌ์ฉ์ ์ ์ ์ ์ ์์ฑ์ ๊ณ์ฐํฉ๋๋ค. ์ด๋ ์ ์ฐจ์ ์์ฑ ๊ธฐ์ ์ ์ ์ฉํ ์ ์์ต๋๋ค.
- ์ง์ฐ ์์ ์ฌ์ ํจ์ค: ์ง์ฐ ์์ ํ์ดํ๋ผ์ธ์ ์ํด ์์น ๋ฐ ๋ฒ์ ๋ฐ์ดํฐ๋ฅผ G-buffer์ ์บก์ฒํฉ๋๋ค. ์ด ๊ธฐ์ ์ ์ฌ์ฉํ๋ฉด ๋ณด๋ค ๋ณต์กํ ์กฐ๋ช ๊ณ์ฐ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ฑ๋ฅ ๊ณ ๋ ค ์ฌํญ
ํธ๋์คํผ ํผ๋๋ฐฑ์ ์๋นํ ์ฑ๋ฅ ํฅ์์ ์ ๊ณตํ ์ ์์ง๋ง ๋ค์ ์์๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
- ๋ฒํผ ๊ฐ์ฒด ํฌ๊ธฐ: ๋ฒํผ ๊ฐ์ฒด๊ฐ ์บก์ฒ๋ ๋ชจ๋ ์ ์ ์์ฑ์ ์ ์ฅํ ์ ์์ ๋งํผ ํฐ์ง ํ์ธํฉ๋๋ค. ์ ์ ์์ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์์ ๋ฐ์ดํฐ ์ ํ์ ๊ธฐ์ค์ผ๋ก ์ฌ๋ฐ๋ฅธ ํฌ๊ธฐ๋ฅผ ํ ๋นํฉ๋๋ค.
- ๋ฐ์ดํฐ ์ ์ก ์ค๋ฒํค๋: CPU์ GPU ๊ฐ์ ๋ถํ์ํ ๋ฐ์ดํฐ ์ ์ก์ ํผํฉ๋๋ค. ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฌ์ฉํ์ฌ GPU์์ ์ต๋ํ ๋ง์ ์ฒ๋ฆฌ๋ฅผ ์ํํฉ๋๋ค.
- ๋์คํฐ๋ผ์ด์ ํ๊ธฐ: ๋ฐ์ดํฐ๋ฅผ ์บก์ฒํ๋ ๋ฐ๋ง ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
gl.RASTERIZER_DISCARD๋ฅผ ํ์ฑํํฉ๋๋ค. - ์ ฐ์ด๋ ๋ณต์ก์ฑ: ์ ์ ์ ฐ์ด๋ ์ฝ๋๋ฅผ ์ต์ ํํ์ฌ ๊ณ์ฐ ๋น์ฉ์ ์ต์ํํฉ๋๋ค. ๋ณต์กํ ์ ฐ์ด๋๋ ํนํ ๋ง์ ์์ ์ ์ ์ ์ฒ๋ฆฌํ ๋ ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค.
- ๋ฒํผ ์ค์ํ: ๋ฃจํ์์ ํธ๋์คํผ ํผ๋๋ฐฑ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ (์: ์ ์ ์๋ฎฌ๋ ์ด์ ์ ๊ฒฝ์ฐ) ์ฝ๊ธฐ ํ ์ฐ๊ธฐ ์ํ์ ํผํ๊ธฐ ์ํด ์ด์ค ๋ฒํผ๋ง(์ ๋ ฅ ๋ฐ ์ถ๋ ฅ ๋ฒํผ ์ค์ํ)์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
- ํ๋ฆฌ๋ฏธํฐ๋ธ ์ ํ: ํ๋ฆฌ๋ฏธํฐ๋ธ ์ ํ(
gl.POINTS,gl.LINES,gl.TRIANGLES)์ ์ ํ์ ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ์ฅ ์ ํฉํ ํ๋ฆฌ๋ฏธํฐ๋ธ ์ ํ์ ์ ํํ์ญ์์ค.
ํธ๋์คํผ ํผ๋๋ฐฑ ๋๋ฒ๊น
ํธ๋์คํผ ํผ๋๋ฐฑ ๋๋ฒ๊น ์ ์ด๋ ค์ธ ์ ์์ง๋ง ๋ค์์ ๋ช ๊ฐ์ง ํ์ ๋๋ค.
- ์ค๋ฅ ํ์ธ: ํธ๋์คํผ ํผ๋๋ฐฑ ์ค์ ์ ๊ฐ ๋จ๊ณ ํ์
gl.getError()๋ฅผ ์ฌ์ฉํ์ฌ WebGL ์ค๋ฅ๋ฅผ ํ์ธํฉ๋๋ค. - ๋ฒํผ ํฌ๊ธฐ ํ์ธ: ๋ฒํผ ๊ฐ์ฒด๊ฐ ์บก์ฒ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ ์์ ๋งํผ ํฐ์ง ํ์ธํฉ๋๋ค.
- ๋ฒํผ ๋ด์ฉ ๊ฒ์ฌ:
gl.getBufferSubData()๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒํผ ๊ฐ์ฒด์ ๋ด์ฉ์ CPU๋ก ๋ค์ ์ฝ๊ณ ์บก์ฒ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฌํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ ์ ๋ ฌ ๋๋ ์ ฐ์ด๋ ๊ณ์ฐ ๋ฌธ์ ๋ฅผ ์๋ณํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค. - ๋๋ฒ๊ฑฐ ์ฌ์ฉ: WebGL ๋๋ฒ๊ฑฐ (์: Spector.js)๋ฅผ ์ฌ์ฉํ์ฌ WebGL ์ํ ๋ฐ ์ ฐ์ด๋ ์คํ์ ๊ฒ์ฌํฉ๋๋ค. ์ด๋ ํธ๋์คํผ ํผ๋๋ฐฑ ํ๋ก์ธ์ค์ ๋ํ ์ ์ฉํ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
- ์ ฐ์ด๋ ๋จ์ํ: ๋ช ๊ฐ์ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์๋ง ์ถ๋ ฅํ๋ ๊ฐ๋จํ ์ ์ ์ ฐ์ด๋๋ก ์์ํฉ๋๋ค. ๊ฐ ๋จ๊ณ๋ฅผ ํ์ธํ ๋๋ง๋ค ๋ณต์ก์ฑ์ ์ ์ฐจ์ ์ผ๋ก ์ถ๊ฐํฉ๋๋ค.
- ๋ฐฐ๋ฆฌ์ด๋ง ์์ ํ์ธ: `varyings` ๋ฐฐ์ด์ ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์ ์์๊ฐ ์ ์ ์ ฐ์ด๋์์ ๊ธฐ๋ก๋๋ ์์ ๋ฐ ๋ฒํผ ๋ฐ์ธ๋ฉ ์ธ๋ฑ์ค์ ์ผ์นํ๋์ง ๋ค์ ํ์ธํฉ๋๋ค.
- ์ต์ ํ ๋นํ์ฑํ: ๋๋ฒ๊น ์ ๋ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ ฐ์ด๋ ์ต์ ํ๋ฅผ ์ผ์์ ์ผ๋ก ๋นํ์ฑํํฉ๋๋ค.
ํธํ์ฑ ๋ฐ ํ์ฅ
ํธ๋์คํผ ํผ๋๋ฐฑ์ WebGL 2 ๋ฐ OpenGL ES 3.0 ์ด์์์ ์ง์๋ฉ๋๋ค. WebGL 1์์ OES_transform_feedback ํ์ฅ์ ์ ์ฌํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ WebGL 2 ๊ตฌํ์ ๋ ํจ์จ์ ์ด๊ณ ๊ธฐ๋ฅ์ด ํ๋ถํฉ๋๋ค.
๋ค์์ ์ฌ์ฉํ์ฌ ํ์ฅ ์ง์์ ํ์ธํ์ญ์์ค.
const transformFeedbackExtension = gl.getExtension('OES_transform_feedback');
if (transformFeedbackExtension) {
// ํ์ฅ ์ฌ์ฉ
}
๊ฒฐ๋ก
WebGL ํธ๋์คํผ ํผ๋๋ฐฑ์ GPU์์ ์ง์ ์ ์ ์์ฑ ๋ฐ์ดํฐ๋ฅผ ์บก์ฒํ๋ ๊ฐ๋ ฅํ ๊ธฐ์ ์ ๋๋ค. ๋ฐฐ๋ฆฌ์ด๋ง ๋ณ์, ๋ฒํผ ๊ฐ์ฒด ๋ฐ ํธ๋์คํผ ํผ๋๋ฐฑ ๊ฐ์ฒด์ ๊ฐ๋ ์ ์ดํดํจ์ผ๋ก์จ ์ด ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๊ณ ๊ธ ๋ ๋๋ง ํจ๊ณผ๋ฅผ ๋ง๋ค๊ณ ์ง์ค๋ฉํธ๋ฆฌ ์ฒ๋ฆฌ ์์ ์ ์ํํ๊ณ WebGL ์ ํ๋ฆฌ์ผ์ด์ ์ ์ต์ ํํ ์ ์์ต๋๋ค. ํธ๋์คํผ ํผ๋๋ฐฑ์ ๊ตฌํํ ๋ ๋ฐ์ดํฐ ์ ๋ ฌ, ๋ฒํผ ํฌ๊ธฐ ๋ฐ ์ฑ๋ฅ ์ํฅ์ ์ ์คํ๊ฒ ๊ณ ๋ คํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค. ์ ์คํ ๊ณํ ๋ฐ ๋๋ฒ๊น ์ ํตํด ์ด ๊ท์คํ WebGL ๊ธฐ๋ฅ์ ์ ์ฌ๋ ฅ์ ์ต๋ํ ํ์ฉํ ์ ์์ต๋๋ค.