레이 마칭에서 three.js의 PerspectiveCamera 사용

9666 단어 GLSLthree.jsWebGL
WebGL에서 레이마칭할 때도 three.js의 THREE.OrbitControls 등으로 카메라를 제어할 수 있으면 편리할 것이라고 생각해 조사했습니다.

먼저 결과를 보여주면 이런 느낌입니다. 위가 THEEE.OrbitControls 로 제어한 THREE.PerspectiveCamera 로 보통으로 렌더링한 것으로, 아래가 같은 카메라의 정보를 바탕으로 레이마칭으로 렌더링한 것입니다. 색상 이외는 같은 방식으로 표시됩니다.


아래에서 실제로 움직이는 것을 확인할 수 있습니다.
htps : // 오로 b에서 b. 기주 b. 이오/s개 dy-th 네. js / 라 y 마 r 찐 g-우 th th three js - 카메라. HTML

구체적으로 무엇을 하고 있는가 하면, three.js 의 PerspectiveCameara 의 정보를 레이마칭을 실시하는 쉐이더에 uniform로 건네주어, 그 정보를 기초로 레이를 생성하고 있습니다.

레이마칭을 하는 쉐이더측은 이와 같이 되어 있습니다. perspectiveCamera 함수의 설계에 대해서는 이 기사 도 참고해 주세요.

raymarch 코드(발췌)

uniform vec2 resolution;
uniform vec3 cameraPosition;
uniform vec3 cameraDirection;
uniform float cameraAspect;
uniform float cameraFov;

void perspectiveCamera(in vec2 uv, in vec3 position, in vec3 cameraDirection, in float fov, in float aspect, out vec3 origin, out vec3 dir) {
  vec2 st = uv * 2.0 - 1.0;
  float radian = fov * PI / 180.0;
  float h = tan(radian * 0.5);
  float w = h * aspect;
  vec3 right = normalize(cross(cameraDirection, vec3(0.0, 1.0, 0.0)));
  vec3 up = normalize(cross(right, cameraDirection));
  dir = normalize(right * w * st.x + up * h * st.y + cameraDirection);
  origin = position;
}

void main() {
  vec3 rayOrigin, rayDirection;
  perspectiveCamera(gl_FragCoord.xy / resolution, cameraPosition, cameraDirection, cameraFov, cameraAspect, rayOrigin, rayDirection);
  vec3 color = raymarch(rayOrigin, rayDirection);
  gl_FragColor = vec4(color, 1.0);
}

JavaScript 측에서 THREE.PerspectiveCamera 의 정보를 셰이더 측에 건네주는 부분은 이와 같이 되어 있습니다. 이 코드에서는 THREE.RawShaderMaterial의 unifoms 매개 변수로 unifom을 전달한다고 가정합니다.THREE.PerspectiveCamera#getWorldDirection#getWorldPosition 로 월드 좌표계에서의 카메라의 방향과 위치를 각각 인수에 건네준 변수에 넣어 줍니다. 이 메소드를 렌더링 그룹의 OrbitControls#update (을)를 실행한 후에 등으로 부르는 것으로 레이마칭의 쉐이더측에서도 현재의 카메라의 정보를 이용할 수 있게 됩니다.
const raymarchUniforms = {
  resolution: {value: new THREE.Vector2(window.innerWidth, window.innerHeight / 2.0)},
  cameraPosition: {value: new THREE.Vector3()},
  cameraDirection: {value: new THREE.Vector3()},
  cameraAspect: {value: camera.aspect},
  cameraFov: {value: camera.fov},
};

// called in rendering loop
camera.getWorldDirection(raymarchUniforms.cameraDirection.value);
camera.getWorldPosition(raymarchUniforms.cameraPosition.value);

좋은 웹페이지 즐겨찾기