2012-07-02 33 views
5

Tôi muốn sử dụng 6 họa tiết khác nhau trên hình lập phương, mỗi hình một bên, nhưng không thể tìm thấy lỗi. Đây là mã hiện tại của tôi:Cách sử dụng nhiều họa tiết trong WebGL?

var texturen = new Array(); 
function initTexture(sFilename,texturen) 
{ 
    var anz = texturen.length; 
    texturen[anz] = gl.createTexture(); 
    texturen[anz].image = new Image(); 
    texturen[anz].image.onload = function()  
    { 
    gl.bindTexture(gl.TEXTURE_2D, texturen[anz]); 
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); 
    gl.texImage2D 
    (gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texturen[anz].image); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 
    gl.bindTexture(gl.TEXTURE_2D, null); 
    } 
    texturen[anz].image.src = sFilename; 
} 


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 cubeVertexPositionBuffer; 
var cubeVertexTextureCoordBuffer; 
var cubeVertexIndexBuffer; 
var cubeVertexPositionBuffer1; 
var cubeVertexTextureCoordBuffer1; 
var cubeVertexIndexBuffer1; 


function initBuffers() { 
    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, 
    ]; 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); 
    cubeVertexPositionBuffer.itemSize = 3; 
    cubeVertexPositionBuffer.numItems = 12; 

cubeVertexPositionBuffer1 = gl.createBuffer(); 
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer1); 
    vertices = [ 
     // 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); 
    cubeVertexPositionBuffer1.itemSize = 3; 
    cubeVertexPositionBuffer1.numItems = 12; 


    cubeVertexTextureCoordBuffer = gl.createBuffer(); 
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer); 
    var textureCoords = [ 
     // Front face 
     0.0, 0.0, 
     1.0, 0.0, 
     1.0, 1.0, 
     0.0, 1.0, 

     // Back face 
     1.0, 0.0, 
     1.0, 1.0, 
     0.0, 1.0, 
     0.0, 0.0, 

     // Top face 
     0.0, 1.0, 
     0.0, 0.0, 
     1.0, 0.0, 
     1.0, 1.0, 
    ]; 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW); 
    cubeVertexTextureCoordBuffer.itemSize = 2; 
    cubeVertexTextureCoordBuffer.numItems = 12; 



cubeVertexTextureCoordBuffer1 = gl.createBuffer(); 
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer1); 
    var textureCoords = [ 
    // Bottom face 
     1.0, 1.0, 
     0.0, 1.0, 
     0.0, 0.0, 
     1.0, 0.0, 

     // Right face 
     1.0, 0.0, 
     1.0, 1.0, 
     0.0, 1.0, 
     0.0, 0.0, 

     // Left face 
     0.0, 0.0, 
     1.0, 0.0, 
     1.0, 1.0, 
     0.0, 1.0, 
    ]; 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW); 
    cubeVertexTextureCoordBuffer1.itemSize = 2; 
    cubeVertexTextureCoordBuffer1.numItems = 12; 

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 
    ]; 
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW); 
    cubeVertexIndexBuffer.itemSize = 1; 
    cubeVertexIndexBuffer.numItems = 18; 

cubeVertexIndexBuffer1 = gl.createBuffer(); 
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer1); 
    var cubeVertexIndices = [ 
     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); 
    cubeVertexIndexBuffer1.itemSize = 1; 
    cubeVertexIndexBuffer1.numItems = 18; 



} 


var xRot = 0; 
var yRot = 0; 
var zRot = 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, [0.0, 0.0, -5.0]); 

    mat4.rotate(mvMatrix, degToRad(xRot), [1, 0, 0]); 
    mat4.rotate(mvMatrix, degToRad(yRot), [0, 1, 0]); 
    mat4.rotate(mvMatrix, degToRad(zRot), [0, 0, 0]); 
    setMatrixUniforms(); 

gl.activeTexture(gl.TEXTURE0); 
gl.bindTexture(gl.TEXTURE_2D, texturen[0]); 
gl.vertexAttribPointer 
(textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0); 
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer); 
    gl.vertexAttribPointer 
    (shaderProgram.vertexPositionAttribute,cubeVertexPositionBuffer.itemSize, 
    gl.FLOAT, false, 0, 0); 

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer); 

    gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0); 


gl.activeTexture(gl.TEXTURE1); 
gl.bindTexture(gl.TEXTURE_2D, texturen[1]); 
gl.vertexAttribPointer 
(textureCoordAttribute, cubeVertexTextureCoordBuffer1.itemSize, gl.FLOAT, false, 0, 0); 
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer1); 
gl.vertexAttribPointer 
(shaderProgram.vertexPositionAttribute,cubeVertexPositionBuffer1.itemSize, 
    gl.FLOAT, false, 0, 0); 


    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer1); 

    gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer1.numItems, gl.UNSIGNED_SHORT, 0); 


} 

tôi chỉ chia thành hai phần, cố gắng thử nghiệm với 2 bức ảnh khác nhau. Và cubeVertexIndexBuffers chính xác là gì?

Trả lời

14

Trước hết, câu trả lời ngắn: Thay thế 10 dòng cuối cùng của mã của bạn bằng những điều sau đây và tôi nghĩ rằng nó sẽ hoạt động.

