【问题标题】:THREE.JS | GLSL How to split canvas texture to multiple planes三.JS | GLSL如何将画布纹理分割到多个平面
【发布时间】:2020-08-27 02:25:45
【问题描述】:

我有一个小演示,我在 1024x1024 区域内堆叠了多个平面。 它均匀分割 1024x1024 动画画布纹理的任务,所以我会得到以下结果:

不是这个:

所以,我必须以某种方式将我需要裁剪的画布纹理的哪一部分传递给他们的着色器材质。而且我不知道该怎么做。

这里附上当前代码。

下面的答案很好,但我必须对这些飞机使用 glsl,所以这个解决方案可以适合其他任务,而不是我的。

    
var renderer, scene, camera, controls, glslMaterial, uniforms, canvas, ctx, markupTexture, t = 0.0;
  
inits();
    
function inits(){

    canvas = document.createElement("canvas")

    canvas.width = 1024 * 2;
    canvas.height = 1024 * 2;

    ctx = canvas.getContext("2d");
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "#00FFFF";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    markupTexture = new THREE.CanvasTexture(canvas);
    //markupTexture.flipX = false;
    //markupTexture.flipY = false;
    
    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setClearColor(0x000000);
    document.body.appendChild( renderer.domElement );
    
    scene = new THREE.Scene();
    
    var light = new THREE.HemisphereLight( 0xFFFFFF, 0x080820, 2.0 );
    scene.add( light );
    
    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5120 );
    camera.position.set(-200, 400, 400);
    
    controls = new THREE.OrbitControls(camera, renderer.domElement);
    
    var markupGeometry = new THREE.PlaneGeometry(1024, 1024, 64, 64);
    var markupPlane = new THREE.Mesh(markupGeometry, new THREE.MeshBasicMaterial({ color: 0xFFFFFF, map: markupTexture, side: THREE.DoubleSide }));
    markupPlane.rotation.set(-Math.PI / 2, 0, 0);
    markupPlane.position.set(0, 1, 0);
    //scene.add(markupPlane);
    
    var uniforms = {
        
        markup: { type: 't', value: markupTexture }
        
    };

    glslMaterial = new THREE.ShaderMaterial({
        
        uniforms: uniforms,
        vertexShader: document.getElementById('vertexShader').textContent,
        fragmentShader: document.getElementById('fragmentShader').textContent
        //side: new THREE.DoubleSide
        
    });
    
    var geometry = new THREE.PlaneGeometry(512, 512, 64, 64);
    var plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane0";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(256, 0, -256)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane1";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(384, 0, 128)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane2";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(128, 0, 128)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane3";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(128, 0, 384)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane4";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(384, 0, 384)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(512, 512, 64, 64);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane5";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(-256, 0, 256)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane6";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(-384, 0, -128)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane7";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(-128, 0, -128)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane8";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(-128, 0, -384)
    scene.add(plane);
    
    geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
    plane = new THREE.Mesh(geometry, glslMaterial);
    plane.name = "plane9";
    plane.rotation.set(-Math.PI / 2, 0, 0);
    plane.position.set(-384, 0, -384)
    scene.add(plane);
    
    window.addEventListener( "resize", onWindowResize, false );
    
    animate();
    
}
    
function onWindowResize() {
    
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
      
}

    
function animate() {
    
    ctx.imageSmoothingEnabled = true;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "#FFFF00";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    ctx.beginPath();
    ctx.arc(1024, 1024, 640, 0, 2 * Math.PI);
    ctx.strokeStyle = "#FF00FF";
    ctx.lineWidth = 16.0;
    ctx.stroke();
    
    ctx.beginPath();
    ctx.moveTo(1024, 1024);
    ctx.arc(1024, 1024, 640, t - Math.PI / 8, t + Math.PI / 8, false);
    ctx.lineTo(1024, 1024);
    ctx.fillStyle = "#FF00FF";
    ctx.fill();
    
    controls.update();
    requestAnimationFrame( animate );
    renderer.render( scene, camera );

    for(var i = 0; i < 10; i++){
        
        scene.getObjectByName("plane" + i).material.uniforms.markup.needsUpdate = true;
        
    }
    //glslMaterial.uniforms.markup.needsUpdate = true;
    markupTexture.needsUpdate = true;
    
    t += 0.05;

}

    
body { margin: 0px; } 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title></title>

    <script src="https://unpkg.com/three@0.85.0/build/three.min.js"></script>
    <script src="https://unpkg.com/three@0.85.0/examples/js/controls/OrbitControls.js"></script>

