所以我正在寻找WebGL纹理/ 3D渲染方面的帮助。
我的代码(我到目前为止所做的)是创建一个纹理块/立方体的3D迷宫,用户可以通过箭头键或WASD导航。我认为我遇到的问题就是texImage2d()。我相信。
我尝试过像
这样的事情 var stonePic = document.getElementById("stoneTex");
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, stonePic));
没有效果,导致this。
我也试过
var stonePic = new Image();
stonePic.src = "stoneWall2.png";
导致了同样的错误。
我做错了什么?我能解决它吗?
<HTML>
<HEAD>
<TITLE>Brick Wall Maze</TITLE>
<SCRIPT>
//VERTEX SHADER TEXT
var vertexShaderText =
[
'precision mediump float;',
'',
'attribute vec3 vertPosition;',
'attribute vec2 vertTexCoord;',
'varying vec2 fragTexCoord;',
'uniform vec3 theta;',
'uniform vec3 trans;',
'uniform float thetaC;',
'uniform vec3 camLoc;',
'void main()',
'{',
'fragTexCoord = vertTexCoord;',
'vec3 c = cos(theta);',
'vec3 s = sin(theta);',
'',
'mat4 ry = mat4(c.y,0.0,-1.0*s.y,0.0, 0.0,1.0,0.0,0.0, s.y,0.0,c.y,0.0, 0.0,0.0,0.0,1.0);',
'mat4 translate = mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, trans.x,trans.y,trans.z,1);',
'vec4 tempLoc = vec4(vertPosition, 1.0);',
'float l = -1.0;',
'float r = 1.0;',
'float t = 1.0;',
'float b = -1.0;',
'float f = 100.0;',
'float n = 1.0;',
'mat4 perspective = mat4(2.0*n/(r-l),0,0,0, 0,2.0*n/(t-b),0,0, (r+l)/(r-l),(t+b)/(t-b),-1.0*(f+n)/(f-n),-1.0, 0,0,-2.0*f*n/(f-n),0);',
'float tempc = cos(thetaC);',
'float temps = sin(thetaC);',
'mat4 camRY = mat4(tempc,0,-1.0*temps,0, 0,1,0,0, temps,0,tempc,0, 0,0,0,1);',
'mat4 viewM = mat4(1.0,0,0,0, 0,1.0,0,0, 0,0,1.0,0, camLoc.x,camLoc.y,camLoc.z,1.0);',
'gl_Position = perspective * camRY * viewM * translate * ry * tempLoc;',
'}'
].join("\n");
// FRAGMENT SHADER TEXT
var fragmentShaderText =
[
'precision mediump float;',
'varying vec2 fragTexCoord;',
'uniform sampler2D sampler;',
'void main()',
'{',
'gl_FragColor = texture2D(sampler, fragTexCoord);',
'}'
].join('\n');
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
function initializeGL()
{
var canvas = document.getElementById("screen");
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
if (!gl) { alert("WEBGL IS NOT AVAILABLE"); }
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.5, 0.7, 0.6 ,1.0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
return gl;
}
function initializeShaders(gl)
{
// VERTEX SHADER
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderText);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.log("ERROR: ",gl.getShaderInfoLog(vertexShader));
}
// FRAGMENT SHADER
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader,fragmentShaderText);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
console.log("ERROR: ",gl.getShaderInfoLog(fragmentShader));
}
// PROGRAM
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error("ERROR", gl.getShaderInfoLog(program));
}
gl.validateProgram(program);
if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) {
console.error("ERROR", gl.getShaderInfoLog(program));
}
return program;
}
// var brickTexture;
var stoneTexture;
function setupIndBuffers(gl, program, buffer)
{
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
positionAttributeLocation = gl.getAttribLocation(program, "vertPosition");
texCoordAttributeLocation = gl.getAttribLocation(program, "vertTexCoord");
gl.vertexAttribPointer(
positionAttributeLocation, //ATTRIBUTE LOCATION
3, //NUMBER of elements per attribute
gl.FLOAT, //TYPES OF ELEMENTS
gl.FALSE,
5*Float32Array.BYTES_PER_ELEMENT, //SIZE OF AN INDIVIDUAL VERTEX
0 //OFFSET
);
gl.vertexAttribPointer(
texCoordAttributeLocation, //ATTRIBUTE LOCATION
2, //NUMBER of elements per attribute
gl.FLOAT, //TYPES OF ELEMENTS
gl.FALSE,
5*Float32Array.BYTES_PER_ELEMENT, //SIZE OF AN INDIVIDUAL VERTEX
3*Float32Array.BYTES_PER_ELEMENT //OFFSET
);
gl.enableVertexAttribArray(positionAttributeLocation);
gl.enableVertexAttribArray(texCoordAttributeLocation);
}
function setupVertices(gl, program)
{
/*
// Brick Texture
brickTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, brickTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
var brickArray = [];
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
if (i == 0 || j == 0) {
// Push Black
brickArray.push(0, 0, 255);
}
else {
// Push Red
brickArray.push(220, 30, 30, 255);
}
}
}
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(brickArray));
gl.bindTexture(gl.TEXTURE_2D, null);
*/
// ~ ~ ~ ~ ~
// STONE TEXTURE
stoneTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, stoneTexture);
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.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, stonePic);
gl.bindTexture(gl.TEXTURE_2D, null);
}
/*
brickVertices =
[
// X, Y, Z U, V,
// Top
-1.0, 1.0, -1.0, 0.0, 0.0,
-1.0, 1.0, 1.0, 0.0, 10,
1.0, 1.0, 1.0, 10, 10,
1.0, 1.0, -1.0, 10, 0.0,
// Left
-1.0, 1.0, 1.0, 10,10,
-1.0, -1.0, 1.0, 0,10,
-1.0, -1.0, -1.0, 0,0,
-1.0, 1.0, -1.0, 10,0,
// Right
1.0, 1.0, 1.0, 10,10,
1.0, -1.0, 1.0, 0,10,
1.0, -1.0, -1.0, 0,0,
1.0, 1.0, -1.0, 10,0,
// Front
1.0, 1.0, 1.0, 10,10,
1.0, -1.0, 1.0, 10,0,
-1.0, -1.0, 1.0, 0,0,
-1.0, 1.0, 1.0, 0,10,
// Back
1.0, 1.0, -1.0, 10,10,
1.0, -1.0, -1.0, 10,0,
-1.0, -1.0, -1.0, 0,0,
-1.0, 1.0, -1.0, 0,10,
// Bottom
-1.0, -1.0, -1.0, 0,0,
-1.0, -1.0, 1.0, 0,10,
1.0, -1.0, 1.0, 10,10,
1.0, -1.0, -1.0, 10,0,
];
*/
stoneVertices =
[
// X, Y, Z U, V,
// Top
-1.0, 1.0, -1.0, 0.0, 0.0,
-1.0, 1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, -1.0, 1.0, 0.0,
// Left
-1.0, 1.0, 1.0, 1,1,
-1.0, -1.0, 1.0, 0,1,
-1.0, -1.0, -1.0, 0,0,
-1.0, 1.0, -1.0, 1,0,
// Right
1.0, 1.0, 1.0, 1,1,
1.0, -1.0, 1.0, 0,1,
1.0, -1.0, -1.0, 0,0,
1.0, 1.0, -1.0, 1,0,
// Front
1.0, 1.0, 1.0, 1,1,
1.0, -1.0, 1.0, 1,0,
-1.0, -1.0, 1.0, 0,0,
-1.0, 1.0, 1.0, 0,1,
// Back
1.0, 1.0, -1.0, 1,1,
1.0, -1.0, -1.0, 1,0,
-1.0, -1.0, -1.0, 0,0,
-1.0, 1.0, -1.0, 0,1,
// Bottom
-1.0, -1.0, -1.0, 0,0,
-1.0, -1.0, 1.0, 0,1,
1.0, -1.0, 1.0, 1,1,
1.0, -1.0, -1.0, 1,0,
];
/*
stoneVertices =
[
// X, Y, Z U, V,
// Top
-1.0, 1.0, -1.0, 0.0, 0.0,
-1.0, 1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, -1.0, 1.0, 0.0,
// Left
-1.0, 1.0, 1.0, 1,1,
-1.0, -1.0, 1.0, 0,1,
-1.0, -1.0, -1.0, 0,0,
-1.0, 1.0, -1.0, 1,0,
// Right
1.0, 1.0, 1.0, 1,1,
1.0, -1.0, 1.0, 0,1,
1.0, -1.0, -1.0, 0,0,
1.0, 1.0, -1.0, 1,0,
// Front
1.0, 1.0, 1.0, 1,1,
1.0, -1.0, 1.0, 1,0,
-1.0, -1.0, 1.0, 0,0,
-1.0, 1.0, 1.0, 0,1,
// Back
1.0, 1.0, -1.0, 1,1,
1.0, -1.0, -1.0, 1,0,
-1.0, -1.0, -1.0, 0,0,
-1.0, 1.0, -1.0, 0,1,
// Bottom
-1.0, -1.0, -1.0, 0,0,
-1.0, -1.0, 1.0, 0,1,
1.0, -1.0, 1.0, 1,1,
1.0, -1.0, -1.0, 1,0,
];
*/
class Cube
{
constructor(test)
{
this.tranLoc = gl.getUniformLocation(program, "trans");
this.thetaLoc = gl.getUniformLocation(program, "theta");
this.loc = [0, 0, 0];
if(test) {
this.verts = stoneBuffer;
this.texture = stoneTexture;
}
/*else {
this.verts = stoneBuffer;
this.texture = stoneTexture;
}*/
this.boxIndices =
[
// Top
0, 1, 2,
0, 2, 3,
// Left
5, 4, 6,
6, 4, 7,
// Right
8, 9, 10,
8, 10, 11,
// Front
13, 12, 14,
15, 14, 12,
// Back
16, 17, 18,
16, 18, 19,
// Bottom
21, 20, 22,
22, 20, 23
];
this.iBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.iBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(this.boxIndices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
render()
{
if (this.texture == stoneTexture) {
//gl.bindBuffer(gl.ARRAY_BUFFER,brickBuffer);
setupIndBuffers(gl, program, stoneBuffer);
}
/*else {
//gl.bindBuffer(gl.ARRAY_BUFFER,this.crateBuffer);
setupIndBuffers(gl, program, brickBuffer);
}*/
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.iBuffer);
var thetaV = [0, 0, 0];
gl.uniform3fv(this.tranLoc, new Float32Array(this.loc));
gl.uniform3fv(this.thetaLoc, new Float32Array(thetaV));
gl.drawElements(gl.TRIANGLES, this.boxIndices.length, gl.UNSIGNED_BYTE, 0);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
}
</SCRIPT>
</HEAD>
<BODY>
<CANVAS ID = "screen" WIDTH = "800" HEIGHT = "600" ALT = "Your browser does not support canvas."/>
<IMG ID = "stoneTex" SRC = "stoneWall2.png" WIDTH = "50" HEIGHT = "50" ALT = "tex"/>
<SCRIPT>
//Init GL System
var gl = initializeGL();
var program = initializeShaders(gl);
setupVertices(gl, program);
gl.useProgram(program);
//var stonePic = document.getElementById("stoneTex");
// SETUP BRICK BUFFER
/*var brickBuffer = gl.createBuffer();
setupIndBuffers(gl, program, brickBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(brickVertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
*/
// SETUP STONE BUFFER
var stoneBuffer = gl.createBuffer();
setupIndBuffers(gl, program, stoneBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(stoneVertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// Initialize and render actual objects.
var x = new Cube(true);
x.loc = [-5, 0, -10];
//var y = new Cube(false);
//y.loc = [5, 0, -10];
var loop = function()
{
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
x.render();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
</SCRIPT>
</BODY>
</HTML>
答案 0 :(得分:0)
你做错了不是等待图片加载。 Web浏览器中的图像是异步下载的。这意味着您必须等到他们下载才能调用gl.texImage2D
通常我会做这样的事情
// Create a texture.
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Fill the texture with a 1x1 blue pixel.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));
// Asynchronously load an image
var image = new Image();
image.src = "resources/f-texture.png";
image.addEventListener('load', function() {
// Now that the image has loaded make copy it to the texture.
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,gl.UNSIGNED_BYTE, image);
// if it's a power of 2 in both dimensions then
// we can generate mips, otherwise we'd have to do other things
gl.generateMipmap(gl.TEXTURE_2D);
});
texture
现在是一个纹理,您可以立即开始渲染它。当图像下载完成后,其内容将被复制到纹理中。此时您需要再次渲染,或者,如果像大多数WebGL应用程序一样,以及问题中的那个,您将继续渲染,那么它将在您的应用下次渲染时自动显示