可以实现 地图,vr,物品展示,室内设计,城市规划
GLSL ES是以字符串的形式存在在JavaScript中的
webgl开源框架
three.js:js 3Dwebgl库
babylon.js: web3D图形引擎
kickjs: web的开源图形和游戏引擎
clayGl: 构建可扩展web3d应用程序
playCanvas: 网络游戏和3D图形引擎
webGlStudio.js和Litescene.js: 开源web 3D图形编辑器和创建器
luma: uber的3D Webgl 可视化库
A-Frame 是用于构建vr(虚拟现实) 体验的web框架
第一个程序
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
//clearColor(r,g,b,a)指定清空<canvas>的颜色 接收四个参数
gl.clearColor(1.0,0.0,0.0,1.0)
//gl.COLOR_BUFFER_BIT清空颜色缓存 gl.DEPTH_BUFFER_BIT 清空深度缓存区 gl.STENCIL_BUFFER_BIT 清空模版缓存区
gl.clear(gl.COLOR_BUFFER_BIT)
注意这两个要一起使用 gl.clearColor 和 gl.clear
着色器
着色器:就是让开发者自己去编写一段程序,用来代替固定渲染管线,来处理图像的渲染
顶点着色器:用来描述顶点的特性 =》通过计算获取位置信息
片元着色器:进行逐片远处理程序 =》通过计算获取颜色信息
流程介绍: 1.开始
2.获取元素
3.初始化顶点着色器源程序
-
初始化片元着色器源程序
创建顶点着色器
创建片元着色器
关联着色器和着色器源码
编译着色器
创建program
关联着色器 和 program
使用program
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
console.log(gl)
// 着色器 就是让开发者自己去编写一段程序,用来代替固定渲染管线,来处理图像的渲染
const VERTEX_SHADER_SOURCE = `
//必须要存在 main 函数 void里面必须有分号
void main() {
// 要绘制的点的坐标
gl_Position = vec4(0.0,0.0,0.0,1.0);
// 点的大小
gl_PointSize = 10.0;
}
`; //顶点着色器
//gl_Position vec4(1.0,0.0,0.0,1.0) x,y,z,w 齐次坐标
//gl_FraColor vec4(1.0,0.0,0.0,1.0) r,g,b,a
const FRAGMENT_SHADER_SOURCE = `
void main() {
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)
// initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
//执行绘制
// 要绘制的图形是什么, 从哪个开始, 使用几个顶点
gl.drawArrays(gl.POINTS, 0, 1)
</script>
attribute变量
1.获取attribute变量
const aPosition = gl.getAttribLocation(program, 'aPositon')
获取attribute变量需要在initShader 函数之后,因为会用到program这个程序对象
2.赋值
gl.vertexAttrib4f(aPosition, 0.5, 0.5, 0.0, 1.0)
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
// 变量声明 vec4 类型 aPosition 变量名
// 只传递顶点数据,不能在片元着色器使用
attribute vec4 aPosition;
void main() {
gl_Position = aPosition;
gl_PointSize = 10.0;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
let x=0;
setInterval(() => {
x += 0.1;
if(x>1.0){
x=0
}
gl.vertexAttrib1f(aPosition, x)
gl.drawArrays(gl.POINTS, 0, 1)
},1000)
</script>
鼠标控制点
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
// 变量声明 vec4 类型 aPosition 变量名
// 只传递顶点数据,不能在片元着色器使用
attribute vec4 aPosition;
void main() {
gl_Position = aPosition;
gl_PointSize = 10.0;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
const points = []
ctx.onclick = function(ev) {
// 坐标
const x = ev.clientX
const y = ev.clientY
//ctx.offsetTop
//ctx.offsetLeft
const domPosition = ev.target.getBoundingClientRect();
console.log(domPosition,ctx.offsetTop,ctx.offsetLeft)
const domx = x - domPosition.left
const domy = y - domPosition.top
const halfWidth = ctx.offsetWidth / 2
const halfHeight = ctx.offsetHeight / 2
const clickX = (domx - halfWidth) /halfWidth
const clickY = (halfHeight - domy)/halfHeight
console.log(clickX,clickY)
points.push({
clickX,clickY
})
for(let i=0;i<points.length;i++){
gl.vertexAttrib2f(aPosition,points[i].clickX,points[i].clickY)
gl.drawArrays(gl.POINTS, 0, 1)
}
}
</script>
绘制不同颜色
1.获取uColor变量
const uColor = gl.getUniformLocation(program, 'uColor')
2.赋值
gl.uniform4f(uColor,1.0,0.0,0.0,1.0)
缓冲区对象
缓冲区对象是webgl系统中的一块内存区域,可以一次性地向缓冲区对象中填充大量的顶点数据,然后将这些数据保存在其中,供顶点着色器使用
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
// 变量声明 vec4 类型 aPosition 变量名
// 只传递顶点数据,不能在片元着色器使用
attribute vec4 aPosition;
void main() {
gl_Position = aPosition;
gl_PointSize = 10.0;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,
0.5,-0.5,
0.0,0.5,
])
//2创建缓存对象
const buffer = gl.createBuffer()
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
// gl.vertexAttrib2f(aPosition,0.0,0.0)
gl.drawArrays(gl.POINTS, 0, 3)
</script>
const VERTEX_SHADER_SOURCE = `
// 变量声明 vec4 类型 aPosition 变量名
// 只传递顶点数据,不能在片元着色器使用
attribute vec4 aPosition;
attribute float aPointSize;
void main() {
gl_Position = aPosition;
gl_PointSize = aPointSize;
}
`;
const aPointSize = gl.getAttribLocation(program, 'aPointSize')
//1创建顶点数据
const size = new Float32Array([
10.0,
20.0,
30.0,
])
//2创建缓存对象
const sizeBuffer = gl.createBuffer()
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,sizeBuffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,size,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPointSize,1,gl.FLOAT,false,0,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPointSize)
gl.drawArrays(gl.POINTS, 0, 3)
缓存区大小和位置写一起
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
// 变量声明 vec4 类型 aPosition 变量名
// 只传递顶点数据,不能在片元着色器使用
attribute vec4 aPosition;
attribute float aPointSize;
void main() {
gl_Position = aPosition;
gl_PointSize = aPointSize;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
const aPointSize = gl.getAttribLocation(program, 'aPointSize')
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,10.0,
0.5,-0.5,20.0,
0.0,0.5,30.0
])
//2创建缓存对象
const buffer = gl.createBuffer()
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
const BYTES = points.BYTES_PER_ELEMENT;
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,BYTES*3,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
gl.vertexAttribPointer(aPointSize,1,gl.FLOAT,false,BYTES*3,BYTES*2);
gl.enableVertexAttribArray(aPointSize)
gl.drawArrays(gl.POINTS, 0, 3)
</script>
多种绘制的图形
通过着色器偏移
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
attribute float aTranslate;
void main() {
gl_Position = vec4(aPosition.x + aTranslate,aPosition.y,aPosition.z,1.0);
gl_PointSize = 10.0;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
const aTranslate = gl.getAttribLocation(program, 'aTranslate')
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,
0.5,-0.5,
0.0,0.5,
])
//2创建缓存对象
const buffer = gl.createBuffer()
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
// gl.vertexAttrib2f(aPosition,0.0,0.0)
let x=-1
setInterval(()=>{
x+=0.1;
if(x>1){
x=-1
}
gl.vertexAttrib1f(aTranslate,x)
gl.drawArrays(gl.TRIANGLES, 0, 3)
},60)
</script>
通过着色器缩放
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
attribute float aTranslate;
attribute float aScale;
void main() {
gl_Position = vec4(aPosition.x*aScale + aTranslate,aPosition.y,aPosition.z,1.0);
gl_PointSize = 10.0;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
// const aTranslate = gl.getAttribLocation(program, 'aTranslate')
const aScale = gl.getAttribLocation(program, 'aScale')
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,
0.5,-0.5,
0.0,0.5,
])
//2创建缓存对象
const buffer = gl.createBuffer()
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
// gl.vertexAttrib2f(aPosition,0.0,0.0)
let x=-1
setInterval(()=>{
x+=0.1;
if(x>2){
x=1
}
gl.vertexAttrib1f(aScale,x)
gl.drawArrays(gl.TRIANGLES, 0, 3)
},60)
</script>
图形旋转
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
attribute float deg;
void main() {
gl_Position.x = aPosition.x*cos(deg) - aPosition.y*sin(deg);
gl_Position.y = aPosition.x*sin(deg) + aPosition.y*cos(deg);
gl_Position.z = aPosition.z;
gl_Position.w = aPosition.w;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
const deg = gl.getAttribLocation(program, 'deg')
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,
0.5,-0.5,
0.0,0.5,
])
//2创建缓存对象
const buffer = gl.createBuffer()
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
// gl.vertexAttrib2f(aPosition,0.0,0.0)
let x=-1
function animation(){
x+=-0.01;
gl.vertexAttrib1f(deg,x)
gl.drawArrays(gl.TRIANGLES, 0, 3)
requestAnimationFrame(animation)
}
animation()
</script>
平移矩阵
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
uniform mat4 mat;
void main() {
gl_Position = mat * aPosition;
gl_PointSize = 10.0;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
const mat = gl.getUniformLocation(program, 'mat')
function getTranslateMatrix(x=0,y=0,z=0) {
return new Float32Array([
1.0,0.0,0.0,0.0,
0.0,1.0,0.0,0.0,
0.0,0.0,1.0,0.0,
x,y,z,1,
])
}
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,
0.5,-0.5,
0.0,0.5,
])
//2创建缓存对象
const buffer = gl.createBuffer()
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
// gl.vertexAttrib2f(aPosition,0.0,0.0)
let x=-1
function animation(){
x+=0.01;
if(x>1){
x=-1
}
const matrix =getTranslateMatrix(x,x)
gl.uniformMatrix4fv(mat,false,matrix)
gl.drawArrays(gl.TRIANGLES, 0, 3)
requestAnimationFrame(animation)
}
animation();
</script>
缩放-缩放矩形
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
uniform mat4 mat;
void main() {
gl_Position = mat * aPosition;
gl_PointSize = 10.0;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
void main() {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
const mat = gl.getUniformLocation(program, 'mat')
function getScaleMatrix(x=1,y=1,z=1) {
return new Float32Array([
x,0.0,0.0,0.0,
0.0,y,0.0,0.0,
0.0,0.0,z,0.0,
0.0,0.0,0.0,1,
])
}
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,
0.5,-0.5,
0.0,0.5,
])
//2创建缓存对象
const buffer = gl.createBuffer()
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
// gl.vertexAttrib2f(aPosition,0.0,0.0)
let x=0.1
function animation(){
x+=0.01;
if(x>1.5){
x=0.1
}
const matrix =getScaleMatrix(x,x)
gl.uniformMatrix4fv(mat,false,matrix)
gl.drawArrays(gl.TRIANGLES, 0, 3)
requestAnimationFrame(animation)
}
animation();
</script>
图形旋转 矩形旋转
varing变量
顶点着色器向片元着色器传值
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
varying vec4 vColor;
void main() {
vColor = aPosition;
gl_Position = aPosition;
gl_PointSize = 10.0;
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
precision lowp float;
varying vec4 vColor;
void main() {
gl_FragColor = vColor;
}
`;
从顶点到图形-webgl渲染流程介绍
1,图元装配过程:将独立的顶点坐标装配成几何图形,图形的类别由gl.drawArrays()第一个参数确定。 2.光栅化:将装配好的图形转换为片元
3.剔除:对于不透明物体,背面对于观察者来说是不可见的,那么在渲染过程中,就会将不可见的部分剔除,不参与绘制。节省渲染开销。
图形背景图
<script>
/* */
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
// 变量声明 vec4 类型 aPosition 变量名
// 只传递顶点数据,不能在片元着色器使用
attribute vec4 aPosition;
attribute vec4 aTex;
varying vec2 vTex;
void main() {
gl_Position = aPosition;
vTex = vec2(aTex.x,aTex.y);
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
precision lowp float;
uniform sampler2D uSampler;
varying vec2 vTex;
void main() {
gl_FragColor = texture2D(uSampler,vTex);
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
const aTex = gl.getAttribLocation(program, 'aTex')
const uSampler = gl.getUniformLocation(program, 'uSampler')
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,0.0,1.0,
0.5,-0.5,0.0,0.0,
-0.5,0.5,1.0,1.0,
0.5,0.5,1.0,0.0,
])
//2创建缓存对象
const buffer = gl.createBuffer()
const BYTES = points.BYTES_PER_ELEMENT
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,BYTES * 4,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
gl.vertexAttribPointer(aTex,2,gl.FLOAT,false,BYTES * 2,0);
gl.enableVertexAttribArray(aTex)
// gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
const img = new Image()
img.onload= function () {
//创建文理对象
const texture = gl.createTexture()
//翻转图片 Y轴
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
//开启一个纹理单元
gl.activeTexture(gl.TEXTURE0)
//绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D,texture)
//处理放大缩小的逻辑
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR)
//横向 纵向 平铺的方式
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE)
//配置纹理图像
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,img)
gl.uniform1i(uSampler,0)
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
}
img.src='../assets/2.png'
console.log(img)
</script>
多重纹理
<script>
/* */
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
// 变量声明 vec4 类型 aPosition 变量名
// 只传递顶点数据,不能在片元着色器使用
attribute vec4 aPosition;
attribute vec4 aTex;
varying vec2 vTex;
void main() {
gl_Position = aPosition;
vTex = vec2(aTex.x,aTex.y);
}
`;
//顶点着色器
const FRAGMENT_SHADER_SOURCE = `
precision lowp float;
uniform sampler2D uSampler;
uniform sampler2D uSampler1;
varying vec2 vTex;
void main() {
vec4 c1 = texture2D(uSampler,vTex);
vec4 c2 = texture2D(uSampler1,vTex);
gl_FragColor =c1 * c2;
}
`;
//片元着色器
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
const aPosition = gl.getAttribLocation(program, 'aPosition')
const aTex = gl.getAttribLocation(program, 'aTex')
const uSampler = gl.getUniformLocation(program, 'uSampler')
const uSampler1 = gl.getUniformLocation(program, 'uSampler1')
//1创建顶点数据
const points = new Float32Array([
-0.5,-0.5,0.0,1.0,
0.5,-0.5,0.0,0.0,
-0.5,0.5,1.0,1.0,
0.5,0.5,1.0,0.0,
])
//2创建缓存对象
const buffer = gl.createBuffer()
const BYTES = points.BYTES_PER_ELEMENT
//3绑定缓存区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
//4将数据写入缓存区 gl.bufferData(target,data,type)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
// 5将缓存区对象分配给一个attribute对象
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,BYTES * 4,0);
//6开启attribute变量
gl.enableVertexAttribArray(aPosition)
gl.vertexAttribPointer(aTex,2,gl.FLOAT,false,BYTES * 2,0);
gl.enableVertexAttribArray(aTex)
// gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
function getImage (url,location,index) {
return new Promise(resolve => {
const img = new Image()
img.onload= function () {
//创建文理对象
const texture = gl.createTexture()
//翻转图片 Y轴
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
//开启一个纹理单元
gl.activeTexture(gl[`TEXTURE${index}`])
//绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D,texture)
//处理放大缩小的逻辑
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR)
//横向 纵向 平铺的方式
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE)
//配置纹理图像
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,img)
gl.uniform1i(location,index)
resolve()
}
img.src=url
})
}
// function getImage1 () {
// return new Promise(resolve => {
// const img = new Image()
// img.onload= function () {
// //创建文理对象
// const texture = gl.createTexture()
// //翻转图片 Y轴
// gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
// //开启一个纹理单元
// gl.activeTexture(gl.TEXTURE1)
// //绑定纹理对象
// gl.bindTexture(gl.TEXTURE_2D,texture)
// //处理放大缩小的逻辑
// gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR)
// gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR)
// //横向 纵向 平铺的方式
// gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE)
// gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE)
// //配置纹理图像
// gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,img)
// gl.uniform1i(uSampler1,0)
// resolve()
// }
// img.src='../assets/1.png'
// })
// }
Promise.all([getImage('../assets/nice.png',uSampler,0), getImage('../assets/1.png',uSampler1,1)]).then(()=>{
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
})
</script>