类似于 ShaderToy 的 WebGL/GLSL 时间变量

Mud*_*Ali 5 javascript shader glsl webgl pixel-shader

这是我的顶点着色器

attribute vec4 a_position;
varying vec4 v_color;

void main() {
  gl_Position = vec4(a_position.xy, 0.0, 1.0);
  v_color = gl_Position * 0.5 + 0.5;
}
Run Code Online (Sandbox Code Playgroud)

这是我的片段着色器

precision mediump float;

varying vec4 v_color;

void main() {
  gl_FragColor = v_color;
}
Run Code Online (Sandbox Code Playgroud)

这是我的 JS,它设置了一切

var gl = document.getElementById("canvas").getContext('webgl');
var vertexShader = createShader(gl, gl.VERTEX_SHADER, window.vert);
var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, window.frag);
var program = createProgram(gl, vertexShader, fragmentShader);
var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
var positions = [
  -1, -1,
  -1, 1,
  1, 1,
  1, 1,
  1, -1,
  -1, -1,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
resizeCanvas(gl);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(program);
gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
var size = 2;          // 2 components per iteration
var type = gl.FLOAT;   // the data is 32bit floats
var normalize = false; // don't normalize the data
var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
var offset = 0;        // start at the beginning of the buffer
gl.vertexAttribPointer(
    positionAttributeLocation, size, type, normalize, stride, offset)
// // draw
var primitiveType = gl.TRIANGLES;
var offset = 0;
var count = 6;
gl.drawArrays(primitiveType, offset, count);
Run Code Online (Sandbox Code Playgroud)

我得到以下输出

在此处输入图片说明

但是,我想接下来的实现是使用类似于一段时间变量,这一动画iTimeShaderToy

我如何设置这样的东西?

gma*_*man 10

如果你想传递时间,你只需要制作一个制服来保持时间并将其设置为某个时间或计数器

uniform float time;
Run Code Online (Sandbox Code Playgroud)

在 JavaScript 中查找初始化时的位置

const timeLocation = gl.getUniformLocation(program, "time");
Run Code Online (Sandbox Code Playgroud)

在渲染时设置它

gl.uniform1f(timeLocation, someTimeValue);
Run Code Online (Sandbox Code Playgroud)

您还需要使用requestAnimationFrame. requestAnimationFrame自从页面加载以来已经过去了,所以你可以使用它

function render(time) {
  ...
  gl.useProgram(program);
  gl.uniform1f(timeLocation, time * 0.001);  // time in seconds
  ...
  // draw

  requestAnimationFrame(render);
}
requestAnimationFrame(render);
Run Code Online (Sandbox Code Playgroud)

例子:

uniform float time;
Run Code Online (Sandbox Code Playgroud)
const timeLocation = gl.getUniformLocation(program, "time");
Run Code Online (Sandbox Code Playgroud)