将不同的纹理应用于场景中的不同对象

时间:2020-07-08 10:30:17

标签: javascript graphics webgl textures

我想简单地在场景中添加两个具有各自纹理的不同对象。 但是,在正确绘制对象的同时,碰巧第二个纹理同时应用于两个对象,并且显然不是我想要的。

我正在尝试尽可能多地泛化代码,但从现在起,我仍然没有解决方案。

var programs = new Array();
var gl;
var shaderDir;
var baseDir;
var boatModel;
var rockModel;



var modelStr = Array();
var modelTexture = Array();

modelStr[0] = 'Assets/Boat/Boat.obj';
modelStr[1] = 'Assets/Rocks/Rock1/rock1.obj';

modelTexture[0] = 'Assets/Boat/textures/boat_diffuse.bmp';
modelTexture[1] = 'Assets/Rocks/Rock1/textures/rock_low_Base_Color.png';

function main() {

  utils.resizeCanvasToDisplaySize(gl.canvas);
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.clearColor(0.85, 1.0, 0.85, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.enable(gl.DEPTH_TEST);

  var lastUpdateTime = (new Date).getTime();

  var Rx_rock = 0.0;
  var Ry_rock = 0.0;
  var Rz_rock = 0.0;
  var S_rock = 1.0 / 10;
  var x_rock = 5.0;
  var y_rock = 0.0;
  var z_rock = 0.0;

  var Rx_boat = 90.0;
  var Ry_boat = 45.0;
  var Rz_boat = 0.0;
  var y_boat = 0.0;
  var z_boat = 0.0;
  var x_boat = -2;
  var S_boat = 1.0 / 300.0;

  utils.resizeCanvasToDisplaySize(gl.canvas);

  var objectVertices = Array();
  var objectNormals = Array();
  var objectIndices = Array();
  var objectTexCoords = Array();

  objectVertices[0] = boatModel.vertices;
  objectNormals[0] = boatModel.vertexNormals;
  objectIndices[0] = boatModel.indices;
  objectTexCoords[0] = boatModel.textures;

  objectVertices[1] = rockModel.vertices;
  objectNormals[1] = rockModel.vertexNormals;
  objectIndices[1] = rockModel.indices;
  objectTexCoords[1] = rockModel.textures;





  var positionAttributeLocation = new Array();
  var uvAttributeLocation = new Array();
  var matrixLocation = new Array();
  var textLocation = new Array();

  positionAttributeLocation[0] = gl.getAttribLocation(programs[0], "a_position");
  uvAttributeLocation[0] = gl.getAttribLocation(programs[0], "a_uv");
  matrixLocation[0] = gl.getUniformLocation(programs[0], "matrix");
  textLocation[0] = gl.getUniformLocation(programs[0], "u_texture");

  positionAttributeLocation[1] = gl.getAttribLocation(programs[1], "a_position");
  uvAttributeLocation[1] = gl.getAttribLocation(programs[1], "a_uv");
  matrixLocation[1] = gl.getUniformLocation(programs[1], "matrix");
  textLocation[1] = gl.getUniformLocation(programs[1], "u_texture");

  objectWorldMatrix = new Array();

  objectWorldMatrix[0] = utils.MakeWorld(x_boat, y_boat, z_boat, Rx_boat, Ry_boat, Rz_boat, S_boat);
  objectWorldMatrix[1] = utils.MakeWorld(x_rock, y_rock, z_rock, Rx_rock, Ry_rock, Rz_rock, S_rock);

  var perspectiveMatrix = utils.MakePerspective(90, gl.canvas.width / gl.canvas.height, 0.1, 100.0);
  var viewMatrix = utils.MakeView(0.0, 0.0, 3.0, 0.0, 0.0);
  var vaos = new Array();




  for (i = 0; i < 2; i++) {
    vaos[i] = gl.createVertexArray();
    gl.bindVertexArray(vaos[i]);

    var positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(objectVertices[i]), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(positionAttributeLocation[i]);
    gl.vertexAttribPointer(positionAttributeLocation[i], 3, gl.FLOAT, false, 0, 0);

    var uvBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(objectTexCoords[i]), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(uvAttributeLocation[i]);
    gl.vertexAttribPointer(uvAttributeLocation[i], 2, gl.FLOAT, false, 0, 0);

    var indexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(objectIndices[i]), gl.STATIC_DRAW);









    var texture = gl.createTexture();

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);

    image = new Image();
    image.crossOrigin = "anonymous";
    image.src = baseDir + modelTexture[i];

    image.onload = function () {

      gl.activeTexture(gl.TEXTURE0)
      gl.bindTexture(gl.TEXTURE_2D, texture);
      gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      gl.generateMipmap(gl.TEXTURE_2D);
    };
  }



  /* --------------------------------------DRAW SCENE-----------------------------------*/
  drawScene();

  function animate() {
    var currentTime = (new Date).getTime();
    if (lastUpdateTime != null) {
      console.log(currentTime - lastUpdateTime);
      var deltaC = (30 * (currentTime - lastUpdateTime)) / 1000.0;
      Ry_boat += deltaC;
      Ry_boat -= deltaC;
      Rz_boat += deltaC;
    }

    y_boat = y_boat + 0.01;
    z_boat = z_boat - 0.01;

    objectWorldMatrix[0] = utils.MakeWorld(0.0, y_boat, z_boat, Rx_boat, Ry_boat, Rz_boat, S_boat);


    lastUpdateTime = currentTime;
  }

  function drawScene() {
    // animate();

    utils.resizeCanvasToDisplaySize(gl.canvas);
    gl.clearColor(0.85, 0.85, 0.85, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);



    for (i = 0; i < 2; i++) {
      gl.useProgram(programs[i]);
      var viewWorldMatrix = utils.multiplyMatrices(viewMatrix, objectWorldMatrix[i]);
      var projectionMatrix = utils.multiplyMatrices(perspectiveMatrix, viewWorldMatrix);
      gl.uniformMatrix4fv(matrixLocation[i], gl.FALSE, utils.transposeMatrix(projectionMatrix));


      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, texture);
      gl.uniform1i(textLocation[i], texture);



      gl.bindVertexArray(vaos[i]);
      gl.drawElements(gl.TRIANGLES, objectIndices[i].length, gl.UNSIGNED_SHORT, 0);

    }


    window.requestAnimationFrame(drawScene);
  }


}

