ТРИ.JS | GLSL Использует canvas в качестве однородной текстуры шейдера

#canvas #three.js #glsl #textures

#canvas #three.js #glsl #Текстуры

Вопрос:

Я пытаюсь использовать холст в качестве однородной текстуры:

 uniforms = {
    
    canvasTexture: { type: "t", value: new THREE.Texture(canvas) }
        
};
  

тоже пробовали:

 uniforms = {
    
    canvasTexture: { type: "t", value: new THREE.CanvasTexture(canvas) }
        
};
  

Но я не вижу ничего, кроме черного экрана.

Я также пытаюсь обновить форму в animate ():

 mesh.material.uniforms.canvasTexture.needsUpdate = true;
  

Без какого-либо успеха. Есть какие-либо изменения?

  
var renderer, scene, camera, canvas, ctx, mesh, canvasTexture;
    
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
renderer.setSize( window.innerWidth, window.innerHeight );
    
camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );

scene = new THREE.Scene();

var canvas = document.createElement("canvas");
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
ctx = canvas.getContext("2d");

var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
    
uniforms = {
    
    canvasTexture: { type: "t", value: new THREE.Texture(canvas) }
        
};

var material = new THREE.ShaderMaterial( {

    uniforms: uniforms,
    vertexShader: document.getElementById( "vs-canvasTest" ).textContent,
    fragmentShader: document.getElementById( "fs-canvasTest" ).textContent,

} );

mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
    
window.addEventListener("resize", onWindowResize, false);

animate();
    
function onWindowResize() { 
    
    renderer.setSize( window.innerWidth, window.innerHeight );
    
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;
        
}
    
function animate() {
    
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
    
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "#FF0000";
    ctx.fill();
    
    mesh.material.uniforms.canvasTexture.needsUpdate = true;

}  
 body { margin: 0; }  
 <!DOCTYPE html>
<html lang="en">
<head>
    <title>Test</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">

    <script src="https://unpkg.com/three@0.106.0/build/three.min.js"></script>

</head>
<body>
    
<script id="vs-canvasTest" type="x-shader/x-vertex">

    varying vec2 vUv;

    void main() {

        vUv = uv;
        gl_Position = vec4( position, 1.0 );

    }

</script>

<script id="fs-canvasTest" type="x-shader/x-fragment">

    varying vec2 vUv;
    uniform sampler2D canvasTexture;

    void main() {

        gl_FragColor = texture2D(canvasTexture, vUv);

    }


</script>

</body>  
</html>  

Ответ №1:

Это крошечная ошибка, я тоже делаю это постоянно. Вот что у вас есть сейчас:

mesh.material.uniforms.canvasTexture.needsUpdate = true;

Вот что вам нужно:

mesh.material.uniforms.canvasTexture.value.needsUpdate = true;

Вам просто нужно .value before .needsUpdate , поэтому вы ориентируетесь на текстуру, а не на форму, которая содержит текстуру.

 var renderer, scene, camera, canvas, ctx, mesh, tex;
    
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
renderer.setSize( window.innerWidth, window.innerHeight );
    
camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );

scene = new THREE.Scene();

var canvas = document.createElement("canvas");
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
ctx = canvas.getContext("2d");

var geometry = new THREE.PlaneBufferGeometry( 2, 2 );

uniforms = {
    
    canvasTexture: { value: new THREE.Texture(canvas) }
        
};

var material = new THREE.ShaderMaterial( {

    uniforms: uniforms,
    vertexShader: document.getElementById( "vs-canvasTest" ).textContent,
    fragmentShader: document.getElementById( "fs-canvasTest" ).textContent,

} );

mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
    
window.addEventListener("resize", onWindowResize, false);

animate();
    
function onWindowResize() { 
    
    renderer.setSize( window.innerWidth, window.innerHeight );
    
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;
        
}
    
function animate() {
    
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
    
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "#FF0000";
    ctx.fill();
    
    mesh.material.uniforms.canvasTexture.value.needsUpdate = true;

}  
 body { margin: 0; }  
 <!DOCTYPE html>
<html lang="en">
<head>
    <title>Test</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">

    <script src="https://unpkg.com/three@0.106.0/build/three.min.js"></script>

</head>
<body>
    
<script id="vs-canvasTest" type="x-shader/x-vertex">

    varying vec2 vUv;

    void main() {

        vUv = uv;
        gl_Position = vec4( position, 1.0 );

    }

</script>

<script id="fs-canvasTest" type="x-shader/x-fragment">

    varying vec2 vUv;
    uniform sampler2D canvasTexture;

    void main() {

        gl_FragColor = texture2D(canvasTexture, vUv);

    }


</script>

</body>  
</html>  

Комментарии:

1. Глупая ошибка. Приветствия.