Three.js Chapter 4 section 29 Raging sea

황상진·2024년 11월 16일
0

Three.js

목록 보기
15/15
post-thumbnail

Raging sea

Base

  • ShaderMaterial 설정
  • vertex Shader 설정
  • fragment Shader 설정
void main(){
    vec4 modelPosition = modelMatrix * vec4(position,1.0);
    vec4 viewPosition = viewMatrix * modelPosition;
    vec4 pojectedPosition = projectionMatrix * viewPosition;
    gl_Position = pojectedPosition;
}


void main(){
    gl_FragColor = vec4(0.5,0.8,1.0,1.0);
}

Big waves

Elevation

sin 함수를 활용해서 wave 생성

  • uniform에서 변수를 활용하여 sin 값 조정
// Material
const waterMaterial = new THREE.ShaderMaterial({
  vertexShader: waterVertexShader,
  fragmentShader: waterFragmentShader,
  uniforms: {
    uBigWavesElevation: { value: 0.2 },
  },
});
uniform float uBigWavesElevation;

void main(){
    vec4 modelPosition = modelMatrix * vec4(position,1.0);
    float elevation = sin(modelPosition.x) * uBigWavesElevation;
    modelPosition.y =elevation;

    vec4 viewPosition = viewMatrix * modelPosition;
    vec4 pojectedPosition = projectionMatrix * viewPosition;
    gl_Position = pojectedPosition;
}

Frequency

  • 위 코드는 x축만 sin을 추가해준 것이다.
  • z축도 sin함수를 적용하자
  • x축과 z축에 물결의 빈도를 높여보자
// Material
const waterMaterial = new THREE.ShaderMaterial({
  vertexShader: waterVertexShader,
  fragmentShader: waterFragmentShader,
  uniforms: {
    uBigWavesElevation: { value: 0.2 },
    uBigWavesFrequency: { value: new THREE.Vector2(4, 1.5) },
  },
});
uniform float uBigWavesElevation;
uniform vec2 uBigWavesFrequency;

void main(){
    vec4 modelPosition = modelMatrix * vec4(position,1.0);

    //Elevation
    float elevation = sin(modelPosition.x * uBigWavesFrequency.x) * 
                      sin(modelPosition.z* uBigWavesFrequency.y) * 
                      uBigWavesElevation;
    
    modelPosition.y += elevation;

    vec4 viewPosition = viewMatrix * modelPosition;
    vec4 pojectedPosition = projectionMatrix * viewPosition;
    gl_Position = pojectedPosition;
}

주의 할 점

  • three.js의 경우 오른손 좌표계를 사용한다.
  • 그러나 vector2의 경우 x,y로 표시한다.
  • 그러므로 three.js 상의 z와 vector2 상의 y를 같이 활용하는 경우가 발생한다.

Animate

  • elapsed Time을 활용해서 파도에 offset을 추가해서 움직이도록 만들어보자
  • Time의 속도를 조절하기 위해서 변수를 추가한다.
// Material
const waterMaterial = new THREE.ShaderMaterial({
  vertexShader: waterVertexShader,
  fragmentShader: waterFragmentShader,
  uniforms: {
    uTime: { value: 0 },
    uBigWavesElevation: { value: 0.2 },
    uBigWavesFrequency: { value: new THREE.Vector2(4, 1.5) },
    uBigWavesSpeed: { value: 0.75 },
  },
});

const tick = () => {
  const elapsedTime = clock.getElapsedTime();

  // Update Water
  waterMaterial.uniforms.uTime.value = elapsedTime;
  ...
}
uniform float uTime;
uniform float uBigWavesElevation;
uniform vec2 uBigWavesFrequency;
uniform float uBigWavesSpeed;![](https://velog.velcdn.com/images/magpies1221/post/8368d488-039e-43b0-bdbf-081ae05aabc9/image.gif)


void main(){
    vec4 modelPosition = modelMatrix * vec4(position,1.0);

    //Elevation
    float elevation = sin(modelPosition.x * uBigWavesFrequency.x + uTime *uBigWavesSpeed) * 
                      sin(modelPosition.z* uBigWavesFrequency.y + uTime * uBigWavesSpeed) * 
                      uBigWavesElevation;
	...
}

Colors

  • 두개의 색상을 활용해서 표현
  • VertexShader에서 사용한 Elevation을 활용한다.
const waterMaterial = new THREE.ShaderMaterial({
    vertexShader: waterVertexShader,
    fragmentShader: waterFragmentShader,
    uniforms:
    {
        // ...
        uColorOffset: { value: 0.08 },
        uColorMultiplier: { value: 5 }
    } 
})
uniform vec3 uDepthColor;
uniform vec3 uSurfaceColor;
uniform float uColorOffset;
uniform float uColorMultiplier;

varying float vElevation;

void main()
{
    float mixStrength = (vElevation + uColorOffset) * uColorMultiplier;
    vec3 color = mix(uDepthColor, uSurfaceColor, mixStrength);
    
    gl_FragColor = vec4(color, 1.0);
    #include <colorspace_fragment>
}

Small waves

  • perlin noise를 활용해서 wave생성
  • time 변수를 활용해서 애니메이션 추가
  • offset과 frquency 변수로 변경
  • 보다 사실적으로 보이기 위해서 반복문으로 perlin noise 적용

perlin noise shader 코드
https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83

const waterMaterial = new THREE.ShaderMaterial({
    vertexShader: waterVertexShader,
    fragmentShader: waterFragmentShader,
    uniforms:
    {
        // ...

        uSmallWavesElevation: { value: 0.15 },
        uSmallWavesFrequency: { value: 3 },
        uSmallWavesSpeed: { value: 0.2 },
        uSmallIterations: { value: 4 },

        // ...
    }
})
uniform float uSmallWavesElevation;
uniform float uSmallWavesFrequency;
uniform float uSmallWavesSpeed;
uniform float uSmallIterations;

// ...

void main()
{
    // ...

    for(float i = 1.0; i <= uSmall![](https://velog.velcdn.com/images/magpies1221/post/e8a94caa-2dc5-4c33-9f8b-ee7b4ed5cf4c/image.mp4)
![업로드중..](blob:https://velog.io/6f5d0aae-aa1a-40d5-86a4-f6ae231a958d)
Iterations; i++)
    {
        elevation -= abs(cnoise(vec3(modelPosition.xz * uSmallWavesFrequency * i, uTime * uSmallWavesSpeed)) * uSmallWavesElevation / i);
    }

    // ...
}

Result

업로드중..

profile
Web FrontEnd Developer

0개의 댓글

관련 채용 정보