我目前正在学习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中的值。为此,您需要做两件事:
-
声明创建着色器材质时着色器中的
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() });
-
你需要有一个渲染循环,在其中不断更新制服的
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。最近的版本中有一些细节使这更简单。