WebGL-学习
绘制接口
WebGLRenderingContext.drawArrays()
void gl.drawArrays(mode, first, count);
参数
mode
指定绘制图元的方式,可能值如下。
gl.POINTS
: 绘制一系列点。gl.LINE_STRIP
: 绘制一个线条。即,绘制一系列线段,上一点连接下一点。gl.LINE_LOOP
: 绘制一个线圈。即,绘制一系列线段,上一点连接下一点,并且最后一点与第一个点相连。gl.LINES
: 绘制一系列单独线段。每两个点作为端点,线段之间不连接。gl.TRIANGLE_STRIP
:绘制一个三角带。gl.TRIANGLE_FAN
:绘制一个三角扇。gl.TRIANGLES
: 绘制一系列三角形。每三个点作为顶点。first
指定从哪个点开始绘制。
count
指定绘制需要使用到多少个点。
创建program
WebGLRenderingContext.createProgram()
WebGLProgram gl.createProgram();
用法如下:
var program = gl.createProgram();
// 添加预先定义好的顶点着色器和片段着色器
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if ( !gl.getProgramParameter( program, gl.LINK_STATUS) ) {
var info = gl.getProgramInfoLog(program);
throw "Could not compile WebGL program. \n\n" + info;
}
//使用program
gl.useProgram(program);
attribute
关键字
声明顶点相关数据的时候需要用到attribute
关键字。
const vsSource = `
attribute vec4 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main() {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
}
`;
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
attribute vec4 aVertexPosition;
声明的变量aVertexPosition
表示矩形所有顶点的位置坐标。WebGL着色器语言之所以规定attribute
这样一个关键字,目的是为了javascript可以调用相关的WebGL API把顶点相关数据从javascript
传递给顶点着色器attribute
声明的变量。
先将变量指定给js
中的变量
const programInfo={
program:shaderProgram,
attribLocations:{
vertexPosition:gl.getAttribLocation(shaderProgram,'aVertexPosition')
},
getUniformLocations:{
projectionMatrix:gl.getUniformLocation(shaderProgram,'uProjectionMatrix'),
modelViewMatrix:gl.getUniformLocation(shaderProgram,'uModelViewMatrix'),
},
}
javascript
会调用相关的WebGL API
通过下面的代码把类型数组data
中包含的顶点位置坐标数据传递给顶点着色器中attribute
关键字声明的变量aVertexPosition
。
此部分代码的作用总体上是把内存中顶点数据输入显存,提高图形的处理效率。
//告诉WebGL如何将位置从位置缓冲区拉出到 vertexPosition 属性中。
{
const numComponents=2; //每次迭代取两个值
const type=gl.FLOAT; //这个数据在buffer中是32位浮点数
const normalize=false;
const stride=0; //从一组值到下一组值获取多少字节
//0等于使用类型和组件
const offset=0 //从缓存器的多少字节开始
//顶点数组data数据传入缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER,buffers.position);
//缓冲区中的数据按照一定的规律传递给位置变量
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset
);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexPosition
);
//告诉WebGL在绘制时使用我们的程序
gl.useProgram(programInfo.program);
//设置shader uniforms
gl.uniformMatrix4fv(
programInfo.getUniformLocations.projectionMatrix,
false,
projectionMatrix
);
gl.uniformMatrix4fv(
programInfo.getUniformLocations.modelViewMatrix,
false,
modelViewMatrix);
{
const offset = 0;
const vertexCount = 4;
gl.drawArrays(gl.POINTS, offset, vertexCount);
// gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
}
}
drawArrays整体执行顺序

