1 Star 0 Fork 0

CDKEY / webgl-learn

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
5.加载纹理.html 12.26 KB
一键复制 编辑 原始数据 按行查看 历史
CDKEY 提交于 2021-07-09 04:11 . 7.9
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>5.加载纹理</title>
</head>
<body onload="main()">
<canvas id="glcanvas" width="640" height="480">
你的浏览器似乎不支持或者禁用了HTML5 <code>&lt;canvas&gt;</code> 元素.
</canvas>
<script src="./static/js/gl-matrix-min.js"></script>
<script>
/**
* 非2的幂纹理
* 一般来说,宽和高都是2的幂的纹理使用是最理想的。
* 2的幂纹理在渲染内存里的存储更高效,而且对它们的使用限制也更少
*
* 1.映射纹理到面
*/
var mat4 = glMatrix.mat4;
var cubeRotation = 0.0;
function main() {
var canvas = document.getElementById('glcanvas')
var gl = canvas.getContext("webgl")
if (!gl) {
alert('不支持webgl')
return;
}
const vsSource = `
attribute vec4 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
varying highp vec2 vTextureCoord;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
vTextureCoord = aTextureCoord;
}
`;
const fsSource = `
varying highp vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vTextureCoord);
}
`;
const shaderProgram = initShaderProgram(gl, vsSource, fsSource)
const programInfo = {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
textureCoord: gl.getAttribLocation(shaderProgram, 'aTextureCoord'),
},
uniformLocations: {
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
uSampler: gl.getUniformLocation(shaderProgram, 'uSampler'),
}
};
const buffers = initBuffers(gl)
const texture = loadTexture(gl, './static/img/FireFox.png');
var then = 0;
//
function render(now) {
now *= 0.001
const deltaTime = now - then
then = now
drawScene(gl, programInfo, buffers, texture, deltaTime)
cubeRotation += deltaTime;
requestAnimationFrame(render)
}
requestAnimationFrame(render);
}
// 初始化着色器
function initShaderProgram(gl, vsSource, fsSource) {
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource)
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader)
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('初始化着色器失败')
return null
}
return shaderProgram;
}
function loadShader(gl, type, source) {
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('初始化着色器失败')
gl.deleteShader(shader);
return null
}
return shader
}
function initBuffers(gl) {
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
// 定义立方体顶点位置
const positions = [
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
];
gl.bufferData(gl.ARRAY_BUFFER,
new Float32Array(positions),
gl.STATIC_DRAW)
// 映射纹理到面
const textureCoordBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer)
const textureCoordinates = [
// Front
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Back
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Top
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Bottom
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Right
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Left
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
];
gl.bufferData(gl.ARRAY_BUFFER,
new Float32Array(textureCoordinates),
gl.STATIC_DRAW);
// Build the element array buffer; this specifies the indices
// into the vertex arrays for each face's vertices.
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
// This array defines each face as two triangles, using the
// indices into the vertex array to specify each triangle's
// position.
const indices = [
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // back
8, 9, 10, 8, 10, 11, // top
12, 13, 14, 12, 14, 15, // bottom
16, 17, 18, 16, 18, 19, // right
20, 21, 22, 20, 22, 23, // left
];
// Now send the element array to GL
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(indices), gl.STATIC_DRAW);
return {
position: positionBuffer,
textureCoord: textureCoordBuffer,
indices: indexBuffer,
}
}
// 渲染场景
function drawScene(gl, programInfo, buffers, texture) {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0)
gl.enable(gl.DEPTH_TEST)
gl.depthFunc(gl.LEQUAL)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
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] // 翻转量
)
// 将modelViewMatrix的当前值cubeRotation绕Z轴旋转
mat4.rotate(modelViewMatrix,
modelViewMatrix,
cubeRotation,
[0, 0, 1])
mat4.rotate(modelViewMatrix,
modelViewMatrix,
cubeRotation * .7,
[1, 1, 0])
{
const numComponents = 3 //每次迭代提取2个值
const type = gl.FLOAT // buffer 类型是32bit float
const normalize = false // 不使用标准化
const stride = 0 //从一组值到下一组值需要多少字节
const offset = 0 //从缓冲区内多少字节开始
// setMatrixUniforms();
// 绘制正方形时使用颜色
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position)
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset
)
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexPosition
)
}
// 初始化颜色属性
{
const numComponents = 2 //每次迭代提取4个值
const type = gl.FLOAT // buffer 类型是32bit float
const normalize = false // 不使用标准化
const stride = 0 //从一组值到下一组值需要多少字节
const offset = 0 //从缓冲区内多少字节开始
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.textureCoord);
gl.vertexAttribPointer(
programInfo.attribLocations.textureCoord,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.textureCoord);
}
// 使用立方体顶点索引数据来渲染
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices)
gl.useProgram(programInfo.program)
gl.uniformMatrix4fv(
programInfo.uniformLocations.projectionMatrix,
false,
projectionMatrix
)
gl.uniformMatrix4fv(
programInfo.uniformLocations.modelViewMatrix,
false,
modelViewMatrix
)
// 告诉WebGL我们想要影响纹理单位0
gl.activeTexture(gl.TEXTURE0);
// 将纹理绑定到纹理单元0
gl.bindTexture(gl.TEXTURE_2D, texture);
// 告诉着色器我们将纹理绑定到纹理单元0
gl.uniform1i(programInfo.uniformLocations.uSampler, 0);
{
const vertexCount = 36;
const type = gl.UNSIGNED_SHORT;
const offset = 0;
gl.drawElements(gl.TRIANGLES, vertexCount, type, offset);
}
}
// 加载纹理
function loadTexture(gl, url) {
// 创建一个GL纹理对象
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Because images have to be download over the internet
// they might take a moment until they are ready.
// Until then put a single pixel in the texture so we can
// use it immediately. When the image has finished downloading
// we'll update the texture with the contents of the image.
const level = 0;
const internalFormat = gl.RGBA;
const width = 1;
const height = 1;
const border = 0;
const srcFormat = gl.RGBA;
const srcType = gl.UNSIGNED_BYTE;
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
// 把已经加载的图片图形数据写到纹理
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
width, height, border, srcFormat, srcType,
pixel);
const image = new Image();
image.onload = function () {
// 新创建的纹理对象绑定到 gl.TEXTURE_2D 来让它成为当前操作纹理。
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
srcFormat, srcType, image);
// WebGL1 has different requirements for power of 2 images
// vs non power of 2 images so check if the image is a
// power of 2 in both dimensions.
if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
// Yes, it's a power of 2. Generate mips.
gl.generateMipmap(gl.TEXTURE_2D);
} else {
// No, it's not a power of 2. Turn of mips and set
// wrapping to clamp to edge
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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// // 纹理过滤器,过滤器用来控制当图片缩放时像素如何生成如何插值。
// // 在这个例子里,我们对图片放大使用的是线性过滤,而对图片缩小使用的是多级渐进纹理过滤
// gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
// gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR_MIPMAP_NEAREST)
// // 生成多级渐进纹理
// gl.generateMipmap(gl.TEXTURE_2D)
// // null 来告诉 WebGL 我们对当前纹理的操作已经结束了
// gl.bindTexture(gl.TEXTURE_2D, null)
}
};
image.src = url;
return texture;
}
function isPowerOf2(value) {
return (value & (value - 1)) == 0;
}
</script>
</body>
</html>
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/Hebelove/webgl-learn.git
git@gitee.com:Hebelove/webgl-learn.git
Hebelove
webgl-learn
webgl-learn
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891