我正在制作带纹理的金字塔,但收到一些警告。我从《 Beginning WebGL for HTML5》一书中逐步完成了它,但是它不起作用。
这是我的代码:
<!doctype html>
<html>
<head>
<title>Project 2</title>
<script type="text/javascript" src="gl-matrix-min.js"></script>
<style>
body{ background-color: grey; }
canvas{ background-color: white; }
</style>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 aVertexPosition;
attribute vec4 aVertexColor;
attribute vec2 aVertexTextureCoord;
varying highp vec2 vTextureCoord;
varying vec4 vColor;
/*
Couting On GPU
// Model matrix
uniform mat4 uMVMatrix;
// Projection matrix
uniform mat4 uPMatrix;
// View matrix
uniform mat4 uVMatrix;
*/
uniform mat4 uPVMatrix;
void main(void) {
vColor = aVertexColor;
gl_Position = uPVMatrix * aVertexPosition;
vTextureCoord = aVertexTextureCoord;
// gl_Position = uPMatrix * uVMatrix * uMVMatrix * aVertexPosition;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
varying highp vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vTextureCoord);
}
</script>
<script>
var gl = null,
canvas = null,
glProgram = null,
fragmentShader = null,
vertexShader = null;
var coordinateArray = [],
triangleVerticeColors = [],
verticesArray = [],
verticesIndexArray = [],
triangleTexCoords = [];
var vertexPositionAttribute = null,
trianglesVerticeBuffer = null,
vertexColorAttribute = null,
trianglesColorBuffer = null,
triangleVerticesIndexBuffer = null,
vertexTexCoordAttribute = null,
trianglesTexCoordBuffer = null;
var P = mat4.create(),
V = mat4.create(),
M = mat4.create(),
VM = mat4.create(),
PVM = mat4.create();
var uPVMMatrix;
var texture;
var textureImage = null;
function initWebGL() {
canvas = document.getElementById("my-canvas");
try {
gl = canvas.getContext("webgl") ||
canvas.getContext("experimental-webgl");
}catch(e){ }
if(gl) {
setupWebGL();
initShaders();
setupTexture();
setupBuffers();
//getMatrixUniforms();
//setMatrixUniforms();
//animationLoop();
drawScene();
}else{
alert( "Error: Your browser does not appear to" + "support WebGL.");
}
}
function animationLoop() {
var R = mat4.create();
var angle = 0;
var i =0;
var loop = function() {
angle = performance.now() / 1000 / 6 * 2 * Math.PI;
i++;
mat4.rotate(PVM, R, angle, [0, 1, 0]);
gl.uniformMatrix4fv(uPVMMatrix, false, PVM);
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
drawScene();
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
}
function setupWebGL() {
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.frontFace(gl.CW);
gl.cullFace(gl.BACK);
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
console.log(P);
console.log(V);
console.log(M);
// mat4.identity(M);
mat4.lookAt(V, [5, 0, -5], [0, 0, 0], [0, 1, 0]);
mat4.perspective(P, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 1000.0);
mat4.multiply(VM,V,M);
mat4.multiply(PVM,P,VM);
}
function initShaders() {
var fs_source = document.getElementById('shader-fs').innerHTML,
vs_source = document.getElementById('shader-vs').innerHTML;
vertexShader = makeShader(vs_source, gl.VERTEX_SHADER);
fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER);
glProgram = gl.createProgram();
gl.attachShader(glProgram, vertexShader);
gl.attachShader(glProgram, fragmentShader);
gl.linkProgram(glProgram);
if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
alert("Unable to initialize the shader program.");
}
gl.useProgram(glProgram);
uPVMMatrix = gl.getUniformLocation(glProgram, "uPVMatrix");
gl.uniformMatrix4fv(uPVMMatrix, false, PVM);
}
function loadTexture() {
textureImage = $("#troll").get(0);
setupTexture();
}
function setupTexture() {
texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNISGNED_BYTE, textureImage);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
glProgram.sampleUniform = gl.getUniformLocation(glProgram, "uSampler");
gl.uniform1i(glProgram.sampleUniform, 0);
if(!gl.isTexture(texture)) {
console.log("Error : Texture is invalid");
}
}
function makeShader(src, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert("Error compiling shader: " + gl.getShaderInfoLog(shader));
}
return shader;
}
function setupBuffers() {
// n-sides polygon
var n = 6;
var radius = 1;
var angle = (Math.PI * 2) / n;
var xCoordinate = 0;
var yCoordinate = 0;
for(var i = 0 ; i < n ; i++) {
var a = angle * i;
var xNewCoordinate = xCoordinate + radius * Math.cos(a);
var yNewCoordinate = yCoordinate + radius * Math.sin(a);
var zNewCoordinate = 0;
coordinateArray.push(xNewCoordinate);
coordinateArray.push(yNewCoordinate);
coordinateArray.push(zNewCoordinate);
}
verticesArray = [
//Bottom Face
0.0, 0.0, 0.0,
0.0, 0.0, -1.0,
1.0, 0.0, -1.0,
0.0, 0.0, 0.0,
1.0, 0.0, -1.0,
1.0, 0.0, 0.0,
//Front Face
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.5, 1.0, -0.5,
//Right Face
1.0, 0.0, 0.0,
1.0, 0.0, -1.0,
0.5, 1.0, -0.5,
//Back Face
1.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.5, 1.0, -0.5,
//Left Face
0.0, 0.0, -1.0,
0.0, 0.0, 0.0,
0.5, 1.0, -0.5,
];
trianglesVerticeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArray), gl.STATIC_DRAW);
verticesIndexArray = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 16, 17,
];
triangleVerticesIndexBuffer = gl.createBuffer();
triangleVerticesIndexBuffer.number_vertext_points = verticesIndexArray.length;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleVerticesIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(verticesIndexArray), gl.STATIC_DRAW);
triangleTexCoords = [
0.5000, 0.1910,
0.1910, 0.5000,
0.5000, 0.8090,
0.5000, 0.1910,
0.5000, 0.8090,
0.8090, 0.5000,
0.5000, 0.1910,
0.8090, 0.5000,
1.0000, 0.0000,
0.8090, 0.5000,
0.5000, 0.8090,
1.0000, 1.0000,
0.5000, 0.8090,
0.1910, 0.5000,
0.0000, 1.0000,
0.1910, 0.5000,
0.5000, 0.1910,
0.0000, 0.0000,
];
trianglesTexCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesTexCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleTexCoords), gl.STATIC_DRAW);
triangleVerticeColors = [
// Bottom quad
0.470, 0.796, 0.886,
0.470, 0.796, 0.886,
0.470, 0.796, 0.886,
0.470, 0.796, 0.886,
0.470, 0.796, 0.886,
0.470, 0.796, 0.886,
// Back triangle
0.772, 0.470, 0.886,
0.772, 0.470, 0.886,
0.772, 0.470, 0.886,
// Left triangle
0.886, 0.552, 0.470,
0.886, 0.552, 0.470,
0.886, 0.552, 0.470,
// Front triangle
0.886, 0.882, 0.470,
0.886, 0.882, 0.470,
0.886, 0.882, 0.470,
// Right triangle
0.470, 0.886, 0.505,
0.470, 0.886, 0.505,
0.470, 0.886, 0.505,
];
trianglesColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVerticeColors), gl.STATIC_DRAW);
}
// GPU
function getMatrixUniforms() {
glProgram.mvMatrixUniform = gl.getUniformLocation(glProgram, "uMVMatrix");
glProgram.pMatrixUniform = gl.getUniformLocation(glProgram, "uPMatrix");
glProgram.vMatrixUniform = gl.getUniformLocation(glProgram, "uVMatrix");
}
// GPU
function setMatrixUniforms() {
gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M);
gl.uniformMatrix4fv(glProgram.pMatrixUniform, false, P);
gl.uniformMatrix4fv(glProgram.vMatrixUniform, false, V);
}
function drawScene() {
vertexPositionAttribute = gl.getAttribLocation(glProgram, "aVertexPosition");
gl.enableVertexAttribArray(vertexPositionAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
vertexTexCoordAttribute = gl.getAttribLocation(glProgram, "aVertexTexCoord");
gl.enableVertexAttribArray(vertexTexCoordAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesTexCoordBuffer);
gl.vertexAttribPointer(vertexTexCoordAttribute, 2, gl.FLOAT, false, 0, 0);
/*vertexColorAttribute = gl.getAttribLocation(glProgram, "aVertexColor");
gl.enableVertexAttribArray(vertexColorAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer);
gl.vertexAttribPointer(vertexColorAttribute, 3, gl.FLOAT, false, 0, 0);
*/
gl.drawElements(gl.TRIANGLE_STRIP, triangleVerticesIndexBuffer.number_vertext_points, gl.UNSIGNED_SHORT, 0);
}
</script>
</head>
<body onload="initWebGL()">
<canvas id="my-canvas" width="800" height="600">
Your browser does not support the HTML5 canvas element.
</canvas>
<img src="./trollface.png" id="troll" />
</body>
</html>
我使用的纹理坐标如下所示:
这是纹理:
警告是关于超出范围的数组和关于图像未加载。
最佳答案
您的代码中有多个错误。
您的函数loadTexture()
不会被调用,因此纹理实际上不会被加载。
将setupTexture()
替换为loadTexture()
内的initWebGL()
。
您似乎也正在使用jQuery从DOM检索图像,但是您没有加载该库。
将$("#troll").get(0)
替换为document.getElementById("troll")
内的loadTexture()
。
纹理的尺寸需要为2的幂(128x32、256x256、512x1024等)
您应该将图片大小调整为256x256。
您使用texImage2D()
的参数之一打错了字。
在gl.UNISGNED_BYTE
调用内将gl.UNSIGNED_BYTE
替换为gl.texImage2D()
。
您的纹理坐标属性名称与您的gl.getAttribLocation()
调用和顶点着色器代码不匹配。
在aVertexTexCoord
调用内将aVertexTextureCoord
替换为gl.getAttribLocation()
。
如果要渲染单个三角形,请在gl.TRIANGLE_STRIP
调用内用gl.TRIANGLES
替换gl.drawElements()
。
如果您解决了所有这些错误,那么您的代码将正确运行。
关于javascript - 在WebGL中构造金字塔,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40554114/