Заменить цвет текстурой в WebGL - PullRequest
5 голосов
/ 11 ноября 2011

В видеоиграх применяется только цвет, чтобы ускорить процесс загрузки. После того, как текстуры готовы, они заменяют текущие цвета. Есть ли способ сделать это в WebGL? Все уроки, которые я видел до сих пор, показывают только, как загружать цвета или текстуры (не один за другим).

Я предполагаю, что буфер для каждой фигуры должен быть изменен после полной загрузки текстуры. Я бы предположил, что это вводится с помощью вызова AJAX, что текстура доступна, а затем применяется с помощью некоторой функции JavaScript. Есть ли у WebGL встроенный способ сделать это без сложного процесса загрузки изображения?

Ответы [ 3 ]

5 голосов
/ 11 ноября 2011

В большинстве игр, которые я видел с описанным вами поведением, они обычно начинаются либо с раскраски на каждую вершину, либо с ОЧЕНЬ текстурой с низким разрешением и «смешиваются» с полной текстурой, когда она становится доступной. Такой плавный переход довольно сложен, но если все, что вам нужно, это быстрое «всплытие» от одного к другому, это не должно вызвать особых проблем.

Основной маршрут, который я выбрал бы, - это создание буфера вершин, который бы имел как текстурную координату, так и информацию о цвете, а также два разных шейдера. Один шейдер будет использовать информацию о цвете, другой проигнорирует ее и вместо этого будет использовать текстуру. Вы дадите сигнал мешу, чтобы начать использовать текстурный, как только текстура будет готова.

Что касается определения загрузки изображения, это совсем не сложно, и вам даже не нужен AJAX для этого:

var image = new Image();
image.addEventListener("load", function() {
    // Image is done loading, push to texture
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    // Set up any other state needed, such as switching the shader for the mesh
}, true);
image.src = src;

Я не уверен, насколько большую помощь я могу оказать по этому вопросу, не публикуя действительно большие блоки кода, но если вы все еще испытываете затруднения, я могу подробно рассказать о некоторых других частях.

1 голос
/ 26 ноября 2011

Подход, который я выбрал бы, следующий:

loadTexture(url, initialColor) {

  var tex = gl.createTexture();

  // start with a single color.
  gl.bindTexture(gl.TEXTURE_2D, tex);
  var pixel = new Uint8Array(initialColor);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, pixel);

  // start loading the image
  var img = new Image();
  img.src = url;
  img.onLoad = function() {

    // when the image has loaded update the texture.          
    gl.bindTexture(gl.TEXTURE_2D, tex);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
    gl.generateMipmap(gl.TEXTURE_2D);
  }
  return tex;
}

// Load a tree texture, use brown until the texture loads.
var treeTexture = loadTexture("tree.png", [255, 200, 0, 255]);
// Load a water texture, use blue until it loads.  
var waterTexture = loadTexture("water.jpg", [0, 0, 255, 255]);

Так работает большинство сэмплов на http://webglsamples.googlecode.com, хотя все они по умолчанию имеют синие текстуры.

Вы можете легко расширить эту идею, чтобы использовать сплошной цвет, загрузить текстуру с низким разрешением, а затем, когда это закончится, загрузить текстуру с высоким разрешением.

Примечание. Приведенный выше код предполагает, что вы загружаете текстуры степени 2. Если нет, вам нужно правильно настроить параметры текстуры.

0 голосов
/ 11 ноября 2011

Это на самом деле очень просто, без WebGL, у которого есть какие-то функции специально для этого, это то, что вы получаете бесплатно только благодаря API DOM.Когда вы загружаете изображения, в любом случае вы должны реализовать их обратный вызов «onload», так как загрузка изображений асинхронна.Так что просто вставьте в этот обратный вызов onload любой код, который нужно запустить, чтобы переключиться со сплошного цвета на текстуру.

...