用canvas创建一个矩形
//获取canvas
const ctx = document.getElementById('canvas')
//获取2d的
const c = ctx.getContext('2d')
//绘制矩形X坐标Y坐标,宽度,高度,未指定颜色默认为黑色
//指定颜色为红色
c.fillStyle = 'red'
c.fillRect(10,10,100,100)
创建webgl程序
const ctx = document.getElementById('canvas')
//获取webgl
const gl = ctx.getContext('webgl')
//gl.clearColor(r,g,b,a)清空指定canvas 的颜色,接受四个参数(取值区间为0.0-1.0)
gl.clearColor(1.0,0.0,0.0,1.0)
//gl.clear() 清空canvas
gl.clear(gl.COLOR_BUFFER_BIT)
//gl.COLOR_BUFFER_BIT 清空颜色缓存
//gl.COLOR_BUFFER_BIT清空深度缓存区
//gl.COLOR_BUFFER_BIT清空模板缓冲区
gl.COLOR_BUFFER_BIT与gl.clearColor(1.0,0.0,0.0,1.0)配合使用 gl.COLOR_BUFFER_BIT与gl.clearDepth(1.0) gl.COLOR_BUFFER_BIT与gl.clearStencil(0)
绘制一个点
着色器:开发者编写的一段程序,代替固定渲染管线 来处理图像的渲染 着色器的分类: 1.顶点着色器:用来描述顶点的特性,通过计算获取位置信息 顶点可以理解为一个点 2.片元着色器:进行逐片元处理程序,通过计算获取颜色信息 片元可以理解为一个像素
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
//创建着色器源码,必须要有分号
const VERTEX_SHADER_SOURCE = `
//void表示无返回值,必须要存在main函数
void main(){
//要绘制的点的坐标
//vec4(0.0,0.0,0.0,1.0); X Y Z W(齐次坐标(x/w,y/w,z/w))
gl_Position = vec4(0.0,0.0,0.0,1.0);
//点的大小,只接受浮点数类型
gl_PointSize = 10.0;
}
` //顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main(){
//要绘制的点的颜色
//vec4(1.0,0.0,0.0,1.0) r g b a
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`//片元着色器
//创建着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
//指定顶点着色器的源码
gl.shaderSource(vertexShader,VERTEX_SHADER_SOURCE)
//指定片元着色器的源码
gl.shaderSource(fragmentShader,FRAGMENT_SHADER_SOURCE)
//编译着色器
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
//使用着色器
//创建一个程序对象
const program = gl.createProgram();
//指定程序对象使用的着色器
gl.attachShader(program,vertexShader)
gl.attachShader(program,fragmentShader)
//连接程序对象
gl.linkProgram(program)
//使用程序对象
gl.useProgram(program)
//执行绘制
//参数:要绘制的图形,从哪个开始,使用几个顶点
gl.drawArrays(gl.POINTS,0,1);
//线段,最少需要两个点
// gl.drawArrays(gl.LINES,0,1);
//三角形,最少需要三个点
// gl.drawArrays(gl.TRIANGLES,0,1);
//三个点
//0.0 0.0 0.0 //一个点
//0.2 0.0 0.0
//0.4 0.0 0.0 //一个线段
gl.drawArrays(gl.POINTS,0,1);
// 从1点开始,需要两个点
gl.drawArrays(gl.LINES,1,2);
全部流程
webgl坐标系
webgl的坐标点
使用attribute变量(修改位置)
const VERTEX_SHADER_SOURCE = `
//在main函数外声明变量
//存储限定符 类型 变量名 分号
attribute vec4 aPosition;
//attribute变量只传递顶点数据,不能在片元着色器中使用
//aPosition默认为vec4(0.0,0.0,0.0,1.0)
void main(){
gl_Position = aPosition;
//点的大小,只接受浮点数类型
gl_PointSize = 10.0;
}
` //顶点着色器
给attribute变量赋值
//获取attribute变量需要在initShader方法后,因为需要profram对象
//getAttribLocation(program,name) program 程序对象, name 指定想要获取的attribute变量的名称 返回变量的储存地址
const aPosition = gl.getAttribLocation(program,'aPosition')
//几个用于给attribute变量赋值的同族函数
//gl.vertexAttrib1f(location,v1) location 变量,v1 四个分量的值
//gl.vertexAttrib2f(location,v1,v2) location 变量,v1 v2 四个分量的值
//gl.vertexAttrib3f(location,v1,v2,v3) location 变量,v1 v2 v3 四个分量的值
//gl.vertexAttrib4f(location,v1,v2,v3,v4) location 变量,v1 v2 v3 v4 四个分量的值
// x,y坐标为0.5
// gl.vertexAttrib4f(aPosition,0.5,0.5,0.0,1.0)
创建一个会动的点
let x = 0;
setInterval(()=>{
x+= 0.1
if(x>1){
x = 0
}
//每次修改完attribute变量后需要重新绘制
gl.vertexAttrib1f(aPosition,x)
gl.drawArrays(gl.POINTS,0,1);
},200)
通过鼠标控制绘制
也可以将click变成其他的事件,如mousemove
ctx.addEventListener('click',(e)=>{
let x = e.clientX
let y = e.clientY
//获取当前元素的left和top
let domPosition = e.target.getBoundingClientRect();
//获取鼠标点击的位置
const domX = x-domPosition.left
const domY = y-domPosition.top
//转换为-1 到 1 的区间
const halfwidth = ctx.offsetWidth/2
const halfheight = ctx.offsetHeight /2
const clickX = (domX - halfheight)/halfwidth
const clickY = (-domY + halfwidth)/halfheight
gl.vertexAttrib2f(aPosition,clickX,clickY)
gl.drawArrays(gl.POINTS,0,1);
})
使用uniform变量(修改颜色)
着色器中
const FRAGMENT_SHADER_SOURCE = `
//同attribute
//片元着色器中没有指定默认精度
//低精度lowp,高精度highp
precision mediump float;
uniform vec2 uColor;
void main(){
//gl_FragColor只接受vec4,故将vec123转换成vec4
gl_FragColor = vec4(uColor.r,uColor.g,0.0,1.0;
}
`//片元着色器
js中
////////////////////////
const uColor = gl.getUniformLocation(program,'uColor')
gl.uniform2f(uColor,1.0,0.0)
//着色器声明vec4,此处用uniform4f,着色器声明vec3,此处用uniform3f,其余同理
//不可声明ucolor的类型为vec1,可以声明为uniform float uColor
//gl.uniform1f(location,v1) location 变量,v1 四个分量的值
//gl.uniform2f(location,v1,v2) location 变量,v1 v2 四个分量的值
//gl.uniform3f(location,v1,v2,v3) location 变量,v1 v2 v3 四个分量的值
//gl.uniform4f(location,v1,v2,v3,v4) location 变量,v1 v2 v3 v4 四个分量的值
//uniform即可以用在顶点着色器,也可以用在片元着色器,
//但是uniform不能传递顶点数据,因为每个顶点数据不同,uniform针对所有点生效