개발 · 컴퓨터공학 / / 2024. 9. 30. 20:20

three.js GPGPU compute shader

728x90
반응형

 

three.js GPUComputationRenderer

 

three.js GPGPU - GPUComputationRenderer 사용하기

https://medium.com/@p5js/threejs-%EC%97%90%EC%84%9C-gpgpu-%EC%82%AC%EC%9A%A9-01-be4090b8e3a4 Threejs 에서 GPGPU 사용 01많이들 사용하지만 한글로된 자료가 부족해서 적어보는..medium.com이 포스팅을 이어서 작업해보자. 

like-grapejuice.tistory.com

위 포스팅에서 simulation fragment 라는 shader를 사용했었다.

이게 vertex shader를 수행하기 전에 사전에 처리되는 compute shader라고 보면

GPGPU를 사용하기에 있어서 충분한 shader구성이다.

 

compute shader라는 것은 렌더링 파이프라인에서 명확히 위치가 있는게 아니라 계산을 위해 중간에 끼워넣는 것이다. 

 

각 shader 살펴보기 

차례대로 shader를 살펴보자.

//simFragment
void main() {
    vec2 vUv = gl_FragCoord.xy / resolution.xy;
    vec2 position = texture2D( uCurrentPosition, vUv ).xy;

    position.x += 0.00001;
    
    gl_FragColor = vec4( position, 0.0, 1.0);
}

simFragment에는 gpuComputationRenderer를 정의할 때 만든 uCurrentPosition 변수에 텍스처가 하나 들어간다.

이렇게 텍스처에 들어가는 값을 가진 변수는 sampler라고 한다.

 

sampler와 현재 좌표 gl_FragCoord를 uv로 가져와서 texture를 만들고,

텍스처의 xy값으로 position을 정의한다.

 

즉, 정리하면 현재 좌표 정보를 가지고 텍스처를 만들어서

(텍스처를 만들 때 밖에서 만들었던 uCurrentPosition을 sampler로 들고온다)

x값을 증가시킨 후 color값으로 내보낸다.

 

uniform sampler2D uTexture;

//vertexshader
void main()
{
    vec3 newpos = position;
    vec4 color = texture2D(uTexture, uv);

    newpos.x += color.x;

    vec4 mvPosition = modelViewMatrix * vec4(newpos, 1.0);
    gl_PointSize = 10.0 / -mvPosition.z;
    gl_Position = projectionMatrix * mvPosition;
}

위에 simulation fragment에서 output으로 내보낸 color값을

texture 형태로 vertex shader로 전달한다.

 

  gpuCompute.compute();
  material.uniforms.uTexture.value = gpuCompute.getCurrentRenderTarget(positionVariable).texture;
  console.log(positionVariable)

아까 simulation fragment을 gpu에서 계산시키고,

그 결과 텍스처 sampler를 uniform변수에 담아서 vertex shader로 가져오고

가져온 sampler를 현재 uv에 맞게 texture에 담아 color값으로 사용한다.

 

여기서 three.js glsl의 특징으로

attribute 중 position과 uv는 현재 vertex에서의 position과 uv를 자동으로 uniform으로 제공한다. 

(그 외에도 modelViewMatrix, projectionMatrix 도 three.js에서 제공하는 기본 uniform 변수이다)

 

new position에 color를 더해서 x좌표 이동을 반영하고, 

model view projection 과정을 수행한다.

 

//fragmentshader
void main()
{
    gl_FragColor = vec4(1.0,1.0,1.0,1.0);
}

최종 pixel color는 변함없다. 

 

정리

정리하자면, GPUComputationRenderer에서는 fragment를 추가로 사용해서 compute shader의 역할을 수행하고

 

미리 연산한 texture 값을 vertex shader에 sampler로 전달함으로써,

compute shader의 결과를 vertex shader로 전달하는 것이다.

 

지금은 단순히 현재 pixel 좌표에서 이동한 결과를 계산하여 반영하였지만, 

이제 유체 시뮬레이션을 여기에 구현해보자. 

728x90
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유