Three.js는 브라우저에서 3D 그래픽을 생성하는 데 널리 사용되는 JavaScript 라이브러리입니다. 대화형 시각화 및 게임을 만드는 데 자주 사용됩니다. 3D 그래픽의 과제 중 하나는 구름이나 연기와 같이 불투명하지 않은 개체를 렌더링하는 것입니다. 이러한 물체는 빛을 통과시켜 더욱 부드럽고 사실적인 모습을 연출할 수 있습니다.
이 경우 목표는 지구 표현에 '대기' 효과를 추가하는 것입니다. 대기는 지구를 둘러싸고 빛을 산란시키는 반투명 레이어가 되어 더욱 사실적인 모습을 제공합니다.
이 효과를 얻기 위해 각 픽셀의 색상을 계산하는 프래그먼트 셰이더를 만듭니다. 대기에서의 위치와 광원의 방향에 따라 대기에서. 프래그먼트 셰이더는 "대기 산란"이라는 기술을 사용하여 빛이 대기의 입자에 의해 산란되는 방식을 시뮬레이션합니다.
프래그먼트 셰이더 코드는 다음과 같습니다.
#ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif uniform vec3 lightDirection; uniform sampler2D earthTexture; varying vec2 vUv; varying vec3 vNormal; void main() { // Compute the surface normal at this position vec3 normal = normalize(vNormal); // Compute the direction from this point to the light source vec3 lightDir = normalize(lightDirection); // Compute the amount of light that is scattered in this direction float scattering = dot(normal, lightDir); // Compute the color of the atmosphere at this position vec3 color = texture2D(earthTexture, vUv).rgb * scattering; // Output the color gl_FragColor = vec4(color, 1.0); }
이 프래그먼트 셰이더는 여러 입력을 받습니다:
프래그먼트 셰이더는 먼저 현재 픽셀의 표면 법선을 계산합니다. 그런 다음 현재 픽셀에서 광원까지의 방향을 계산합니다. 이 두 값은 픽셀 방향으로 산란되는 빛의 양을 계산하는 데 사용됩니다.
그런 다음 프래그먼트 셰이더는 지구 텍스처의 색상에 다음을 곱하여 현재 픽셀의 대기 색상을 계산합니다. 산란의 양. 결과 색상은 프래그먼트 색상으로 출력됩니다.
이 프래그먼트 셰이더를 사용하려면 이를 사용하는 머티리얼을 생성해야 합니다. 다음은 대기 산란 조각 셰이더를 사용하는 재료의 예입니다.
const material = new THREE.ShaderMaterial({ fragmentShader: ` #ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif uniform vec3 lightDirection; uniform sampler2D earthTexture; varying vec2 vUv; varying vec3 vNormal; void main() { vec3 normal = normalize(vNormal); vec3 lightDir = normalize(lightDirection); float scattering = dot(normal, lightDir); vec3 color = texture2D(earthTexture, vUv).rgb * scattering; gl_FragColor = vec4(color, 1.0); } `, uniforms: { lightDirection: { value: new THREE.Vector3(0, 1, 0) }, earthTexture: { value: new THREE.TextureLoader().load('earth.jpg') } } });
이 재료는 두 가지 유니폼을 사용합니다.
재료는 각 방향으로 산란되는 빛의 양을 계산하기 위한 lightDirection 균일성. EarthTexture 유니폼을 사용하여 지구의 표면을 표현합니다.
이 머티리얼을 사용하려면 메시를 생성하여 머티리얼에 할당해야 합니다. 다음은 메쉬를 생성하고 이를 재질에 할당하는 방법에 대한 예입니다.
const geometry = new THREE.SphereGeometry(10, 32, 32); const material = new THREE.ShaderMaterial({ fragmentShader: ` #ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif uniform vec3 lightDirection; uniform sampler2D earthTexture; varying vec2 vUv; varying vec3 vNormal; void main() { vec3 normal = normalize(vNormal); vec3 lightDir = normalize(lightDirection); float scattering = dot(normal, lightDir); vec3 color = texture2D(earthTexture, vUv).rgb * scattering; gl_FragColor = vec4(color, 1.0); } `, uniforms: { lightDirection: { value: new THREE.Vector3(0, 1, 0) }, earthTexture: { value: new THREE.TextureLoader().load('earth.jpg') } } }); const mesh = new THREE.Mesh(geometry, material);
이 코드는 반경 10, 세그먼트 32개, 링 32개의 구 형상을 생성합니다. 그런 다음 대기 산란 조각 셰이더를 사용하는 재료를 만듭니다. 마지막으로 메시를 생성하여 머티리얼에 할당합니다.
메시가 생성되면 장면에 추가할 수 있습니다. 다음은 장면에 메시를 추가하는 방법에 대한 예입니다.
#ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif uniform vec3 lightDirection; uniform sampler2D earthTexture; varying vec2 vUv; varying vec3 vNormal; void main() { // Compute the surface normal at this position vec3 normal = normalize(vNormal); // Compute the direction from this point to the light source vec3 lightDir = normalize(lightDirection); // Compute the amount of light that is scattered in this direction float scattering = dot(normal, lightDir); // Compute the color of the atmosphere at this position vec3 color = texture2D(earthTexture, vUv).rgb * scattering; // Output the color gl_FragColor = vec4(color, 1.0); }
이 코드는 장면에 메시를 추가합니다. 이제 메시는 대기 산란 조각 셰이더를 사용하여 렌더링됩니다. 그 결과 지구를 둘러싸는 반투명 대기가 탄생하게 됩니다.
위 내용은 Three.js와 사용자 정의 프래그먼트 셰이더를 사용하여 3D 지구 모델 주변의 현실적인 분위기를 어떻게 시뮬레이션할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!