Луч, идущий с фрагментным шейдером, кажется странным - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь провести несколько экспериментов рендеринга 3d-сферы с использованием three.jsЦель эксперимента:

«Можем ли мы визуализировать трехмерную сферу с заданными мировыми координатами сферы (x,y,z) и радиусом r, используя лучевую метку?»

Эксперимент показался удачнымну как ниже.works well. Левый красный кружок представляет собой сферу на основе three.js и хорошо визуализируется в перспективной камере.Правый выводится с помощью raymarching с единообразными переменными, такими как

uniforms: {
    x: { value: -testSphere.position.x }, // just for comparing left and right
    y: { value: testSphere.position.y },
    z: { value: testSphere.position.z },
    r: { value: 100 }, //fixed but can be variable
    u_resolution: {
      type: "v2",
      value: new THREE.Vector2(SCREEN_WIDTH, SCREEN_HEIGHT)
    },
    u_pixel_ratio: {
      type: "float",
      value: window.devicePixelRatio
    },
    campos: {
      type: "v3",
      value: camPos // in my case, it was (0, 0, 1000)
    }
  }

А также, для правильной обработки события изменения размера окна пользователя, прикрепляется обработчик событий, подобный этому.

function onWindowResize(event) {
    SCREEN_WIDTH = window.innerWidth;
    SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN;
    camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
    camera.updateProjectionMatrix();
    renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    howBackPlane.material.uniforms.u_resolution.value = new THREE.Vector2(
        SCREEN_WIDTH, 
        SCREEN_HEIGHT); // howBackPlane is plane mesh for draw fragment shader of right red sphere.
}

Однако, когдаЯ изменяю размер окна по горизонтали или вертикали, кажется, что правое окно не отображается так, как я ожидал.

Изменение размера по горизонтали (уменьшается) Resize horizontally(get smaller) Изменение размера по вертикали (увеличивается) Resize vertically(get larger)

Что еще хуже, каждый раз, когда я обновляю свою страницу любого размера, она возвращается к нормальной (работает правильно).Я даже не знаю, почему тот, у которого three.js работает идеально, а почему не мой.Как сделать так, чтобы сфера отображалась как three.js one?

Вот мой код вершинного шейдера и фрагментного шейдера howBackPlane.

//vertex shader
    void main(){
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }

//fragment shader
    uniform vec2 u_resolution;
    uniform float u_pixel_ratio;
    uniform vec3 campos;
    uniform float x;
    uniform float y;
    uniform float z;
    uniform float r;

    mat3 calcLookAtMatrix( in vec3 ro, in vec3 ta)
    {
        vec3 ww = normalize( ta - ro );
        vec3 uu = normalize( cross(ww,vec3(0.0,1.0,0.0) ) );
        vec3 vv = normalize( cross(uu,ww));
        return mat3( uu, vv, ww );
    }

    float sdSphere( vec3 p, float s )
    {
      return length(p - vec3(x, y, z))-s;
    }

    float calcIntersection( in vec3 ro, in vec3 rd )
    {
      const float maxd = 20000.0;
      const float precis = 0.01;
        float h = precis*2.0;
        float t = 0.0;
      float res = -1.0;
        for( int i=0; i<150; i++ )
        {
            if( h<precis||t>maxd ) break;
            h = sdSphere( ro+rd*t , r);
            t += h;
        }

        if( t<maxd ) res = t;
        return res;
    }

    void main(){
      vec3 camtar = vec3(0.0, 0.0, 0.0);
      mat3 camMat = calcLookAtMatrix( campos, camtar );
      vec2 p = -1.0 + 2.0 * (gl_FragCoord.xy/u_pixel_ratio) / (u_resolution.xy);
      p.x *= u_resolution.x/u_resolution.y;

      vec3 camdir = normalize(camMat * vec3(p, 1.0/tan(radians(45.0/2.0)))); // fov of camera is 45 deg in this app.
      float dist = calcIntersection(campos, camdir);
      if (dist != -1.0) {

        vec3 col = vec3(0.0);
        vec3 pos = campos + dist * camdir;

        col += vec3(pos);
        gl_FragColor = vec4(vec3(1.0, 0.0, 0.0), 1.0);
      }else{
        gl_FragColor = vec4(0.0);
      }

    }

Вы можете увидеть ресурс лучевого марширования, на который я ссылался здесь.

...