我一直在墙上撞了一会儿。
我正在使用webgl,我必须设置顶点集。 (x,y和z是相同的,但我也包括你,v为纹理。)
纹理贴图的一组从0到1,另一组从0到10(为了重复纹理。
但是,根据我最后设置的数组缓冲区,这是唯一使用的UV。
//SETUP Crate Texture
var crateBuffer = gl.createBuffer();
setupIndBuffers(gl,program,crateBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(crateVerts),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
//Setup brick vertex buffer (and UV)
var brickBuffer = gl.createBuffer();
setupIndBuffers(gl,program,brickBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(brickVerts),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
这将导致纹理重复10次
然而,
//Setup brick vertex buffer (and UV)
var brickBuffer = gl.createBuffer();
setupIndBuffers(gl,program,brickBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(brickVerts),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
//SETUP Crate Texture
var crateBuffer = gl.createBuffer();
setupIndBuffers(gl,program,crateBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(crateVerts),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
这将使两个纹理不重复。最初我试图将数组缓冲区放在对象中,我认为这是一个javaScript绑定问题。然而,这似乎不是问题。
欢迎任何建议或意见。
这是我的整个代码:
//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");
var fragmentShaderText =
[
'precision mediump float;',
'varying vec2 fragTexCoord;',
'uniform sampler2D sampler;//samplers appear in order defined',
'void main()',
'{',
'gl_FragColor = texture2D(sampler,fragTexCoord);',
'}'
].join('\n');
function getGL()
{
var c = document.getElementById("MyScreen");
var gl = c.getContext("webgl")||c.getContext("experimental-webgl");
if(!gl)
{
alert("WEBGL IS NOT AVAILABLE");
}
gl.viewport(0,0,c.width, c.height);
gl.clearColor(.6,.6,1.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
//VERY IMPORTANT
gl.enable(gl.DEPTH_TEST);
return gl;
}
function initShaderProgram(gl)
{
//Setup shaders
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader,vertexShaderText);
gl.shaderSource(fragmentShader,fragmentShaderText);
gl.compileShader(vertexShader);
if(!gl.getShaderParameter(vertexShader,gl.COMPILE_STATUS))
{
console.log("ERROR: ",gl.getShaderInfoLog(vertexShader));
}
gl.compileShader(fragmentShader);
if(!gl.getShaderParameter(fragmentShader,gl.COMPILE_STATUS))
{
console.log("ERROR: ",gl.getShaderInfoLog(fragmentShader));
}
//Setup 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 checkeredTexture;
var XTexture;
function setupIndBuffers(gl,program, buff)
{
gl.bindBuffer(gl.ARRAY_BUFFER,buff);
positionAttributeLcoation = gl.getAttribLocation(program,'vertPosition');
texCoordAttributeLocation = gl.getAttribLocation(program,'vertTexCoord');
gl.vertexAttribPointer(
positionAttributeLcoation, //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(positionAttributeLcoation);
gl.enableVertexAttribArray(texCoordAttributeLocation);
}
function setupVertices(gl,program)
{
checkeredTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, checkeredTexture);
//Sets up our S
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S,gl.REPEAT); //gl.MIRRORED_REPEAT//gl.CLAMP_TO_EDGE
//Sets up our T
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.REPEAT); //gl.MIRRORED_REPEAT//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);
//Actually get our texture;
var myPic = [];
for(i =0; i < 16; i ++)
{
for(j =0; j< 16; j ++)
{
if(i%2 == j%2)
{
//Push red
myPic.push(0,255,0,255);
}
else
{
myPic.push(128,255,128,255);
}
}
}
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,16,16,0,gl.RGBA,gl.UNSIGNED_BYTE,new Uint8Array(myPic));
gl.bindTexture(gl.TEXTURE_2D,null);
//
//
//
//Brick Texture
//
//
brickTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, brickTexture);
//Sets up our S
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);//gl.CLAMP_TO_EDGE
//Sets up our T
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T,gl.MIRRORED_REPEAT);//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);
var myPic2 = [];
for(i =0; i < 16; i ++)
{
for(j =0; j< 16; j ++)
{
if(i == 0 || j ==0)
{
//Push Black
myPic2.push(0,0,0,255);
}
else
{
myPic2.push(255,30,30,255);
}
}
}
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,16,16,0,gl.RGBA,gl.UNSIGNED_BYTE,new Uint8Array(myPic2));
gl.bindTexture(gl.TEXTURE_2D,null);
//
//X TEXTURE/
//
XTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, XTexture);
//Sets up our S
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);//gl.CLAMP_TO_EDGE
//Sets up our T
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T,gl.MIRRORED_REPEAT);//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);
var myPic2 = [];
for(i =0; i < 16; i ++)
{
for(j =0; j< 16; j ++)
{
if(i == 0 || j ==0 || i == 15 || j == 15 || i ==j || i+j == 15)
{
//Push red
myPic2.push(0,0,0,255);
}
else
{
myPic2.push(137,63,69,255);
}
}
}
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,16,16,0,gl.RGBA,gl.UNSIGNED_BYTE,new Uint8Array(myPic2));
gl.bindTexture(gl.TEXTURE_2D,null);
gl.activeTexture(gl.TEXTURE0);
}
//
//Initializing the GL context
//
brickVerts =
[
// 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,
];
crateVerts = [
// 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 = brickBuffer;
this.tex = brickTexture;
}
else
{
this.verts = crateBuffer;
this.tex = XTexture;
}
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()
{
gl.bindBuffer(gl.ARRAY_BUFFER,this.verts);
gl.bindTexture(gl.TEXTURE_2D, this.tex);
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);
}
}
//Init GL System
var gl = getGL();
var program = initShaderProgram(gl);
setupVertices(gl,program);
gl.useProgram(program);
//Setup brick vertex buffer (and UV)
var brickBuffer = gl.createBuffer();
setupIndBuffers(gl,program,brickBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(brickVerts),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
//SETUP Crate Texture
var crateBuffer = gl.createBuffer();
setupIndBuffers(gl,program,crateBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(crateVerts),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();
y.render();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
<img id="tex" src = "https://opengameart.org/sites/default/files/cratetex.png" alt="texture" width = "0" height = "0" />
<CANVAS ID ="MyScreen" width="400" Height="250" alt="Your browser does not support canvas"></CANVAS>
答案 0 :(得分:0)
您需要在 EACH 绘制调用之前设置属性(或者更确切地说,您想要绘制不同的内容)。或者使用顶点数组对象。
每个属性都有一个缓冲区的引用。该引用是在您为某些属性调用gl.vertexAttribPointer
时设置的。因此,要在该属性上使用不同的缓冲区进行绘制,您需要先调用gl.bindBuffer(gl.ARRAY_BUFFER, bufferYouWantTheAttributeToUse)
,然后调用gl.vertexAttribPointer
来设置属性使用该缓冲区。
另外see this