gl.activeTexture(gl.TEXTURE0); 
gl.bindTexture(gl.TEXTURE_2D, texturen[1]); 
gl.vertexAttribPointer(textureCoordAttribute, cubeVertexTextureCoordBuffer1.itemSize, gl.FLOAT, false, 0, 0); 
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer1); 
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,cubeVertexPositionBuffer1.itemSize, gl.FLOAT, false, 0, 0); 

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer); 
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0); 

Những thay đổi chính là:

  • activeTexture vẫn là TEXTURE0 (bạn chỉ sử dụng một kết cấu tại một thời điểm ở đây)
  • Sử dụng cubeVertexIndexBuffer thay vì cubeVertexIndexBuffer1, trong đó có out-of- các chỉ báo phạm vi

Để có giải thích tốt hơn về các chỉ số thực sự được sử dụng cho Tôi sẽ giới thiệu bạn đến this SO question vì tôi không muốn lặp lại tất cả những gì ở đây.

Bây giờ, với câu trả lời chung chung hơn.

Có hai cách cơ bản để xử lý vấn đề sử dụng họa tiết khác nhau trên các khuôn mặt khác nhau. Phương pháp đầu tiên và đơn giản hơn là thực hiện chính xác những gì bạn đang làm ở đây: Render đối tượng theo từng phần, ràng buộc một texture khác nhau cho mỗi phần. Mặc dù không phải là cách hiệu quả nhất để hoàn thành hiệu ứng nhưng cách phổ biến nhất để xử lý nó trong các ứng dụng hiệu suất cao như trò chơi đơn giản là vì nó cung cấp nhiều tính linh hoạt, đặc biệt khi vật liệu của bạn phức tạp hơn kết cấu khuếch tán đơn giản .

Có một cách đơn giản để bạn có thể cải thiện hiệu suất của mã như mã của bạn cho trường hợp như thế này. Các đỉnh/chỉ mục không cần phải được chia thành các bộ đệm riêng biệt cho mỗi kết cấu. Bạn thay vì có thể kết hợp tất cả chúng vào một bộ đệm đơn và đưa ra chúng với hiệu số khác nhau như sau:

// On Init 
var vertBuffer = gl.createBuffer(); 
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer); 
var vertices = [ 
    // Vertex values for all 6 faces 
]; 
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); 

var indexBuffer = gl.createBuffer(); 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 
var indices = [ 
    // Index values for all 6 faces 
]; 
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); 

// On Draw 
// Setup the shader and uniforms and all that jazz 

gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer); 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 
gl.vertexAttribPointer(// Blah blah blah...); 

// Draw face 0 
gl.bindTexture(gl.TEXTURE_2D, texture[0]); 
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 

// Draw face 1 
gl.bindTexture(gl.TEXTURE_2D, texture[1]); 
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 12); 

// Draw face 2 
gl.bindTexture(gl.TEXTURE_2D, texture[2]); 
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 24); 

// .. And so on to face 5 
// Draw face 2 
gl.bindTexture(gl.TEXTURE_2D, texture[5]); 
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 60); 

gì đang xảy ra ở đây là mỗi cuộc gọi đến drawElements chỉ vẽ 2 hình tam giác (6 đỉnh, tham số thứ hai của cuộc gọi), nhưng mỗi cuộc gọi được bù đắp vào bộ đệm chỉ mục để nó bắt đầu trên một khuôn mặt khác. (tham số thứ tư của cuộc gọi, biểu thị độ lệch byte. Mỗi chỉ mục là Uint16, vì vậy 2 byte cho mỗi chỉ mục. 12 == "start on index [6]") Bằng cách này tất cả các ràng buộc và thiết lập chỉ xảy ra một lần, và mỗi cuộc gọi vẽ chỉ phải thay đổi trạng thái thực sự cần thiết (kết cấu). Một cách khác để xử lý điều này, nhanh hơn nhưng khó tổng quát hơn, là liên kết một mảng các kết cấu với đồng phục đổ bóng và sử dụng một thuộc tính đỉnh khác để lập chỉ mục vào mảng trong bóng đổ. Tôi sẽ không trình bày chi tiết mã cho cách tiếp cận này nhưng nó sẽ tương đối dễ dàng để thiết lập khi bạn thấy thoải mái với việc sử dụng shader WebGL. Nếu bạn có thêm câu hỏi về cách tiếp cận cụ thể này, tốt nhất nên hỏi trong một câu hỏi SO khác để không làm quá tải câu hỏi này.

+0

Tôi đã nhập mọi thứ bạn đã viết, nhưng nó vẫn không hoạt động:/tôi có thể gửi lại cho bạn mã không? :) – Applecow

+0

[câu hỏi mới] (http://stackoverflow.com/questions/11306460/how-to-use-multiple-textures-on-a-cube-in-webgl) – Applecow

+0

@Toji Tôi muốn biết về "mảng kết cấu" mà bạn ám chỉ - xem http: // stackoverflow.com/questions/19592850/làm cách nào để liên kết-một-mảng-của-kết cấu-tới-một-webgl-shader-đồng phục cho một câu hỏi mới, vui lòng. Cảm ơn – virtualnobi

Các vấn đề liên quan