在 webgl / three.js 中对自定义着色器进行动画处理



我目前正在学习OpenGL,偶然发现了本教程:http://patriciogonzalezvivo.com/2015/thebookofshaders/03/

我试图在 webgl 中使用截图来进一步了解机制,但不知何故它不起作用,老实说我不确定为什么。我确定一定有一些语法错误,但它可能是什么?如果没有,那么我该如何完成这项工作?

老实说,我试图了解如何实现u_time。我认为 GPU 会自动有一个内置计时器,它会导致颜色过渡动画。

// set the scene size
var WIDTH = 400,
    HEIGHT = 300;
// set some camera attributes
var VIEW_ANGLE = 45,
    ASPECT = WIDTH / HEIGHT,
    NEAR = 0.1,
    FAR = 10000;
// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');
// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.Camera(  VIEW_ANGLE,
                              ASPECT,
                              NEAR,
                              FAR  );
var scene = new THREE.Scene();
// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;
// start the renderer
renderer.setSize(WIDTH, HEIGHT);
// attach the render-supplied DOM element
$container.append(renderer.domElement);
// create the sphere's material
var shaderMaterial = new THREE.MeshShaderMaterial({
  vertexShader:   $('#vertexshader').text(),
  fragmentShader: $('#fragmentshader').text()
});
// set up the sphere vars
var radius = 50, segments = 16, rings = 16;
// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
  new THREE.Sphere(radius, segments, rings),
  shaderMaterial);
// add the sphere to the scene
scene.addChild(sphere);
// draw!
renderer.render(scene, camera);
<div id="container"></div>
<script type="x-shader/x-vertex" id="vertexshader">
// switch on high precision floats
#ifdef GL_ES
precision highp float;
#endif
void main()
{
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform float u_time;
void main() {
  gl_FragColor = vec4(sin(u_time),0.0,0.0,1.0);
}
</script>
<script src="https://aerotwist.com/static/tutorials/an-introduction-to-shaders-part-1/demo/js/Three.js"></script>
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>

你是对的,你需要绑定/更新javascript中的值。为此,您需要做两件事:

  1. 声明创建着色器材质时着色器中的u_time统一(包括type和初始value)。

    var shaderMaterial = new THREE.MeshShaderMaterial({
      uniforms: { // <- This is an object with your uniforms as keys
        u_time: { type: "f", value: 0 }
      },
      vertexShader:   $('#vertexshader').text(),
      fragmentShader: $('#fragmentshader').text()
    });
    
  2. 你需要有一个渲染循环,在其中不断更新制服的value。下面是渲染循环的基本示例,一旦浏览器准备好渲染另一个帧,它就使用 requestAnimationFrame() 调用自身:

    function draw () {
      requestAnimationFrame(draw);
      // Update shader's time
      sphere.materials[0].uniforms.u_time.value += 0.01;
      // draw!
      renderer.render(scene, camera);
    }
    draw();
    

    请注意,您更新uniforms.u_time.value而不是uniforms.u_time 。这是因为制服既能容纳它的type,又能容纳当前的value

工作 js摆弄变化

还要知道您在小提琴中使用了 three.js 的非常旧版本。r40 版本来自 2011 年,我们目前高达 r76。最近的版本中有一些细节使这更简单。

最新更新