1、图片不显示:图片分辨率为非2的幂次方,图片不能被渲染。图形变成黑方块
2的N次幂:1 2 4 8 16 32 64 128 256 512 1024 2048 4096……
2、几何图形配置映射方式,顶点坐标和纹理坐标对应需要注意,构建顺序与新增顶点的奇偶性相关。
如果新增顶点时奇数,顶点排列顺序为:T = [n-1 n-2 n];
如果新增顶点为偶数,顶点排列顺序为:T = [n-2 n-1 n];
图片素材:
链接: https://pan.baidu.com/s/1CQ2fZ36Ke8QfGFDytFkyQw
提取码: 3dh4
关键代码:
function initTexture(ctx) {
let texture = ctx.createTexture()
let u_sampler = ctx.getUniformLocation(ctx.program, "u_sampler")
let image = new Image()
image.crossOrigin = "anonymous"
image.src = "http://localhost:8080/upload/dog.webp"
//异步加载,图片加载完成之后执行这个函数里的任务
image.onload = () => {
//对纹理图像进行y轴反转,是否翻转
ctx.pixelStorei(ctx.UNPACK_FLIP_Y_WEBGL, true);
//默认可以贴8张图片,从索引0开始,这里激活第一个
ctx.activeTexture(ctx.TEXTURE0)
//以TEXTURE_2D方式绑定贴图
ctx.bindTexture(ctx.TEXTURE_2D, texture)
//对贴图的参数进行设置texParameteri(贴图的种类,参数的名称,具体值)
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR)
//设置纹理贴图填充方式(纹理贴图像素尺寸小于顶点绘制区域像素尺寸)
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR)
console.log(image)
//贴图用那种图片进行贴图
ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, image)
//将第0张贴图贴到u_sampler
ctx.uniform1i(u_sampler, 0)
draw(ctx)
}
}
html
*{
margin: 0px;
padding: 0px;
}
您的浏览器不支持HTML5,请更换浏览器
main.js
let canvas = document.getElementById('webgl')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
let radio = window.innerWidth / window.innerHeight;
let ctx = canvas.getContext('webgl')
//创建顶点资源和像素资源(颜色)
let vertexSource = `
attribute vec2 a_position;
attribute vec2 a_uv;
varying vec2 v_uv;
void main() {
v_uv = a_uv;
gl_Position = vec4(a_position, 0.0, 1.0);
gl_PointSize = 10.0;
}
`
let fragmentSource = `
precision mediump float;
varying vec2 v_uv;
uniform sampler2D u_sampler;
void main (){
vec4 color = texture2D(u_sampler, v_uv);
gl_FragColor = color;
}
`
//gl_FragColor = vec4(v_uv, 0.0, 1.0);
if (initShader(ctx, vertexSource, fragmentSource)) {
let box = [
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
-0.5, 0.5
]
let boxFloat32Array = new Float32Array(box)
//创建buffer
let buffer = ctx.createBuffer()
//绑定buffer
ctx.bindBuffer(ctx.ARRAY_BUFFER, buffer)
//往buffer中填充值,并指定数据用途
ctx.bufferData(ctx.ARRAY_BUFFER, boxFloat32Array, ctx.STATIC_DRAW)
//获取vertexShader指定变量内存
let a_Position = ctx.getAttribLocation(ctx.program, "a_position")
//指定每两个数组元素为一个点
/*
* 当数组元素不需进行分割拆分的时候最后两位可以指定为0,0
*
*
*/
ctx.vertexAttribPointer(
a_Position, //location: vertex Shader里面的attributes变量的location
2, ctx.FLOAT, //size: attribute变量的长度 vec2长度2 vec3长度3
false, //normalized: 正交化 true或false , [1, 2] => [1/根号5, 2/根号5]
2 * boxFloat32Array.BYTES_PER_ELEMENT, //stride: 每个点的信息所占的BYTES
0 //offset: 每个点的信息,从第几个BYTES开始数
)
ctx.enableVertexAttribArray(a_Position);
let color = [
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
]
let colorFloat32Array = new Float32Array(color)
let colorBuffer = ctx.createBuffer()
ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer)
ctx.bufferData(ctx.ARRAY_BUFFER, colorFloat32Array, ctx.STATIC_DRAW)
let a_uv = ctx.getAttribLocation(ctx.program, "a_uv")
ctx.vertexAttribPointer(a_uv, 2, ctx.FLOAT, false, 2 * colorFloat32Array.BYTES_PER_ELEMENT, 0)
ctx.enableVertexAttribArray(a_uv)
initTexture(ctx)
}
function draw(ctx) {
ctx.clearColor(0.0, 0.0, 0.0, 1.0)
ctx.clear(ctx.COLOR_BUFFER_BIT)
ctx.drawArrays(ctx.TRIANGLE_FAN,
0,//从第几个点开始
4 //画几个点)
)
// ctx.drawArrays(ctx.TRIANGLE_FAN,
// 0,//从第几个点开始
// 4 //画几个点)
// )
}
function initTexture(ctx) {
let texture = ctx.createTexture()
let u_sampler = ctx.getUniformLocation(ctx.program, "u_sampler")
let image = new Image()
image.crossOrigin = "anonymous"
image.src = "http://localhost:8080/upload/dog.webp"//需要更改资源地址
//异步加载,图片加载完成之后执行这个函数里的任务
image.onload = () => {
//对纹理图像进行y轴反转
ctx.pixelStorei(ctx.UNPACK_FLIP_Y_WEBGL, 1);
//默认可以贴8张图片,从索引0开始,这里激活第一个
ctx.activeTexture(ctx.TEXTURE0)
//以TEXTURE_2D方式绑定贴图
ctx.bindTexture(ctx.TEXTURE_2D, texture)
//对贴图的参数进行设置texParameteri(贴图的种类,参数的名称,具体值)
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR)
//设置纹理贴图填充方式(纹理贴图像素尺寸小于顶点绘制区域像素尺寸)
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR)
console.log(image)
//贴图用那种图片进行贴图
ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, image)
//将第0张贴图贴到u_sampler
ctx.uniform1i(u_sampler, 0)
draw(ctx)
}
}
//创建顶点阴影和像素阴影
function createShader(ctx, type, source) {
//创建shader
let shader = ctx.createShader(type)
//绑定
ctx.shaderSource(shader, source)
//编译shader
ctx.compileShader(shader)
//获取编译结果
let compiler = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS)
if (compiler) {
return shader
} else {
let log = ctx.getShaderInfoLog(shader)
console.log("compile shaders error", log)
//删除异常的shader,防止内存泄露
ctx.deleteShader(shader)
return null
}
}
function createProgram(ctx, vertexShader, fragmentShader) {
//创建program
let program = ctx.createProgram()
if (!program) {
return null
}
//点资源和像素资源合并
ctx.attachShader(program, vertexShader)
ctx.attachShader(program, fragmentShader)
ctx.linkProgram(program)
//获取linked的结果
let linked = ctx.getProgramParameter(program, ctx.LINK_STATUS)
if (linked) {
return program
} else {
//获取link错误信息
let log = ctx.getProgramInfoLog(program)
console.log("link program error", log)
//删除防止内存泄漏
ctx.delete(program)
ctx.deleteShader(vertexShader)
ctx.deleteShader(fragmentShader)
return null
}
}
function initShader(ctx, vertexSource, fragmentSource) {
let vertexShader = createShader(ctx, ctx.VERTEX_SHADER, vertexSource)
let fragmentShader = createShader(ctx, ctx.FRAGMENT_SHADER, fragmentSource)
let program = createProgram(ctx, vertexShader, fragmentShader)
if (program) {
ctx.useProgram(program)
//挂载到ctx
ctx.program = program
return true
} else {
return false
}
}
效果图