第一个webgl程序
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 500;
document.body.append(canvas);
const gl = canvas.getContext('webgl');
gl.clearColor(0,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);
偏元着色器
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
const gl = canvas.getContext('webgl');
const VERTEX_SHADER =
'void main() {\n\
gl_Position = vec4(-0.5, 0, 0, 1);\n\
gl_PointSize = 10.0;\n\
}';
const FRAG_SHADER =
'void main() {\n\
gl_FragColor = vec4(1, 0, 0, 1);\n\
}';
const vertex = gl.createShader(gl.VERTEX_SHADER);
const frag = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertex,VERTEX_SHADER);
gl.shaderSource(frag,FRAG_SHADER);
gl.compileShader(vertex);
gl.compileShader(frag);
const program = gl.createProgram();
gl.attachShader(program,vertex);
gl.attachShader(program,frag);
gl.linkProgram(program);
gl.useProgram(program);
gl.linkProgram(program);
gl.useProgram(program);
gl.clearColor(0,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS,0,1);
旋转操作
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
const gl = canvas.getContext('webgl');
const VERTEX_SHADER =
`
attribute vec4 a_pos;\n\
uniform float u_sinB,u_cosB;\n\
void main() {\n\
gl_Position.x = a_pos.x * u_cosB - a_pos.y * u_sinB;\n
gl_Position.y = a_pos.y * u_cosB + a_pos.y * u_cosB;\n
gl_Position.z = a_pos.z;\n
gl_Position.w = a_pos.w;\n
}`;
const FRAG_SHADER =
`void main() {\n\
gl_FragColor = vec4(1, 0, 0, 1);\n\
}`;
const vertex = gl.createShader(gl.VERTEX_SHADER);
const frag = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertex,VERTEX_SHADER);
gl.shaderSource(frag,FRAG_SHADER);
gl.compileShader(vertex);
gl.compileShader(frag);
const program = gl.createProgram();
gl.attachShader(program,vertex);
gl.attachShader(program,frag);
gl.linkProgram(program);
gl.useProgram(program);
const dataVertices = new Float32Array([
0.0,0.0,
0.3,0.3,
0.6,0.0,
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,dataVertices,gl.STATIC_DRAW);
const a_pos = gl.getAttribLocation(program,'a_pos');
gl.vertexAttribPointer(a_pos,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(a_pos);
const angle = 30;
const sinB = Math.sin(angle / 180 * Math.PI);
const cosB = Math.cos(angle / 180 * Math.PI);
const u_sinB = gl.getUniformLocation(program,'u_sinB');
const u_cosB = gl.getUniformLocation(program,'u_cosB');
gl.uniform1f(u_sinB,sinB);
gl.uniform1f(u_cosB,cosB);
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES,0,3);
缩放操作
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
const gl = canvas.getContext('webgl');
const VERTEX_SHADER =
`
attribute vec4 a_pos;\n\
uniform float u_change;\n\
void main() {\n\
gl_Position.x = a_pos.x;\n
gl_Position.y = a_pos.y;\n
gl_Position.z = a_pos.z;\n
gl_Position.w = u_change;\n
}`;
const FRAG_SHADER =
`void main() {\n\
gl_FragColor = vec4(1, 0, 0, 1);\n\
}`;
const vertex = gl.createShader(gl.VERTEX_SHADER);
const frag = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertex,VERTEX_SHADER);
gl.shaderSource(frag,FRAG_SHADER);
gl.compileShader(vertex);
gl.compileShader(frag);
const program = gl.createProgram();
gl.attachShader(program,vertex);
gl.attachShader(program,frag);
gl.linkProgram(program);
gl.useProgram(program);
const dataVertices = new Float32Array([
0.0,0.0,
0.3,0.3,
0.6,0.0,
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,dataVertices,gl.STATIC_DRAW);
const a_pos = gl.getAttribLocation(program,'a_pos');
gl.vertexAttribPointer(a_pos,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(a_pos);
const u_change = gl.getUniformLocation(program,'u_change');
let scale = 1;
function run() {
gl.uniform1f(u_change,scale);
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES,0,3);
}
run();
window.addEventListener('keydown',(ev) => {
if(ev.code === 'ArrowUp') {
scale+= 0.1;
}else{
scale-= 0.1;
}
run();
console.log(ev);
})
uniform传值
const fragShaderSource = `
precision mediump float;
uniform vec3 u_color;
void main() {
gl_FragColor = vec4(u_color,1);
}
`;
const u_color = gl.getUniformLocation(program,'u_color');
gl.uniform3f(u_color,0.0,1.0,0.0);
buffer生成纯色三角形
const vertexShaderSource = `
attribute vec4 a_Position;
void main() {
gl_Position = a_Position;
gl_PointSize = 10.0;
}
`;
const fragShaderSource = `
void main() {
gl_FragColor = vec4(1,0,0,1);
}
`;
const dataVertices = new Float32Array([
-0.5,0.0,
0.5,0.0,
0.5,0.5,
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,dataVertices,gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(program,'a_Position');
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(a_Position);
渐变三角形
const dataVertices = new Float32Array([
-0.5,0.0,1.0,0.0,0.0,
0.5,0.0,0.0,1.0,0.0,
0.0,0.5,0.0,0.0,1.0,
]);
const FSIZE = dataVertices.BYTES_PER_ELEMENT;
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,dataVertices,gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(program,'a_Position');
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,5 * FSIZE,0);
gl.enableVertexAttribArray(a_Position);
const a_Color = gl.getAttribLocation(program,'a_color');
gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,5 * FSIZE,2 * FSIZE);
gl.enableVertexAttribArray(a_Color);
webgl中添加动画
const vertexShaderSource = `
precision mediump float;
attribute vec2 a_position;
uniform vec4 u_translate;
void main() {
gl_Position = vec4(a_position,0.0,1.0) + u_translate;
gl_PointSize = 10.0;
}
`;
let tx = 0;
let ty = 0;
const u_translate = gl.getUniformLocation(program,'u_translate');
function animation() {
requestAnimationFrame(animation);
tx += 0.001;
ty += 0.001;
gl.uniform4f(u_translate,tx,ty,0,0);
gl.clearColor(0,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES,0,3);
}
旋转动画
const VERTEX_SHADER = `
attribute vec4 a_position;
uniform float u_sinB;
uniform float u_cosB;
void main() {
float x1 = a_position.x;
float y1 = a_position.y;
float z1 = 0.0;
float x2 = x1 * u_cosB - y1 *u_sinB;
float y2 = y1 * u_cosB + x1 * u_sinB;
float z2 = z1;
gl_Position = vec4(x2,y2,z2,1.0);
}
`;
const aPosition = gl.getAttribLocation(program, 'a_position');
const uSinB = gl.getUniformLocation(program, 'u_sinB');
const uCosB = gl.getUniformLocation(program, 'u_cosB');
let angle = 45;
function tick() {
angle += 1;
requestAnimationFrame(tick);
gl.uniform1f(uSinB, Math.sin(angle * Math.PI / 180));
gl.uniform1f(uCosB, Math.cos(angle * Math.PI / 180));
gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aPosition);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
tick();
颜色和顶点生成渐变四边形
const dataVertices = new Float32Array([
-0.5,0.5,0.0, 1.0,0.0,0.0,
-0.5,-0.5,0.0, 0.0,1.0,0.0,
0.5,-0.5,0.0, 0.0,0.0,1.0,
0.5,0.5,0.0, 1.0,1.0,1.0
]);
const FSIZE = dataVertices.BYTES_PER_ELEMENT;
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,dataVertices,gl.STATIC_DRAW);
const aPosition = gl.getAttribLocation(program,'a_position');
gl.vertexAttribPointer(aPosition,3,gl.FLOAT,false,6 * FSIZE,0);
gl.enableVertexAttribArray(aPosition);
const aColor = gl.getAttribLocation(program,'a_color');
gl.vertexAttribPointer(aColor,3,gl.FLOAT,false,6 * FSIZE,FSIZE * 3);
gl.enableVertexAttribArray(aColor);
uv颜色渐变
const vertexShaderSource = `
attribute vec3 a_position;
attribute vec2 a_uv;
varying vec2 v_uv;
void main() {
v_uv = a_uv;
gl_Position = vec4(a_position,1.0);
gl_PointSize = 10.0;
}
`;
const fragShaderSource = `
precision mediump float;
varying vec2 v_uv;
void main() {
gl_FragColor = vec4(v_uv,0.0,1.0);
}
`;
const uvs = new Float32Array([
0.0,0.0,
1.0,0.0,
1.0,1.0,
0.0,1.0,
]);
const uvBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER,uvs,gl.STATIC_DRAW);
const aUv = gl.getAttribLocation(program,'a_uv');
gl.vertexAttribPointer(aUv,2,gl.FLOAT,false,FSIZE * 2,0);
gl.enableVertexAttribArray(aUv);
canvas坐标转极坐标
window.addEventListener('click',(event) => {
const sx = event.clientX;
const sy = event.clientY;
const x = (sx / width) * 2 - 1;
const y = -(sy / height) * 2 + 1;
const vertextData = new Float32Array([x,y]);
const aPosition = gl.getAttribLocation(program,'a_position');
gl.vertexAttrib2fv(aPosition,vertextData);
draw();
})
缓冲区绘制多个点
const arr = [];
window.addEventListener('click', (event) => {
const sx = event.clientX;
const sy = event.clientY;
const x = (sx / width) * 2 - 1;
const y = -(sy / height) * 2 + 1;
arr.push(x, y);
const dataVertices = new Float32Array(arr);
const FSIZE = dataVertices.BYTES_PER_ELEMENT;
console.log(dataVertices);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, dataVertices, gl.STATIC_DRAW);
const a_position = gl.getUniformLocation(program,'a_position');
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, FSIZE * 2, 0);
gl.enableVertexAttribArray(a_position);
draw();
});
function draw() {
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, arr.length / 2 || 1);
}
点击生成随机大小的点
window.addEventListener('click', (event) => {
const sx = event.clientX;
const sy = event.clientY;
const x = (sx / width)* 2 - 1;
const y = -(sy / height) * 2 + 1;
const aPosition = gl.getAttribLocation(program, 'a_position');
gl.vertexAttrib2fv(aPosition,new Float32Array([x,y]));
const a_pointSize = gl.getAttribLocation(program, 'a_pointSize');
gl.vertexAttrib1f(a_pointSize, Math.random() * 100);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, 1);
});
鼠标点击生成随机颜色
const fragShaderSource = `
precision mediump float;
uniform vec3 u_color;
void main() {
gl_FragColor = vec4(u_color,1.0);
}
`
window.addEventListener('click',(event) => {
const sx = event.clientX;
const sy = event.clientY;
const x = (sx / width) * 2 - 1;
const y = -(sy / width) * 2 + 1;
const aPosition = gl.getAttribLocation(program,'a_position');
gl.vertexAttrib2fv(aPosition,new Float32Array([x,y]));
const aPointSize = gl.getAttribLocation(program,'a_pointSize');
gl.vertexAttrib1f(aPointSize,Math.random() * 100);
const uColor = gl.getUniformLocation(program,'u_color');
gl.uniform3f(uColor,Math.random(),Math.random(),Math.random());
draw();
})
鼠标点击生成随机圆
const fragShaderSource = `
precision mediump float;
uniform vec3 u_color;
void main() {
float dist = distance(gl_PointCoord,vec2(0.5,0.5));
if(dist < 0.5) {
gl_FragColor = vec4(u_color,1.0);
}else {
discard;
}
}
`;
window.addEventListener('click', (event) => {
const sx = event.clientX;
const sy = event.clientY;
const x = (sx / width) * 2 - 1;
const y = -(sy / width) * 2 + 1;
const aPosition = gl.getAttribLocation(program, 'a_position');
gl.vertexAttrib2fv(aPosition, new Float32Array([x, y]));
const aPointSize = gl.getAttribLocation(program, 'a_pointSize');
gl.vertexAttrib1f(aPointSize, Math.random() * 20);
const uColor = gl.getUniformLocation(program, 'u_color');
gl.uniform3f(uColor, Math.random(), Math.random(), Math.random());
draw();
});
缓冲区绘制图元
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position,0.0,1.0);
gl_PointSize = 10.0;
}
`;
const dataVertices = new Float32Array([
0.0,0.0,
0.3,0.3,
0.6,0.0,
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,dataVertices,gl.STATIC_DRAW);
const aPosition = gl.getUniformLocation(program,'a_position');
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(aPosition);
github
blog
网站