更改webgl数组缓冲区不保留uv坐标

时间:2017-04-13 16:01:47

标签: textures webgl

我一直在墙上撞了一会儿。 我正在使用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>
	
	

1 个答案:

答案 0 :(得分:0)

您需要在 EACH 绘制调用之前设置属性(或者更确切地说,您想要绘制不同的内容)。或者使用顶点数组对象。

每个属性都有一个缓冲区的引用。该引用是在您为某些属性调用gl.vertexAttribPointer时设置的。因此,要在该属性上使用不同的缓冲区进行绘制,您需要先调用gl.bindBuffer(gl.ARRAY_BUFFER, bufferYouWantTheAttributeToUse),然后调用gl.vertexAttribPointer来设置属性使用该缓冲区。

See this explanation for more

另外see this