使用 texture() 时 Opengl 错误 1282(无效操作)
Opengl error 1282 (invalid operation) when using texture()
我有以下片段着色器:
#version 330 core
layout (location = 0) out vec4 color;
uniform vec4 colour;
uniform vec2 light_pos;
in DATA
{
vec4 position;
vec2 texCoord;
float tid;
vec4 color;
} fs_in;
uniform sampler2D textures[32];
void main()
{
float intensity = 1.0 / length(fs_in.position.xy - light_pos);
vec4 texColor = fs_in.color;
if (fs_in.tid > 0.0)
{
int tid = int(fs_in.tid + 0.5);
texColor = texture(textures[tid], fs_in.texCoord);
}
color = texColor * intensity;
}
如果我 运行 我的程序,我得到 opengl 错误 1282,这是无效操作。如果我不使用 texture(),那么我写 texCoord = vec4(...) 它会完美地工作。我总是将 tid(纹理 ID)作为 0(无纹理)传递,因此该部分甚至不应该 运行。我已经将纹理统一设置为某个占位符,但据我所知这根本不重要。那么什么会导致无效操作呢?
您的着色器编译很可能失败了。确保在尝试编译着色器后始终检查编译状态,使用:
GLint val = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &val);
if (val != GL_TRUE)
{
// compilation failed
}
在您的情况下,着色器是非法的,因为您正试图访问具有可变索引的采样器数组:
texColor = texture(textures[tid], fs_in.texCoord);
GLSL 3.30 不支持此功能。来自规范(添加了重点):
Samplers aggregated into arrays within a shader (using square brackets [ ]) can only be indexed with integral constant expressions (see section 4.3.3 “Constant Expressions”).
此限制在以后的 OpenGL 版本中有所放宽。例如,来自 GLSL 4.50 规范:
When aggregated into arrays within a shader, samplers can only be indexed with a dynamically uniform integral expression, otherwise results are undefined.
此更改是在 GLSL 4.00 中引入的。但这对你的情况来说仍然不够,因为你试图使用一个 in
变量作为索引,它不是动态统一的。
如果您的纹理大小都相同,您可能需要考虑改用数组纹理。这将允许您根据动态计算的索引对数组纹理中的一层进行采样。
我知道这个解决方案来晚了,但如果它对任何人有帮助..
根据 Cherno 的视频,这应该有效。然而,他使用属性 'fs_in.tid' 作为纹理索引 gl_VertexAttribPointer 中的 'GL_BYTE',出于某种原因,关于铸造 1.0f 总是被转换为 0.0f,因此不起作用。
将 GL_BYTE 更改为 GL_FLOAT 为我解决了这个问题。
关于 'opengl error 1282',这是我遇到的一个非常常见的错误。我曾经忘记在设置任何制服之前调用 glUseProgram(ShaderID)。因此,制服即使当时不是 used/set 也会导致错误,即“1282”。这可能是解决方案之一,这为我解决了。
我有以下片段着色器:
#version 330 core
layout (location = 0) out vec4 color;
uniform vec4 colour;
uniform vec2 light_pos;
in DATA
{
vec4 position;
vec2 texCoord;
float tid;
vec4 color;
} fs_in;
uniform sampler2D textures[32];
void main()
{
float intensity = 1.0 / length(fs_in.position.xy - light_pos);
vec4 texColor = fs_in.color;
if (fs_in.tid > 0.0)
{
int tid = int(fs_in.tid + 0.5);
texColor = texture(textures[tid], fs_in.texCoord);
}
color = texColor * intensity;
}
如果我 运行 我的程序,我得到 opengl 错误 1282,这是无效操作。如果我不使用 texture(),那么我写 texCoord = vec4(...) 它会完美地工作。我总是将 tid(纹理 ID)作为 0(无纹理)传递,因此该部分甚至不应该 运行。我已经将纹理统一设置为某个占位符,但据我所知这根本不重要。那么什么会导致无效操作呢?
您的着色器编译很可能失败了。确保在尝试编译着色器后始终检查编译状态,使用:
GLint val = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &val);
if (val != GL_TRUE)
{
// compilation failed
}
在您的情况下,着色器是非法的,因为您正试图访问具有可变索引的采样器数组:
texColor = texture(textures[tid], fs_in.texCoord);
GLSL 3.30 不支持此功能。来自规范(添加了重点):
Samplers aggregated into arrays within a shader (using square brackets [ ]) can only be indexed with integral constant expressions (see section 4.3.3 “Constant Expressions”).
此限制在以后的 OpenGL 版本中有所放宽。例如,来自 GLSL 4.50 规范:
When aggregated into arrays within a shader, samplers can only be indexed with a dynamically uniform integral expression, otherwise results are undefined.
此更改是在 GLSL 4.00 中引入的。但这对你的情况来说仍然不够,因为你试图使用一个 in
变量作为索引,它不是动态统一的。
如果您的纹理大小都相同,您可能需要考虑改用数组纹理。这将允许您根据动态计算的索引对数组纹理中的一层进行采样。
我知道这个解决方案来晚了,但如果它对任何人有帮助..
根据 Cherno 的视频,这应该有效。然而,他使用属性 'fs_in.tid' 作为纹理索引 gl_VertexAttribPointer 中的 'GL_BYTE',出于某种原因,关于铸造 1.0f 总是被转换为 0.0f,因此不起作用。 将 GL_BYTE 更改为 GL_FLOAT 为我解决了这个问题。
关于 'opengl error 1282',这是我遇到的一个非常常见的错误。我曾经忘记在设置任何制服之前调用 glUseProgram(ShaderID)。因此,制服即使当时不是 used/set 也会导致错误,即“1282”。这可能是解决方案之一,这为我解决了。