</head>
<body>

<script id="vertexShader" type="x-shader/x-vertex">

    varying vec2 vUv;

    void main() {

        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix *  vec4(position,1.0);

    }
    
</script>
    
<script id="fragmentShader" type="x-shader/x-fragment">

    uniform sampler2D markup;

    varying vec2 vUv;

    void main() {
    
        gl_FragColor = texture2D(markup, vUv);
        
    }
    
</script>

    
</body>
</html>

【问题讨论】:

    标签: three.js glsl textures crop plane


    【解决方案1】:

    您不需要自定义着色器。您只需要为每个平面设置纹理坐标即可。

    这是一个缩放和偏移纹理坐标的函数

    function offsetUVs(geometry, offU, offV, scaleU, scaleV) {
      const off = new THREE.Vector2(offU, offV);
      const scale = new THREE.Vector2(scaleU, scaleV);
      for(const uvs of geometry.faceVertexUvs[0]) {
        for (const uv of uvs) {
          uv.multiply(scale);
          uv.add(off);
        }
      }
    }
    

    如果将比例设置为 0.25、0.25,则该平面上将出现 16 分之一的纹理(就像纹理被划分为 4x4 网格一样)

    偏移量将移动纹理,其中 1 是纹理的全长,0.5 是长度的一半,0.25 是长度的四分之一

    var renderer, scene, camera, controls, glslMaterial, uniforms, canvas, ctx, markupTexture, t = 0.0;
      
    inits();
        
    function inits(){
    
        canvas = document.createElement("canvas")
    
        canvas.width = 1024 * 2;
        canvas.height = 1024 * 2;
    
        ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "#00FFFF";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        markupTexture = new THREE.CanvasTexture(canvas);
        //markupTexture.flipX = false;
        //markupTexture.flipY = false;
        
        renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.setClearColor(0x000000);
        document.body.appendChild( renderer.domElement );
        
        scene = new THREE.Scene();
        
        var light = new THREE.HemisphereLight( 0xFFFFFF, 0x080820, 2.0 );
        scene.add( light );
        
        camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5120 );
        camera.position.set(-200, 400, 400);
        
        controls = new THREE.OrbitControls(camera, renderer.domElement);
        
        var markupGeometry = new THREE.PlaneGeometry(1024, 1024, 64, 64);
        var markupPlane = new THREE.Mesh(markupGeometry, new THREE.MeshBasicMaterial({ color: 0xFFFFFF, map: markupTexture, side: THREE.DoubleSide }));
        markupPlane.rotation.set(-Math.PI / 2, 0, 0);
        markupPlane.position.set(0, 1, 0);
        //scene.add(markupPlane);
        
    
        /*glslMaterial = new THREE.ShaderMaterial({
            
            uniforms: uniforms,
            vertexShader: document.getElementById('vertexShader').textContent,
            fragmentShader: document.getElementById('fragmentShader').textContent
            //side: new THREE.DoubleSide
            
        });
        */
        const simple = new THREE.MeshBasicMaterial({ color: 0xFFFFFF, map: markupTexture, side: THREE.DoubleSide });
        
        var geometry = new THREE.PlaneGeometry(512, 512, 64, 64);
        offsetUVs(geometry, 0.5, 0.5, 0.5, 0.5);
        var plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane0";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(256, 0, -256)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.75, 0.25, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane1";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(384, 0, 128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.5, 0.25, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane2";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(128, 0, 128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.5, 0, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane3";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(128, 0, 384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.75, 0, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane4";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(384, 0, 384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(512, 512, 64, 64);
        offsetUVs(geometry, 0, 0, 0.5, 0.5);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane5";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-256, 0, 256)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.0, 0.5, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane6";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-384, 0, -128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.25, 0.5, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane7";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-128, 0, -128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.25, 0.75, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane8";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-128, 0, -384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.0, 0.75, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, simple);
        plane.name = "plane9";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-384, 0, -384)
        scene.add(plane);
        
        window.addEventListener( "resize", onWindowResize, false );
        
        animate();
        
    }
    
    function offsetUVs(geometry, offU, offV, scaleU, scaleV) {
      const off = new THREE.Vector2(offU, offV);
      const scale = new THREE.Vector2(scaleU, scaleV);
      for(const uvs of geometry.faceVertexUvs[0]) {
        for (const uv of uvs) {
          uv.multiply(scale);
          uv.add(off);
        }
      }
    }
        
    function onWindowResize() {
        
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
          
    }
    
        
    function animate() {
        
        ctx.imageSmoothingEnabled = true;
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "#FFFF00";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        ctx.beginPath();
        ctx.arc(1024, 1024, 940, 0, 2 * Math.PI);
        ctx.strokeStyle = "#FF00FF";
        ctx.lineWidth = 16.0;
        ctx.stroke();
        
        ctx.beginPath();
        ctx.moveTo(1024, 1024);
        ctx.arc(1024, 1024, 940, t - Math.PI / 8, t + Math.PI / 8, false);
        ctx.lineTo(1024, 1024);
        ctx.fillStyle = "#FF00FF";
        ctx.fill();
        markupTexture.needsUpdate = true;
        
        controls.update();
        requestAnimationFrame( animate );
        renderer.render( scene, camera );
        
        t += 0.05;
    
    }
    body { margin: 0px; }
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
            "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <title></title>
    
        <script src="https://unpkg.com/three@0.85.0/build/three.min.js"></script>
        <script src="https://unpkg.com/three@0.85.0/examples/js/controls/OrbitControls.js"></script>
    
    </head>
    <body>
        
    </body>
    </html>

    Ps:我把圆圈变大了,所以它接触了所有的平面,否则 2 个角是纯黄色的,所以很难看出它们是否正确。

    参见this article作为几何结构的参考

    同样的解决方案也适用于您的自定义着色器

    var renderer, scene, camera, controls, glslMaterial, uniforms, canvas, ctx, markupTexture, t = 0.0;
      
    inits();
        
    function inits(){
    
        canvas = document.createElement("canvas")
    
        canvas.width = 1024 * 2;
        canvas.height = 1024 * 2;
    
        ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "#00FFFF";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        markupTexture = new THREE.CanvasTexture(canvas);
        //markupTexture.flipX = false;
        //markupTexture.flipY = false;
        
        renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.setClearColor(0x000000);
        document.body.appendChild( renderer.domElement );
        
        scene = new THREE.Scene();
        
        var light = new THREE.HemisphereLight( 0xFFFFFF, 0x080820, 2.0 );
        scene.add( light );
        
        camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5120 );
        camera.position.set(-200, 400, 400);
        
        controls = new THREE.OrbitControls(camera, renderer.domElement);
        
        var markupGeometry = new THREE.PlaneGeometry(1024, 1024, 64, 64);
        var markupPlane = new THREE.Mesh(markupGeometry, new THREE.MeshBasicMaterial({ color: 0xFFFFFF, map: markupTexture, side: THREE.DoubleSide }));
        markupPlane.rotation.set(-Math.PI / 2, 0, 0);
        markupPlane.position.set(0, 1, 0);
        //scene.add(markupPlane);
        
        var uniforms = {
            
            markup: { type: 't', value: markupTexture }
            
        };
    
        glslMaterial = new THREE.ShaderMaterial({
            
            uniforms: uniforms,
            vertexShader: document.getElementById('vertexShader').textContent,
            fragmentShader: document.getElementById('fragmentShader').textContent
            //side: new THREE.DoubleSide
            
        });
        
        var geometry = new THREE.PlaneGeometry(512, 512, 64, 64);
        offsetUVs(geometry, 0.5, 0.5, 0.5, 0.5);
        var plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane0";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(256, 0, -256)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.75, 0.25, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane1";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(384, 0, 128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.5, 0.25, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane2";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(128, 0, 128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.5, 0, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane3";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(128, 0, 384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.75, 0, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane4";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(384, 0, 384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(512, 512, 64, 64);
        offsetUVs(geometry, 0, 0, 0.5, 0.5);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane5";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-256, 0, 256)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.0, 0.5, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane6";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-384, 0, -128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.25, 0.5, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane7";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-128, 0, -128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.25, 0.75, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane8";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-128, 0, -384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        offsetUVs(geometry, 0.0, 0.75, 0.25, 0.25);
        plane = new THREE.Mesh(geometry, glslMaterial);
        plane.name = "plane9";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-384, 0, -384)
        scene.add(plane);
        
        window.addEventListener( "resize", onWindowResize, false );
        
        animate();
        
    }
    
    function offsetUVs(geometry, offU, offV, scaleU, scaleV) {
      const off = new THREE.Vector2(offU, offV);
      const scale = new THREE.Vector2(scaleU, scaleV);
      for(const uvs of geometry.faceVertexUvs[0]) {
        for (const uv of uvs) {
          uv.multiply(scale);
          uv.add(off);
        }
      }
    }
        
    function onWindowResize() {
        
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
          
    }
    
        
    function animate() {
        
        ctx.imageSmoothingEnabled = true;
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "#FFFF00";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        ctx.beginPath();
        ctx.arc(1024, 1024, 940, 0, 2 * Math.PI);
        ctx.strokeStyle = "#FF00FF";
        ctx.lineWidth = 16.0;
        ctx.stroke();
        
        ctx.beginPath();
        ctx.moveTo(1024, 1024);
        ctx.arc(1024, 1024, 940, t - Math.PI / 8, t + Math.PI / 8, false);
        ctx.lineTo(1024, 1024);
        ctx.fillStyle = "#FF00FF";
        ctx.fill();
        markupTexture.needsUpdate = true;
        
        controls.update();
        requestAnimationFrame( animate );
        renderer.render( scene, camera );
        
        t += 0.05;
    
    }
    body { margin: 0px; }
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
            "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <title></title>
    
        <script src="https://unpkg.com/three@0.85.0/build/three.min.js"></script>
        <script src="https://unpkg.com/three@0.85.0/examples/js/controls/OrbitControls.js"></script>
    <script id="vertexShader" type="x-shader/x-vertex">
    
        varying vec2 vUv;
    
        void main() {
    
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix *  vec4(position,1.0);
    
        }
        
    </script>
        
    <script id="fragmentShader" type="x-shader/x-fragment">
    
        uniform sampler2D markup;
    
        varying vec2 vUv;
    
        void main() {
        
            gl_FragColor = texture2D(markup, vUv);
            
        }
        
    </script>
    </head>
    <body>
        
    </body>
    </html>

    您也可以在着色器中进行相同的 uv 操作,但您需要为每个平面创建一个新材质,以便为每个平面传递不同的偏移和缩放。

    var renderer, scene, camera, controls, glslMaterial, uniforms, canvas, ctx, markupTexture, t = 0.0;
      
    inits();
        
    function inits(){
    
        canvas = document.createElement("canvas")
    
        canvas.width = 1024 * 2;
        canvas.height = 1024 * 2;
    
        ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "#00FFFF";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        markupTexture = new THREE.CanvasTexture(canvas);
        //markupTexture.flipX = false;
        //markupTexture.flipY = false;
        
        renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.setClearColor(0x000000);
        document.body.appendChild( renderer.domElement );
        
        scene = new THREE.Scene();
        
        var light = new THREE.HemisphereLight( 0xFFFFFF, 0x080820, 2.0 );
        scene.add( light );
        
        camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5120 );
        camera.position.set(-200, 400, 400);
        
        controls = new THREE.OrbitControls(camera, renderer.domElement);
        
        var markupGeometry = new THREE.PlaneGeometry(1024, 1024, 64, 64);
        var markupPlane = new THREE.Mesh(markupGeometry, new THREE.MeshBasicMaterial({ color: 0xFFFFFF, map: markupTexture, side: THREE.DoubleSide }));
        markupPlane.rotation.set(-Math.PI / 2, 0, 0);
        markupPlane.position.set(0, 1, 0);
        //scene.add(markupPlane);
        
        function createMaterial(offX, offY, scaleX, scaleY) {
          var uniforms = {
              uvOffset: { value: new THREE.Vector2(offX, offY) },
              uvScale: { value: new THREE.Vector2(scaleX, scaleY) },
              markup: { type: 't', value: markupTexture }
    
          };
    
          return new THREE.ShaderMaterial({
    
              uniforms: uniforms,
              vertexShader: document.getElementById('vertexShader').textContent,
              fragmentShader: document.getElementById('fragmentShader').textContent
              //side: new THREE.DoubleSide
    
          });
        }
    
        var geometry = new THREE.PlaneGeometry(512, 512, 64, 64);
        var plane = new THREE.Mesh(geometry, createMaterial(0.5, 0.5, 0.5, 0.5));
        plane.name = "plane0";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(256, 0, -256)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        plane = new THREE.Mesh(geometry, createMaterial(0.75, 0.25, 0.25, 0.25));
        plane.name = "plane1";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(384, 0, 128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        plane = new THREE.Mesh(geometry, createMaterial(0.5, 0.25, 0.25, 0.25));
        plane.name = "plane2";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(128, 0, 128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        plane = new THREE.Mesh(geometry, createMaterial(0.5, 0, 0.25, 0.25));
        plane.name = "plane3";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(128, 0, 384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        plane = new THREE.Mesh(geometry, createMaterial(0.75, 0, 0.25, 0.25));
        plane.name = "plane4";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(384, 0, 384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(512, 512, 64, 64);
        plane = new THREE.Mesh(geometry, createMaterial(0, 0, 0.5, 0.5));
        plane.name = "plane5";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-256, 0, 256)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        plane = new THREE.Mesh(geometry, createMaterial(0.0, 0.5, 0.25, 0.25));
        plane.name = "plane6";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-384, 0, -128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        plane = new THREE.Mesh(geometry, createMaterial(0.25, 0.5, 0.25, 0.25));
        plane.name = "plane7";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-128, 0, -128)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        plane = new THREE.Mesh(geometry, createMaterial(0.25, 0.75, 0.25, 0.25));
        plane.name = "plane8";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-128, 0, -384)
        scene.add(plane);
        
        geometry = new THREE.PlaneGeometry(256, 256, 32, 32);
        plane = new THREE.Mesh(geometry, createMaterial(0.0, 0.75, 0.25, 0.25));
        plane.name = "plane9";
        plane.rotation.set(-Math.PI / 2, 0, 0);
        plane.position.set(-384, 0, -384)
        scene.add(plane);
        
        window.addEventListener( "resize", onWindowResize, false );
        
        animate();
        
    }
        
    function onWindowResize() {
        
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
          
    }
    
        
    function animate() {
        
        ctx.imageSmoothingEnabled = true;
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "#FFFF00";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        ctx.beginPath();
        ctx.arc(1024, 1024, 940, 0, 2 * Math.PI);
        ctx.strokeStyle = "#FF00FF";
        ctx.lineWidth = 16.0;
        ctx.stroke();
        
        ctx.beginPath();
        ctx.moveTo(1024, 1024);
        ctx.arc(1024, 1024, 940, t - Math.PI / 8, t + Math.PI / 8, false);
        ctx.lineTo(1024, 1024);
        ctx.fillStyle = "#FF00FF";
        ctx.fill();
        
        controls.update();
        requestAnimationFrame( animate );
        renderer.render( scene, camera );
    
        markupTexture.needsUpdate = true;
        
        t += 0.05;
    
    }
    body { margin: 0px; }
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
            "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <title></title>
    
        <script src="https://unpkg.com/three@0.85.0/build/three.min.js"></script>
        <script src="https://unpkg.com/three@0.85.0/examples/js/controls/OrbitControls.js"></script>
    
    </head>
    <body>
    
    <script id="vertexShader" type="x-shader/x-vertex">
    
        varying vec2 vUv;
    
        void main() {
    
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix *  vec4(position,1.0);
    
        }
        
    </script>
        
    <script id="fragmentShader" type="x-shader/x-fragment">
    
        uniform sampler2D markup;
        uniform vec2 uvOffset;
        uniform vec2 uvScale;
    
        varying vec2 vUv;
    
        void main() {
        
            gl_FragColor = texture2D(markup, vUv * uvScale + uvOffset);
            
        }
    </script>
    
        
    </body>
    </html>

    【讨论】:

    • 我必须为其他任务使用平面着色器。
    • 该解决方案仍然可以使用您的自定义着色器。把你的着色器放回去,它会工作得很好。我唯一的观点是你表明你不需要自定义着色器来达到你要求的结果。
    猜你喜欢
    • 1970-01-01
    • 2017-01-20
    • 2020-12-03
    • 2018-04-10
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 2017-10-10
    相关资源
    最近更新 更多