Извиняюсь за неопределенный вопрос, но я не был уверен, как это сформулировать. Я пытаюсь написать код 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>
1
benjia

1 ответ

Не могу получить эту строку:

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>
58573184