glsl - 在 Three.js 中指定 WebGL2 上下文后,无法遍历 sampler2D 数组
问题描述
我一直sampler2D
在我的片段着色器中使用一个数组(这些是阴影贴图,最多可以有 16 个,所以当然,一个数组比使用 16 个单独的变量更可取)。然后我const context = canvas.getContext('webgl2');
将WebGL2 上下文(THREE.WebGLRenderer
array index for samplers must be constant integral expressions
uniform sampler2D samplers[MAX_SPLITS];
for (int i = 0; i < MAX_SPLITS; ++i) {
if (i >= splitCount) {
break;
}
if (func(samplers[i])) { // that's where the error happens
...
}
}
真的没有办法解决这个问题吗?我必须使用十六个单独的变量吗?
(着色器中没有直接#version
指令,但 THREE.js 似乎#version 300 es
默认添加了一个)
解决方案
您不能在 GLSL ES 3.0 中对采样器使用动态索引。从规格
12.29 采样器
应该允许采样器作为 l 值吗?该规范已经允许等效行为:
当前规格:
uniform sampler2D sampler[8]; int index = f(...); vec4 tex = texture(sampler[index], xy); // allowed
使用采样器类型的分配:
uniform sampler2D s; s = g(...); vec4 tex = texture(s, xy); // not allowed
解决方案:规范现在禁止对采样器数组进行动态索引。将采样器数组的索引限制为常量整数表达式。
和
12.30 动态索引
对于 GLSL ES 1.00,不强制支持数组、向量和矩阵的动态索引,因为某些实现不直接支持它。软件解决方案(通过程序转换)适用于部分案例,但会导致性能不佳。GLSL ES 3.00 是否应该强制支持动态索引?
解决方案:强制支持数组的动态索引,但采样器数组、片段输出数组和统一块数组除外。
GLSL ES 3.00 是否应该强制支持向量和矩阵的动态索引?
解决方案:是的。
GLSL ES 1.00 支持通过常量索引表达式对采样器数组进行索引。常量索引表达式是由常量表达式和某些循环索引形成的表达式,为循环构造的子集定义。这个功能应该包含在 GLSL ES 3.00 中吗?
解决方案:不可以。采样器数组只能由常量积分表达式索引。
您可以使用 2D_ARRAY 纹理来解决您的问题吗?将您当前的每个 2D 纹理放入 2D_ARRAY 纹理的层中,然后 z 坐标只是一个整数层索引。优点是,您可以使用更多带有 2D_ARRAY 的图层,然后获得采样器。WebGL2 实现通常只有 32 个采样器,但在 2D_ARRAY 纹理中允许数百或数千层。
或使用 GLSL 1.0
const vs1 = `
void main() { gl_Position = vec4(0); }
`;
const vs3 = `#version 300 es
void main() { gl_Position = vec4(0); }
`;
const fs1 = `
precision highp float;
#define MAX_SPLITS 4
uniform sampler2D samplers[MAX_SPLITS];
uniform int splitCount;
bool func(sampler2D s) {
return texture2D(s, vec2(0)).r > 0.5;
}
void main() {
float v = 0.0;
for (int i = 0; i < MAX_SPLITS; ++i) {
if (i >= splitCount) {
break;
}
if (func(samplers[i])) { // that's where the error happens
v += 1.0;
}
}
gl_FragColor = vec4(v);
}
`;
const fs3 = `#version 300 es
precision highp float;
#define MAX_SPLITS 4
uniform sampler2D samplers[MAX_SPLITS];
uniform int splitCount;
bool func(sampler2D s) {
return texture(s, vec2(0)).r > 0.5;
}
out vec4 color;
void main() {
float v = 0.0;
for (int i = 0; i < MAX_SPLITS; ++i) {
if (i >= splitCount) {
break;
}
if (func(samplers[i])) { // that's where the error happens
v += 1.0;
}
}
color = vec4(v);
}
`;
function main() {
const gl = document.createElement('canvas').getContext('webgl2');
if (!gl) {
return alert('need WebGL2');
}
test('glsl 1.0', vs1, fs1);
test('glsl 3.0', vs3, fs3);
function test(msg, vs, fs) {
const p = twgl.createProgram(gl, [vs, fs]);
log(msg, ':', p ? 'success' : 'fail');
}
}
main();
function log(...args) {
const elem = document.createElement('pre');
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
推荐阅读
- postgresql - 我想用 postgresql 开发一个 adf fusion web 应用程序项目
- c - 我在接收 C 中的按键时遇到问题
- mysql - docker内部的django-mysql连接错误
- sql-server - Power BI 查询错误:Microsoft SQL:';' 附近的语法不正确。')' 附近的语法不正确
- javascript - 从javascript对象literel返回值
- postgresql - psql 身份验证失败并显示 --host=localhost
- javascript - 未捕获的类型错误:无法读取未定义的属性“1”(即使已定义)
- android - Android gradle 同步:无法获取资源 firebase-measurement-connector-impl-17.0.4-javadoc.jar
- javascript - useReducer/useState 更新太慢
- python - 为什么我们在运行 subprocess.check_output(xyz, shell=True) 后会从终端丢失标准输出?