渐变
前置工作,创建缓冲,对顶点着色器传递顶点数据
function main() {
var canvas = document.getElementById('webgl');
var gl = getWebGLContext(canvas);
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) return
var n = initVertexBuffers(gl);
}
function initVertexBuffers(gl) {
var vertices = new Float32Array([-1, 1, -1, -1, 1, -1, 1, 1]);
var n = 4;
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
return n;
}
顶点着色
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
'}\n';
思考,最终操作改变每个片元的颜色,就是根据uv坐标的不同逐片元计算,使用cos控制周期性效果
uv坐标:二维空间每个像素绝对位置(0,0 ~ 宽高) gl_FragCoord.xy / 设备分辨率
cos周期变化:delta时间,每帧间隔为主键
对片元着色传递这些控制变量
let time = Date.now();
let iTime = 0;
let iResolutionAddr = gl.getUniformLocation(gl.program, "iResolution");
let iTimeAddr = gl.getUniformLocation(gl.program, "iTime");
gl.clear(gl.COLOR_BUFFER_BIT);
let loop = () => {
let nowTime = Date.now();
let dt = (nowTime - time) * 0.002;
iTime += dt;
time = nowTime;
gl.uniform2f(iResolutionAddr, 1536, 865); // 传递分辨率
gl.uniform1f(iTimeAddr, iTime); // 传递时间
gl.clearColor(0, 0, 0, 0);
gl.drawArrays(gl.TRIANGLE_FAN, 0, n);
requestAnimationFrame(loop);
};
loop();
片元着色
var FSHADER_SOURCE =
'#ifdef GL_ES\n' +
'precision mediump float;\n' +
'#endif\n' +
'uniform vec2 iResolution;\n' + // 屏幕分辨率
'uniform float iTime;\n' +
'void main() {\n' +
'vec2 uv = gl_FragCoord.xy / iResolution;' + // 计算uv 0~1
// cos 分别计算 v.x, v.y, v.z 的余弦值,返回 vec3(-1~1, -1~1, -1~1)
'vec3 c = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0, 2, 4));' + // vec3 0~1
'gl_FragColor = vec4(c, 1.0);\n' +
'}\n';