示例源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"
integrity="sha512-zhHQR0/H5SEBL3Wn6yYSaTTZej12z0hVZKOv3TwCUXT1z5qeqGcXJLLrbERYRScEDDpYIJhPC1fk31gqR783iQ=="
crossorigin="anonymous"
defer></script>
</head>
<body onload="main()">
<canvas id="myCanvas" width="640" height="640"></canvas>
</body>
<script>
function main(){
let canvas=document.getElementById('myCanvas');
let gl=canvas.getContext("webgl");
if(!gl){
alert("无法初始化WebGL,你的浏览器、操作系统或硬件等可能不支持WebGL")
return;
}
//使用完全不透明等黑色清除所有图像
gl.clearColor(0.0,0.0,0.0,1.0);
// Vertex shader program
//用上面指定等颜色清除缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
const vsSource = `
attribute vec4 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main() {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
}
`;
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
const shaderProgram=initShaderProgram(gl,vsSource,fsSource);
const programInfo={
program:shaderProgram,
attribLocations:{
vertexPosition:gl.getAttribLocation(shaderProgram,'aVertexPosition')
},
getUniformLocations:{
projectionMatrix:gl.getUniformLocation(shaderProgram,'uProjectionMatrix'),
modelViewMatrix:gl.getUniformLocation(shaderProgram,'uModelViewMatrix'),
},
}
const buffers=initBuffers(gl);
drawScene(gl,programInfo,buffers)
}
//初始化着色器,让WebGL指导如何绘制我们的数据
function initShaderProgram(gl,vsSource,fsSource){
const vertexShader=loadShader(gl,gl.VERTEX_SHADER,vsSource);
const fragmentShader=loadShader(gl,gl.FRAGMENT_SHADER,fsSource);
//创建着色器程序
const shaderProgram=gl.createProgram();
gl.attachShader(shaderProgram,vertexShader);
gl.attachShader(shaderProgram,fragmentShader);
gl.linkProgram(shaderProgram);
//创建失败,alert
if(!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)){
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return null;
}
return shaderProgram;
}
//创建指定类型的着色器,上传source源码并编译
function loadShader(gl,type,source){
const shader=gl.createShader(type);
//将source传送给对象
gl.shaderSource(shader,source);
//编译shader程序
gl.compileShader(shader);
//判定是否编译成功
if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader
}
//创建对象
function initBuffers(gl){
//创建一个buffer为这个正方形区域
const positionBuffer=gl.createBuffer();
//选中这个positionBuffer作为一个应用buffer
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
//创建一个数组,关于正方形的位置
const positions=
// 1.0,1.0,
// -1.0,1.0,
// 1.0,-1.0,
// -1.0,-1.0,
// ]
[0.5,0.5,-0.5,0.5,-0.5,-0.5,0.5,-0.5]
//现在将此数组传到WebGL去构建形状,我们通过创建32位浮点数组,然后将其填入当前buffer中
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
return {
position:positionBuffer,
}
}
//绘制场景
function drawScene(gl,programInfo,buffers){
gl.clearColor(0.0,0.0,0.0,0.8); //填充黑色,0.8透明度
gl.clearDepth(1.0) //清空所有
gl.enable(gl.DEPTH_TEST) //depth能够使用测试
gl.depthFunc(gl.LEQUAL) //Near things obscure far things
//清空canvas在绘制之前
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
//创建投影矩阵,一种特殊的矩阵常被用于模拟相机失真
//我们的视野是45度,具有高度和宽度匹配画布的显示大小并且我们只想在0.1单位之间看到物体,距离相机100单位远
const fieldOfView=45*Math.PI/180; //转换为极坐标
const aspect=gl.canvas.clientWidth/gl.canvas.clientHeight;
const zNear=0.1;
const zFar=100.0;
const projectionMatrix=mat4.create();
mat4.perspective(projectionMatrix,fieldOfView,aspect,zNear,zFar);
//设置绘制位置为识别点,位于场景中心
const modelViewMatrix = mat4.create();
//现在将绘图位置移动到我们想要的位置
mat4.translate(modelViewMatrix, //目标矩阵
modelViewMatrix,//要翻译的矩阵
[-0.0,0.0,-6.0])//要移动的数据
//告诉WebGL如何将位置从位置缓冲区拉出到 vertexPosition 属性中。
{
const numComponents=2; //每次迭代取两个值
const type=gl.FLOAT; //这个数据在buffer中是32位浮点数
const normalize=false;
const stride=0; //从一组值到下一组值获取多少字节
//0等于使用类型和组件
const offset=0 //从缓存器的多少字节开始
gl.bindBuffer(gl.ARRAY_BUFFER,buffers.position);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset
);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexPosition
);
//告诉WebGL在绘制时使用我们的程序
gl.useProgram(programInfo.program);
//设置shader uniforms
gl.uniformMatrix4fv(
programInfo.getUniformLocations.projectionMatrix,
false,
projectionMatrix
);
gl.uniformMatrix4fv(
programInfo.getUniformLocations.modelViewMatrix,
false,
modelViewMatrix);
{
const offset = 0;
const vertexCount = 4;
gl.drawArrays(gl.POINTS, offset, vertexCount);
// gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
}
}
}
</script>
</html>
- 本文链接:https://archer-lan.github.io/2023/11/20/WebGL-%E7%9F%A9%E9%98%B5%E5%88%9B%E5%BB%BA/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。