async function init() {

  var path = window.location.pathname;
  var page = path.split("/").pop();
  baseDir = window.location.href.replace(page, '');
  shaderDir = baseDir + "shaders/";

  var canvas = document.getElementById("c");
  gl = canvas.getContext("webgl2");
  if (!gl) {
    document.write("GL context not opened");
    return;
  }

  await utils.loadFiles([shaderDir + 'vs.glsl', shaderDir + 'fs.glsl'], function (shaderText) {
    var vertexShader = utils.createShader(gl, gl.VERTEX_SHADER, shaderText[0]);
    var fragmentShader = utils.createShader(gl, gl.FRAGMENT_SHADER, shaderText[1]);
    programs[0] = utils.createProgram(gl, vertexShader, fragmentShader);

  });

  await utils.loadFiles([shaderDir + 'vs.glsl', shaderDir + 'fs.glsl'], function (shaderText) {
    var vertexShader = utils.createShader(gl, gl.VERTEX_SHADER, shaderText[0]);
    var fragmentShader = utils.createShader(gl, gl.FRAGMENT_SHADER, shaderText[1]);
    programs[1] = utils.createProgram(gl, vertexShader, fragmentShader);

  });


  //###################################################################################
  //This loads the obj model in the boatModel variable
  var boatObjStr = await utils.get_objstr(baseDir + modelStr[0]);
  boatModel = new OBJ.Mesh(boatObjStr);
  //###################################################################################

  //###################################################################################
  //This loads the obj model in the boatModel variable
  var rockObjStr = await utils.get_objstr(baseDir + modelStr[1]);
  rockModel = new OBJ.Mesh(rockObjStr);
  //###################################################################################

  main();
}

window.onload = init;

1 个答案:

答案 0 :(得分:0)

我看到了这段代码

var texture = gl.createTexture();

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);

image = new Image();
image.crossOrigin = "anonymous";
image.src = baseDir + modelTexture[i];

image.onload = function () {

  gl.activeTexture(gl.TEXTURE0)
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.generateMipmap(gl.TEXTURE_2D);
};    

被调用了两次,但是只有1个变量texture。也许您打算制作textures = []并将其更改为

texture[i] = gl.createTexture();

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture[i]);

image = new Image();
image.crossOrigin = "anonymous";
image.src = baseDir + modelTexture[i];

image.onload = function (texture, image) {
  return function() {
    gl.activeTexture(gl.TEXTURE0)
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.generateMipmap(gl.TEXTURE_2D);
  };
}(texture[i], image);

请注意对回调的更改,因为我们需要在textureimage上“关闭”,以便它们在回调中可用。

并将渲染代码更改为

  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, texture[i]);
  gl.uniform1i(textLocation[i], texture[i]);