首页 > 解决方案 > Threejs数组索引错误:索引表达式必须是常量

问题描述

当我尝试使用具有非恒定索引的数组时, Three.js出现以下错误:

'[]' : 索引表达式必须是常量

使用以下片段着色器:

precision mediump float;

varying vec2 vUV;

uniform vec2 screenResolution;

vec4 colors[2];

void main(void) {

    vec2 uv = gl_FragCoord.xy / screenResolution.xy;

    colors[0] = vec4(0.0);
    colors[1] = vec4(1.0);

    int index = int(floor(uv.y * 1.9));

    gl_FragColor = colors[index];
}

Babylon.js不会发生此错误。

我知道在早期版本中不可能对数组使用非常量索引,GLSL ES但现在应该可以了,对吧?

如何知道 Three.js 和 Babylon.js 使用的 GLSL 版本?

标签: three.jsglslwebglshader

解决方案


简短的回答

要在Three.js中使用 GLSL ES 3.0,您必须创建一个 WebGL 2.0 上下文。

检查设备是否支持 WebGL 2 后,WebGLRenderer使用给定的webgl2上下文创建一个:

var canvas = document.createElement( 'canvas' );
var context = canvas.getContext( 'webgl2' );
var renderer = new THREE.WebGLRenderer( { canvas: canvas, context: context } );

请参阅 Three.js 文档:如何使用 WebGL2

长答案

问题的着色器版本是 GLSL ES 1.0。数组的索引必须是常量表达式。

请参阅OpenGL ES 着色语言 1.00 规范 - 13 致谢;第 109 页:

5 数组、向量和矩阵的索引

定义:常量索引表达式是常量表达式的超集。常量索引表达式可以包括附录 A 第 4 节中定义的循环索引
。以下是常量索引表达式:

  • 常量表达式
  • 第 4 节中定义的循环索引
  • 由以上两个组成的表达式

当用作索引时,常量索引表达式必须具有整数类型。

制服(不包括采样器)

在顶点着色器中,要求支持所有形式的数组索引。在片段着色器中,仅对常量索引表达式要求支持索引。#

这意味着片段着色器中数组的索引在任何情况下都必须是常量或循环索引。


这在 GLSL ES 3.0 中发生了变化。请参阅OpenGL ES 着色语言 3.00 - 12.30 动态索引;第 142 页:

对于 GLSL ES 1.00,不强制支持数组、向量和矩阵的动态索引,因为某些实现不直接支持它。软件解决方案(通过程序转换)适用于部分案例,但会导致性能不佳。GLSL ES 3.00 是否应该强制支持动态索引?

解决方案:强制支持数组的动态索引,但采样器数组、片段输出数组和统一块数组除外。


GLSL ES 3.0 着色器必须由着色代码第一行中的版本限定符限定:

#version 300 es

此外,还有一些语法差异,例如着色器输入和输出的限定符,它们in分别out代替attributeor varying

要使用 GLSL ES 3.0,您必须创建一个 WebGL 2.0 上下文。
请参阅 Three.js 文档:如何使用 WebGL2


推荐阅读