c++ - 带有片段着色器的多个纹理单元不起作用

标签 c++ opengl glsl

我需要显示一些索引图形文件,该文件还具有每像素 alpha channel 。此外,我需要确保我可以随时更改调色板,并且生成的图像也会更改。为此,我首先使用软件像素预计算,但这对于实时渲染来说太慢了,所以我决定编写一个着色器来处理 GPU 端的索引纹理。问题是第二个纹理 (rec_colors) 没有加载(至少看起来是这样——从该采样器读取的每个纹素看起来都是空的)。

来自零纹理的数据读取正确,导致黑色图像具有正确的 alpha :)

着色器初始化相关代码:

Application::Display->GetRC();
glewInit();
if(!GLEW_VERSION_2_0) return false;

char* code_frag = loadCode("shader.frag");
char* code_verx = loadCode("shader.verx");

aShader_palette = glCreateShader(GL_FRAGMENT_SHADER);
//glShaderSource(aShader_palette, 1, &aShaderProgram_palette, NULL);
glShaderSource(aShader_palette, 1, (const GLchar**)&code_frag, NULL);
glCompileShader(aShader_palette);

GLint compiled = 0;
glGetShaderiv(aShader_palette, GL_COMPILE_STATUS, &compiled);

if(!compiled)
{
    /* error-handling */
}

GLuint texloc = glGetUniformLocation(aShader_palette, "rec");
glUniform1i(texloc, 0);
texloc = glGetUniformLocation(aShader_palette, "rec_colors");
glUniform1i(texloc, 1);

glsl_palette_Program = glCreateProgram();
glAttachShader(glsl_palette_Program, aShader_palette);
glLinkProgram(glsl_palette_Program);

和渲染相关的:

glPushAttrib(GL_CURRENT_BIT);
glColor4ub(255, 255, 255, t_a); // t_a is overall alpha of sprite displayed
glUseProgram(glsl_palette_Program); // this one is a compiled/linked shader declared above
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->m_SpriteData[idx].texture);
glActiveTexture(GL_TEXTURE1); // at this point, it looks like texture unit is actually changed (I checked that via glGetIntegerv)
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->m_PaletteTex);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, 256, 1, GL_RGBA, GL_UNSIGNED_BYTE, palette); // update possibly changed palette on each render
glActiveTexture(GL_TEXTURE0);
glBegin(GL_QUADS);
    glTexCoord2i(0, 0);
    glVertex2i(x, y);
    glTexCoord2i(0, this->GetHeight(idx));
    glVertex2i(x, y+this->GetHeight(idx));
    glTexCoord2i(this->GetWidth(idx), this->GetHeight(idx));
    glVertex2i(x+this->GetWidth(idx), y+this->GetHeight(idx));
    glTexCoord2i(this->GetWidth(idx), 0);
    glVertex2i(x+this->GetWidth(idx), y);
glEnd();
glActiveTexture(GL_TEXTURE1);
glUnbindTexture(GL_TEXTURE_RECTANGLE_ARB); // custom macro
glActiveTexture(GL_TEXTURE0);
glUnbindTexture(GL_TEXTURE_RECTANGLE_ARB);
glUseProgram(0);
glPopAttrib();

着色器代码:

#extension GL_ARB_texture_rectangle : enable

uniform sampler2DRect rec;
uniform sampler2DRect rec_colors;

void main(void)
{
    vec4 oldcol = texture2DRect(rec, gl_TexCoord[0].st);
    vec4 newcol = texture2DRect(rec_colors, vec2(oldcol.r*255.0, 0.0)); // palette index should be*255 bcs rectangle coordinates aren't normalized
    gl_FragColor.rgb = newcol.rgb;
    gl_FragColor.a = oldcol.g; // alpha from green part
}

Google 搜索了很多,我发现的任何类似帖子都通过修复 glUniform1i 调用中的纹理单元 ID 解决了,但对我来说这看起来绝对正常(至少,TEXTURE0 正确加载到 rec)。

最佳答案

您是否使用 glGetError 检查任何地方的错误?我相信你做错了什么。 glGetUniformLocation 应该针对链接程序而不是着色器执行。您在链接程序之前调用 glGetUniformLocation

请参阅手册页中的相关文本:http://www.opengl.org/wiki/GLAPI/glGetUniformLocation

分配给统一变量的实际位置不是 直到程序对象被成功链接才知道。后 链接已经发生,命令 glGetUniformLocation 可以用来获取 统一变量的位置。统一的变量位置和值只能 如果链接成功,则在链接后查询。

在开发过程中,您应该始终至少每帧检查一次 glGetError 是否有 opengl 错误。在您必须上网寻求帮助之前,它会提醒您注意这些问题。

关于c++ - 带有片段着色器的多个纹理单元不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9879455/

相关文章:

c++ - SDL_RenderReadPixels 返回一个黑色矩形?

c++ - 进行随机文件访问的有效方法?

c++ - Ubuntu 上 QtCreator 中的 Cocos2d-x

ios - GLSL 着色器错误 "Constructor calls may not have precision"

opengl - 无法获取指定着色器类型的子例程信息

c++ - c++删除指针数组中每个元素指向的对应元素

c++ - C2143 类型的错误 - 在 ',' 之前缺少 '<'

c++ - glCreateShader失败并返回0

c++ - OpenGL 光栅转换未产生预期结果

opengl - 我应该在统一缓冲区或着色器存储缓冲区对象内使用 `vec3` 吗?