我正在尝试编写一个简单的测试程序来演示 GLSL 4.2 的ImageLoad
功能。到目前为止,我有:
- 一个简单的着色器,它从 an 加载左下角的纹素
image2D
并显示它。 - 一些简单的顶点代码来绘制全屏小队
- 其他用于创建上下文、编译着色器等的脚手架代码。
这是我的片段代码(顶点是一个简单的直通着色器):
#version 420
#include <gtest/SmallImage.h> //NOTE: I have a preprocessor that takes care of includes
layout(binding = SMALL_IMAGE_ONE_BINDING, rgba8) uniform image2D image_one;
smooth in vec2 texture_coords;
out vec4 out_color;
void main(void)
{
vec4 loaded = imageLoad(image_one, ivec2(0,0));
vec4;
out_color = vec4(loaded.r,
loaded.g,
gl_FragCoord.y/1200.0,
1);
}
很简单,没有阅读空间。与像素坐标成比例的蓝色通道让我知道即使imageLoad
调用失败,四边形也被正确渲染。
这是我用来渲染到屏幕的 C++ 循环。它绑定一个纹理,写入一个黄色纹素,然后渲染一个全屏四边形。有两种变体:当MAKE_ONCE
定义时,纹理在循环之前生成一次。如果未定义,则循环的每次迭代都会生成一个新纹理:
MyTestFun(void)
{
glm::vec4 yellow = glm::vec4(1.0, 1.0, 0.0, 1.0);
#ifdef MAKE_ONCE
renderer->InitFrame(); //sets current OpenGL context
GLuint name = 0;
glGenTextures(1, &name);
renderer->EndFrame();
#endif
while(1)
{
renderer->InitFrame();
#ifndef MAKE_ONCE
GLuint name =0;
glGenTextures(1, &name);
#endif
glBindTexture(GL_TEXTURE_2D, name);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_FLOAT,
glm::value_ptr(yellow));
glBindTexture(GL_TEXTURE_2D, 0);
glBindImageTexture(SMALL_IMAGE_ONE_UNIT, name, 0, false, 0, GL_READ_ONLY,
GL_RGBA8);
renderer->FullscreenQuad(); //shades using the frag shader shown above
//bind the default texture to the image unit, hopefully freeing ours for editing
glBindImageTexture(SMALL_IMAGE_ONE_UNIT, 0, 0, false, 0, GL_READ_WRITE,
GL_RGBA8);
renderer->EndFrame();
}
}
定义时MAKE_ONCE
,第一帧显示从白色到黄色的垂直渐变,但随后的帧显示从蓝色到黑色的垂直渐变,表示IMAGE_LOAD
调用返回 0.0。
当MAKE_ONCE
未定义时,例如在每一帧上重新制作纹理,程序将按预期运行,在每一帧上显示相同的白色<->黄色渐变。
什么可能导致这种行为?OpenGL 4.2 规范说,imageLoad
如果图像处于无效状态 (p255-266),则调用将返回黑色(全零),但此处似乎没有任何有效条件。