Я пытаюсь написать функцию куба для отключения от этого примера - почему появляется только один куб, когда я сделал несколько вызовов моей функции makeCube ().У меня есть предчувствие чего-то странного, когда я делаю матрицу push / pop.Я новичок в webgl и написал игру, уже использующую canvas2d, и хотел бы открыть opengl с помощью веб-браузера.Помогите!Я обещаю, что вы можете провести бета-тестирование моей первой 3d-игры. Что я делаю не так?(мой код указан ниже)
<html>
<head>
<title>Learning WebGL — lesson 4</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="glMatrix-0.9.5.min.js"></script>
<script type="text/javascript" src="webgl-utils.js"></script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec4 vColor;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
</script>
<script type="text/javascript">
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
}
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var shaderProgram;
function initShaders() {
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}
var mvMatrix = mat4.create();
var mvMatrixStack = [];
var pMatrix = mat4.create();
function mvPushMatrix() {
var copy = mat4.create();
mat4.set(mvMatrix, copy);
mvMatrixStack.push(copy);
}
function mvPopMatrix() {
if (mvMatrixStack.length == 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
}
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
function degToRad(degrees) {
return degrees * Math.PI / 180;
}
var pyramidVertexPositionBuffer;
var pyramidVertexColorBuffer;
var cubeVertexPositionBuffer;
var cubeVertexColorBuffer;
var cubeVertexIndexBuffer;
function initBuffers() {
pyramidVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
var vertices = [
// Front face
0.0, 1.0, 0.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
// Right face
0.0, 1.0, 0.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
// Back face
0.0, 1.0, 0.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
// Left face
0.0, 1.0, 0.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
pyramidVertexPositionBuffer.itemSize = 3;
pyramidVertexPositionBuffer.numItems = 12;
pyramidVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
var colors = [
// Front face
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
// Right face
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0,
// Back face
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
// Left face
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
pyramidVertexColorBuffer.itemSize = 4;
pyramidVertexColorBuffer.numItems = 12;
cubeVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
vertices = [
// Front 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,
// 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(vertices), gl.STATIC_DRAW);
cubeVertexPositionBuffer.itemSize = 3;
cubeVertexPositionBuffer.numItems = 24;
cubeVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
colors = [
[1.0, 0.0, 0.0, 1.0], // Front face
[1.0, 1.0, 0.0, 1.0], // Back face
[0.0, 1.0, 0.0, 1.0], // Top face
[1.0, 0.5, 0.5, 1.0], // Bottom face
[1.0, 0.0, 1.0, 1.0], // Right face
[0.0, 0.0, 1.0, 1.0] // Left face
];
var unpackedColors = [];
for (var i in colors) {
var color = colors[i];
for (var j=0; j < 4; j++) {
unpackedColors = unpackedColors.concat(color);
}
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
cubeVertexColorBuffer.itemSize = 4;
cubeVertexColorBuffer.numItems = 24;
cubeVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
12, 13, 14, 12, 14, 15, // Bottom face
16, 17, 18, 16, 18, 19, // Right face
20, 21, 22, 20, 22, 23 // Left face
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
cubeVertexIndexBuffer.itemSize = 1;
cubeVertexIndexBuffer.numItems = 36;
}
var rPyramid = 0;
var rCube = 0;
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [-1.5, 0.0, -8.0]);
mvPushMatrix();
mat4.rotate(mvMatrix, degToRad(rPyramid), [0, 1, 0]);
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, pyramidVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, pyramidVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, pyramidVertexPositionBuffer.numItems);
mvPopMatrix();
makeCube(
{'r':0.3,'g':0.3,'b':0.87,'a':1.0}, // color
{'x':3.5,'y':1.0,'z':2.0}, // position
{'x':0.0,'y':0.0,'z':0.0}, // rotation
0.5 // length
);
makeCube(
{'r':0.9,'g':0.7,'b':0.17,'a':1.0}, // color
{'x':3.5,'y':1.0,'z':2.0}, // position
{'x':0.0,'y':0.0,'z':0.0}, // rotation
0.5 // length
);
makeCube(
{'r':0.3,'g':0.3,'b':0.87,'a':1.0}, // color
{'x':3.5,'y':1.0,'z':2.0}, // position
{'x':0.0,'y':0.0,'z':0.0}, // rotation
0.1 // length
);
makeCube(
{'r':0.3,'g':0.5,'b':0.87,'a':1.0}, // color
{'x':0.5,'y':3.0,'z':12.0}, // position
{'x':0.0,'y':0.0,'z':0.0}, // rotation
0.8 // length
);
makeCube(
{'r':0.5,'g':0.3,'b':0.87,'a':1.0}, // color
{'x':0.1,'y':-3.0,'z':5.0}, // position
{'x':0.0,'y':0.0,'z':0.0}, // rotation
0.4 // length
);
}
var oCubeColorBuffer = null;
function _makeCubeColorBuffer(aColor){
oCubeColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, oCubeColorBuffer);
var aColors = [
[aColor.r, aColor.g, aColor.b, aColor.a], // Front face
[aColor.r, aColor.g, aColor.b, aColor.a], // Back face
[aColor.r, aColor.g, aColor.b, aColor.a], // Top face
[aColor.r, aColor.g, aColor.b, aColor.a], // Bottom face
[aColor.r, aColor.g, aColor.b, aColor.a], // Right face
[aColor.r, aColor.g, aColor.b, aColor.a] // Left face
];
var unpackedColors = [];
for (var i in aColors) {
var color = aColors[i];
for (var j=0; j < 4; j++) {
unpackedColors = unpackedColors.concat(color);
}
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
oCubeColorBuffer.itemSize = 4;
oCubeColorBuffer.numItems = 24;
return oCubeColorBuffer;
}
var oCubePositionBuffer = null;
function _makeCubePositionBuffer(fLength){
oCubePositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, oCubePositionBuffer);
var aVertices = [
// Front face
-1.0*fLength, -1.0*fLength, 1.0*fLength,
1.0*fLength, -1.0*fLength, 1.0*fLength,
1.0*fLength, 1.0*fLength, 1.0*fLength,
-1.0*fLength, 1.0*fLength, 1.0*fLength,
// Back face
-1.0*fLength, -1.0*fLength, -1.0*fLength,
-1.0*fLength, 1.0*fLength, -1.0*fLength,
1.0*fLength, 1.0*fLength, -1.0*fLength,
1.0*fLength, -1.0*fLength, -1.0*fLength,
// Top face
-1.0*fLength, 1.0*fLength, -1.0*fLength,
-1.0*fLength, 1.0*fLength, 1.0*fLength,
1.0*fLength, 1.0*fLength, 1.0*fLength,
1.0*fLength, 1.0*fLength, -1.0*fLength,
// Bottom face
-1.0*fLength, -1.0*fLength, -1.0*fLength,
1.0*fLength, -1.0*fLength, -1.0*fLength,
1.0*fLength, -1.0*fLength, 1.0*fLength,
-1.0*fLength, -1.0*fLength, 1.0*fLength,
// Right face
1.0*fLength, -1.0*fLength, -1.0*fLength,
1.0*fLength, 1.0*fLength, -1.0*fLength,
1.0*fLength, 1.0*fLength, 1.0*fLength,
1.0*fLength, -1.0*fLength, 1.0*fLength,
// Left face
-1.0*fLength, -1.0*fLength, -1.0*fLength,
-1.0*fLength, -1.0*fLength, 1.0*fLength,
-1.0*fLength, 1.0*fLength, 1.0*fLength,
-1.0*fLength, 1.0*fLength, -1.0*fLength
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(aVertices), gl.STATIC_DRAW);
oCubePositionBuffer.itemSize = 3;
oCubePositionBuffer.numItems = 24;
return oCubePositionBuffer;
}
var oCubeIndexBuffer = null;
function _makeCubeVertexIndexBuffer(){
oCubeIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, oCubeIndexBuffer);
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
12, 13, 14, 12, 14, 15, // Bottom face
16, 17, 18, 16, 18, 19, // Right face
20, 21, 22, 20, 22, 23 // Left face
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
oCubeIndexBuffer.itemSize = 1;
oCubeIndexBuffer.numItems = 36;
return oCubeIndexBuffer;
}
function makeCube(aColor, aPosition, aRotation, fLength){
mvPushMatrix();
mat4.translate(mvMatrix, [aPosition.x, aPosition.y, aPosition.z]);
// mat4.rotate(mvMatrix, degToRad(rCube), [aRotation.x, aRotation.y, aRotation.z]);
var oCubeVertexPositionBuffer = _makeCubePositionBuffer(fLength);
gl.bindBuffer(gl.ARRAY_BUFFER, oCubeVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, oCubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
var oCubeVertexColorBuffer = _makeCubeColorBuffer(aColor);
gl.bindBuffer(gl.ARRAY_BUFFER, oCubeVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, oCubeVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
var oCubeVertexIndexBuffer = _makeCubeVertexIndexBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, oCubeVertexIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, oCubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
mvPopMatrix();
}
var lastTime = 0;
function animate() {
var timeNow = new Date().getTime();
if (lastTime != 0) {
var elapsed = timeNow - lastTime;
rPyramid += (90 * elapsed) / 1000.0;
rCube -= (75 * elapsed) / 1000.0;
}
lastTime = timeNow;
}
function tick() {
requestAnimFrame(tick);
drawScene();
animate();
}
function webGLStart() {
var canvas = document.getElementById("lesson04-canvas");
initGL(canvas);
initShaders()
initBuffers();
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
tick();
}
</script>
</head>
<body onload="webGLStart();">
<a href="http://learningwebgl.com/blog/?p=370"><< Back to Lesson 4</a><br />
<canvas id="lesson04-canvas" style="border: none;" width="500" height="500"></canvas>
<br/>
<a href="http://learningwebgl.com/blog/?p=370"><< Back to Lesson 4</a><br />
<!-- Google Analytics stuff, please ignore - nothing to do with WebGL :-) -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-2240015-5");
pageTracker._trackPageview();
} catch(err) {
}
</script>
</body>
</html>