GLSL: память исчерпана - PullRequest
       32

GLSL: память исчерпана

0 голосов
/ 02 июля 2018

Я работаю над сценой WebGL с ~ 100 различными текстурами 2048 x 2048 px. Я рендеринг точек примитивов, и каждая точка имеет индекс текстуры и смещения текстуры, которые указывают область данной текстуры, которая должна использоваться в точке.

Сначала я пытался передать индекс текстуры каждой точки как значение varying, затем я попытался извлечь заданную текстуру из массива sampler2D, используя эту позицию индекса. Однако это привело к ошибке, что можно получить только значения массива sampler2D с «постоянным целочисленным выражением», так что теперь я использую грубое условное выражение для назначения индекса текстуры каждой точки:

/**
* The fragment shader's main() function must define `gl_FragColor`,
* which describes the pixel color of each pixel on the screen.
*
* To do so, we can use uniforms passed into the shader and varyings
* passed from the vertex shader.
*
* Attempting to read a varying not generated by the vertex shader will
* throw a warning but won't prevent shader compiling.
**/

// set float precision
precision highp float;

// repeat identifies the size of each image in an atlas
uniform vec2 repeat;

// textures contains an array of textures with length n textures
uniform sampler2D textures[42];

// identify the uv values as a varying attribute
varying vec2 vUv; // blueprint uv coords
varying vec2 vTexOffset; // instance uv offsets
varying float vTexture; // set index of each object's vertex

void main() {
  int textureIndex = int(floor(vTexture));

  vec2 uv = vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y );

  // The block below is automatically generated
  if (textureIndex == 0) {vec4 color = texture2D(textures[0], uv * repeat + vTexOffset ); }
  else if (textureIndex == 1) { vec4 color = texture2D(textures[1], uv * repeat + vTexOffset );  } 
  else if (textureIndex == 2) { vec4 color = texture2D(textures[2], uv * repeat + vTexOffset );  } 
  else if (textureIndex == 3) { vec4 color = texture2D(textures[3], uv * repeat + vTexOffset );  } 
  [ more lines of the same ... ]
  gl_FragColor = color;

}

Если количество текстур невелико, это нормально работает. Но если количество текстур велико (например, 40), такой подход выдает:

ОШИБКА: 0:58: '[': память исчерпана

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

Подробнее:
Общий размер всех текстур для загрузки: 58 ​​МБ
Браузер: недавний Chrome
Видеокарта: AMD Radeon R9 M370X, графическая карта 2048 МБ (карта OSX 2015 года выпуска)

1 Ответ

0 голосов
/ 03 июля 2018

Существует ограничение на количество сэмплеров, к которым может получить доступ фрагментный шейдер. Его можно получить через gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS). Гарантируется, что оно будет не менее 8, а обычно 16 или 32.

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

Если вы не хотите ограничивать себя WebGL2, вам придется разделить ваш рендеринг на несколько вызовов отрисовки с различными текстурами.

Также учтите, что при наличии 100 8-битных текстур RGBA 2048x2048 используется 1,6 ГБ видеопамяти. Сжатие текстур с помощью WEBGL_compressed_texture_s3tc может уменьшить его в 8 или 4 раза, в зависимости от того, насколько вам нужна альфа-точность.

...