понедельник, 29 июля 2013 г.

WebGL. Загрузка текстур. Особенность Chrome

    Чтобы использовать текстуры в WebGL, их нужно для начала создать, а затем инициализировать. Делается это примерно так:

gl - объект типа WebGL Context

// Инициализация текстуры
function initTex(texture)
{
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,texture.image);
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.LINEAR);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D, null);
}

// Создание текстуры
// Возвращает объект типа текстура
function createTex(image_name)
{
var image = new Image();
var texture = gl.createTexture();
image.src = image_name;
texture.image = image;
image.onload = function()
{
initTex(texture);
}
return texture;
}

// И собственно, как это потом выглядит в коде
texture[0] = createTex("pic/back_01.jpg");

Замечание!!!!
Вызов метода gl.createTexture(); обязательно должен производиться вне тела функции initTex();. Из-за такого в буферах начинали путаться текстуры, и общая картина смотрелась довольно забавно. Но одно дело забавно, а другое дело, что текстуры не на своих местах.

Google Chrome


С ним было много заморочек. Например:

При стандартных настройках безопасности у хрома нет возможности загрузки некоторых локальных ресурсов. По-этому, чтобы проверить работоспособность вашей программы на Хроме, разрабатывайте ее на сервере. В серьезных проектах это естественно будет так. Но вдруг вы просто решили потестить маленький примерчик, создали локальный html файл, и вдруг видите черный квадрат вместо текстуры. Это именно оно и есть.

Надеюсь, это кому-нибудь пригодится)))

4 комментария:

  1. Этот комментарий был удален автором.

    ОтветитьУдалить
    Ответы
    1. то есть всё же не удалось решить проблему без использования сервера ? у меня возникла проблема с Chrome и не знаю как её решить без установки всяких серверов, чтобы поюзать самый примитивный скрипт
      obj.initCanvas("example");
      obj.initGl();
      obj.initShaders("shader-fs","shader-vs");
      //alert("1");
      var a_TexCoord =obj.gl.getAttribLocation(obj.shaderProgram, 'a_TexCoord');
      var a_Position=obj.gl.getAttribLocation(obj.shaderProgram,'a_Position');
      var u_Sampler = obj.gl.getUniformLocation(obj.shaderProgram, 'u_Sampler');

      obj.gl.clearColor(0.0,0.0,0.0,1.0);
      obj.gl.clear(obj.gl.COLOR_BUFFER_BIT);

      var n = initVertexBuffers(obj.gl);
      if (n < 0) {
      console.log('Failed to set the positions of the vertices');
      }
      //alert(initTextures(obj.gl, n));
      if (!initTextures(obj.gl, n)) {
      }

      Удалить
    2. function initVertexBuffers(gl) {
      var vertices = new Float32Array([
      -0.5, 0.5, 0.0, 1.0,
      -0.5, -0.5, 0.0, 0.0,
      0.5, 0.5, 1.0, 1.0,
      0.5, -0.5, 1.0, 0.0,
      ]);

      var n = 4; // Число вершин
      // Создать буферный объект
      var vertexTexCoordBuffer = gl.createBuffer();

      if (!vertexTexCoordBuffer) {
      console.log('Failed to create the buffer object ');
      return -1;
      }

      gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
      var FSIZE=vertices.BYTES_PER_ELEMENT;
      gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE*4, 0);
      gl.enableVertexAttribArray(a_Position);

      gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE*4, FSIZE*2);
      gl.enableVertexAttribArray(a_TexCoord);

      return n;
      }
      function initTextures(gl, n){
      var texture = gl.createTexture(); // Создать объект текстуры

      // Получить ссылку на u_Sampler
      var image = new Image(); // Создать объект изображения

      // Зарегистрировать обработчик, вызываемый послезагрузки изображения
      image.onload = function(){
      loadTexture(gl,n,texture,u_Sampler,image);
      };
      // Заставить браузер загрузить изображение
      //image.crossOrigin = '*';
      //image.crossOrigin = 'Anonymous';
      image.src = 'C:/jo/sky.jpg';

      return true;
      }
      function loadTexture(gl, n, texture, u_Sampler, image){
      //alert(image);
      gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // Повернуть ось Y изображения
      // Выбрать текстурный слот 0
      gl.activeTexture(gl.TEXTURE0);
      // Указать тип объекта текстуры
      gl.bindTexture(gl.TEXTURE_2D, texture);

      // Определить параметры текстуры
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      // Определить изображение текстуры
      //alert(image);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,image);

      // Определить указатель на текстурный слот 0
      gl.uniform1i(u_Sampler, 0);

      gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Нарисовать прямоугольник
      }

      Удалить
    3. собственно проблема возникает только вот здесь:
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,image);
      ----
      Image from origin 'file://' has been blocked from loading by Cross-Origin Resource Sharing policy: Invalid response. Origin 'null' is therefore not allowed access.
      ---
      или ещё такая ошибка:
      e11.html:125 Uncaught SecurityError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at file:///C:/jo/sky.jpg may not be loaded.

      Удалить