GLSL:内存耗尽
GLSL: memory exhausted
我正在处理具有约 100 种不同的 2048 x 2048 像素纹理的 WebGL 场景。我正在渲染点基元,每个点都有一个纹理索引和纹理 uv 偏移量,指示应该在该点上使用的给定纹理区域。
最初,我尝试将每个点的纹理索引作为 varying
值传递,然后我尝试使用该索引位置从 sampler2D
数组中提取给定纹理。但是,这会产生一个错误,即只能使用 "constant integer expression" 获取 sampler2D
数组值,所以现在我使用一个粗糙的 if 条件来分配每个点的纹理索引:
/**
* 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),这种方法会抛出:
ERROR: 0:58: '[' : memory exhausted
我已尝试阅读有关此错误的信息,但仍不确定其含义。我是否超过了 GPU 中的最大 RAM?如果有人知道这个错误是什么意思,and/or我可以做些什么来解决这个问题,如果你能提供任何提示,我将不胜感激。
更多详情:
要加载的所有纹理的总大小:58MB
浏览器:最近 Chrome
显卡:AMD Radeon R9 M370X 2048 MB 显卡(库存 2015 OSX 卡)
片段着色器可以访问的采样器数量是有限制的。可以通过gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)
获得。保证至少为 8,通常为 16 或 32。
为了规避限制,纹理数组在 WebGL2 中可用,它还允许使用任何变量索引图层。在 WebGL1 中,你唯一的选择是地图集,但由于你的纹理已经是 2048 x 2048,你不能让 ghem 更大。
如果您不想将自己局限于 WebGL2,则必须将渲染拆分为多个具有不同纹理集的绘制调用。
还要考虑到拥有 100 个 8 位 RGBA 2048x2048 纹理会占用 1.6 GB 的 VRAM。通过 WEBGL_compressed_texture_s3tc
进行纹理压缩可以将其降低 8 倍或 4 倍,具体取决于您需要多少 alpha 精度。
我正在处理具有约 100 种不同的 2048 x 2048 像素纹理的 WebGL 场景。我正在渲染点基元,每个点都有一个纹理索引和纹理 uv 偏移量,指示应该在该点上使用的给定纹理区域。
最初,我尝试将每个点的纹理索引作为 varying
值传递,然后我尝试使用该索引位置从 sampler2D
数组中提取给定纹理。但是,这会产生一个错误,即只能使用 "constant integer expression" 获取 sampler2D
数组值,所以现在我使用一个粗糙的 if 条件来分配每个点的纹理索引:
/**
* 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),这种方法会抛出:
ERROR: 0:58: '[' : memory exhausted
我已尝试阅读有关此错误的信息,但仍不确定其含义。我是否超过了 GPU 中的最大 RAM?如果有人知道这个错误是什么意思,and/or我可以做些什么来解决这个问题,如果你能提供任何提示,我将不胜感激。
更多详情:
要加载的所有纹理的总大小:58MB
浏览器:最近 Chrome
显卡:AMD Radeon R9 M370X 2048 MB 显卡(库存 2015 OSX 卡)
片段着色器可以访问的采样器数量是有限制的。可以通过gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)
获得。保证至少为 8,通常为 16 或 32。
为了规避限制,纹理数组在 WebGL2 中可用,它还允许使用任何变量索引图层。在 WebGL1 中,你唯一的选择是地图集,但由于你的纹理已经是 2048 x 2048,你不能让 ghem 更大。
如果您不想将自己局限于 WebGL2,则必须将渲染拆分为多个具有不同纹理集的绘制调用。
还要考虑到拥有 100 个 8 位 RGBA 2048x2048 纹理会占用 1.6 GB 的 VRAM。通过 WEBGL_compressed_texture_s3tc
进行纹理压缩可以将其降低 8 倍或 4 倍,具体取决于您需要多少 alpha 精度。