首页 > 解决方案 > 没有从 THREE.js/GLSL 代码中得到预期结果

问题描述

为这个模糊的问题道歉,但我不知道该如何表达。我正在尝试编写一些产生圆形渐变的 THREE.js/GLSL 代码(对于一些 SDF 的东西)。使用下面的代码,我希望看到平面上的渐变,但平面仍然是白色的,上面没有其他渲染。谁能告诉我哪里出错了?

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My first three.js app</title>
        <style>
            body { margin: 0; }
            canvas { width: 100%; height: 100% }
        </style>
    </head>
    <body>
        <script type="x-shader/x-vertex" id="sdfVS">
            varying vec2 vUv; // pass the uv coordinates of each pixel to the frag shader

            void main() {
              vUv = uv;
              gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
        </script>
        <script type="x-shader/x-fragment" id="sdfFS">
            precision mediump float;
            uniform vec2 u_resolution;
            varying vec2 vUv;

            float circle(vec2 pos, float radius)
            {
                return distance(pos, vec2(radius));
            }

            void main()
            {
                vec2 pos = (gl_FragCoord.xy / vUv) * 2.0 - 1.0;
                float circle1 = circle(pos, 0.5);
                vec3 color = vec3(circle1);
                gl_FragColor = vec4(color, 1.0);
            }
        </script>
        <script src="../../js/three.min.js"></script>
        <script>
            var scene, camera, renderer, aspect, geometry, material, plane;
            var container;
            var frustumSize = 2;

            init();
            animate();

            function init() {
                container = document.createElement( 'div' );
                document.body.appendChild( container );

                scene = new THREE.Scene();
                scene.background = new THREE.Color(0x0000ff);

                aspect = window.innerWidth / window.innerHeight;
                camera = new THREE.OrthographicCamera( 0.5 * frustumSize * aspect / - 2, 0.5 * frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 0.1, 1 );
                cameraOrthoHelper = new THREE.CameraHelper( camera );
                scene.add( cameraOrthoHelper );

                var width = 1;
                var height = 1;
                geometry = new THREE.PlaneGeometry(width, height);

                material = new THREE.ShaderMaterial( {
                    vertexShader: document.getElementById('sdfVS').textContent,
                    fragmentShader: document.getElementById('sdfFS').textContent,
                    side: THREE.DoubleSide
                } );

                plane = new THREE.Mesh( geometry, material );
                plane.rotation.x = 0;
                plane.rotation.y = THREE.Math.degToRad( -90 );
                plane.rotation.z = 0;
                scene.add( plane )

                renderer = new THREE.WebGLRenderer();
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                container.appendChild( renderer.domElement );

                window.addEventListener( 'resize', onWindowResize, false );
            }

            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize( window.innerWidth, window.innerHeight );
            }

            function animate() {
                requestAnimationFrame( animate );
                render();
            }

            function render() {
                camera.position.x = -1;
                camera.position.y = 0;
                camera.position.z = 0;
                camera.lookAt( scene.position );
                camera.updateMatrixWorld();
                renderer.render( scene, camera );
            }
        </script>
    </body>
</html>

标签: three.jsglslshader

解决方案


无法获取此行:

vec2 pos = (gl_FragCoord.xy / vUv) * 2.0 - 1.0;

好像你想计算uv坐标,但如果是这样,那么你已经有了 uvs(传入vUv)。

作为一种选择,您可以这样做:

var scene, camera, renderer, aspect, geometry, material, plane;
var container;
var clock = new THREE.Clock();
var frustumSize = 2;

init();
animate();

function init() {
  container = document.createElement('div');
  document.body.appendChild(container);

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x0000ff);

  aspect = window.innerWidth / window.innerHeight;
  camera = new THREE.OrthographicCamera(0.5 * frustumSize * aspect / -2, 0.5 * frustumSize * aspect / 2, frustumSize / 2, frustumSize / -2, 0.1, 1);
  cameraOrthoHelper = new THREE.CameraHelper(camera);
  scene.add(cameraOrthoHelper);

  var width = 1;
  var height = 1;
  geometry = new THREE.PlaneGeometry(width, height);

  material = new THREE.ShaderMaterial({
  	uniforms: {time: {value: 0}},
    vertexShader: document.getElementById('sdfVS').textContent,
    fragmentShader: document.getElementById('sdfFS').textContent,
    side: THREE.DoubleSide
  });

  plane = new THREE.Mesh(geometry, material);
  plane.rotation.x = 0;
  plane.rotation.y = THREE.Math.degToRad(-90);
  plane.rotation.z = 0;
  scene.add(plane)

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);

  window.addEventListener('resize', onWindowResize, false);
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  camera.position.x = -1;
  camera.position.y = 0;
  camera.position.z = 0;
  camera.lookAt(scene.position);
  camera.updateMatrixWorld();
  var t = clock.getElapsedTime();
  material.uniforms.time.value = t;
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script type="x-shader/x-vertex" id="sdfVS">
  varying vec2 vUv; // pass the uv coordinates of each pixel to the frag shader

  void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  }
</script>
<script type="x-shader/x-fragment" id="sdfFS">
  precision mediump float;

  uniform float time;
  uniform vec2 u_resolution;
  varying vec2 vUv;

  float circle(vec2 uv, vec2 pos, float radius) {
    return smoothstep(radius, 0., length(uv - pos));
  }

  void main()
  {
    vec2 uv = vUv * 2. - 1.;
    vec2 pos = vec2(cos(time), sin(time));
    float circle1 = circle(uv, pos, 1.0);
    vec3 color = vec3(circle1);
    gl_FragColor = vec4(color, 1.0);
  }
</script>


推荐阅读