当前位置: 首页 > 知识库问答 >
问题:

碎片着色器中未使用纹理数据-OpenGL

雷晋
2023-03-14

我正在OpenGL中练习纹理,将定义为白色的简单纹理应用到四边形上。代码编译和运行良好,但四元体的颜色只是黑色,而不是我指定的白色。

我认为这是因为我的片段着色器没有进行正确的采样,就像它从纹理函数返回的数据都是零,因此四边形的纹理变为黑色。我之所以这么想,是因为当我运行程序时,我可以把白色变成清晰的颜色,并稍微移动四边形上的一个顶点,以便看到背景(因为它通常会填充整个曲面)。然后我可以清楚地看到白色的背景,上面是黑色的四边形。所以一些输出颜色是从片段着色器生成的,这是错误的,因为我提供的小像素阵列只是白色。问题是我不知道为什么我的代码会产生错误的结果。我正试图在一本书中遵循这一点,书中使用的代码基本相同。我也试着在不同的教程中查找,但它们似乎都使用相同的方法,所以我被卡住了。

[编辑]

我已经找到了一些问题。通过使用glGetError()进行一些错误跟踪,我发现这行代码:

glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGB8, 4, 4);

返回错误代码1282(无效操作),因为第二个参数级别为0。如果我将其设置为1,错误就消失了。然后问题变成了这一行:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_R, GL_FLOAT, myTexture);

它返回相同的错误,但不会通过更改level参数得到修复。

这是我使用的片段和顶点着色器:

片段着色器

// FRAGMENT SHADER
#version 330

uniform sampler2D tex;

in vec2 vs_tex_coord;

layout (location = 0) out vec4 outputColor;

void main(void)
{
    outputColor = texture(tex, vs_tex_coord);
}

顶点着色器

// VERTEX SHADER
#version 330

layout(location = 0) in vec4 position;
layout(location = 1) in vec2 in_tex_coord;

uniform vec2 offset;

out vec2 vs_tex_coord;

void main(void)
{
    vec4 finalOffset = vec4(offset.x, offset.y, 0.0, 0.0);
    gl_Position = position + finalOffset;
    vs_tex_coord = in_tex_coord;
}

我用于纹理对象生成和存储的代码非常简单:

glGenTextures(1, &textureHandle);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureHandle);

glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGB8, 4, 4);

const GLubyte myTexture[] = {0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF,
                             0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF,
                             0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF,
                             0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF};

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RGB, GL_UNSIGNED_BYTE, myTexture);

myTexture只包含内部格式为RGB的4x4纹理,每个组件有4位。我把它们都调成了白色。

然后我简单地生成一个默认采样器,如下所示:

glGenSamplers(1, &mySampler);

glBindSampler(0, mySampler);

最后我呈现:

glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glUseProgram(theProgram);

GLuint samplerLoc = glGetUniformLocation(theProgram, "tex");

if (samplerLoc == -1)
    printf("Location name could not be found...\n");

glUniform1i(samplerLoc, 0);

glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(16 * sizeof(float)));

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

我上传到VBO的数组是:

const float vertexPositions[] =
{
    // Vertex position
    -0.8f, -1.0f, 0.0f, 1.0f,
     1.0f, -1.0f, 0.0f, 1.0f,
     1.0f,  1.0f, 0.0f, 1.0f,
    -1.0f,  1.0f, 0.0f, 1.0f,

    // Texture coordinates
    0.0f, 0.0f,
    1.0f, 0.0f,
    1.0f, 1.0f,
    0.0f, 1.0f
};

是因为我错误地使用了采样器对象吗?我需要在它们上设置某种设置才能让它正常工作吗?我错过了一些中间步骤吗?

你可以看到白色的背景,我有目的地移动了一个顶点的位置,这样你就可以看到白色背景下的黑色四边形。

共有1个答案

巫马安怡
2023-03-14

好吧,经过一些错误跟踪,我终于发现了问题!:)对于任何将来遇到这个问题的人,这里有一个(非常简单…doh!)解决方案

首先,这里有一行:

glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGB8, 4, 4);

返回了一个OpenGL错误1281(无效操作),这是因为第二个参数级别必须至少为1,才能为基本图像存储足够的内存,无论您是否想要使用mipmap(我认为应该为0)。因此,将其从0更改为1修复了它。

其次,这一行:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_R, GL_FLOAT, myTexture);

format参数有问题,在上面的代码片段中显示为GL_R。这完全是错误的。查看该功能的官方文档,它说明了以下内容:

format指定像素数据的格式。接受以下符号值:GL_红色、GL_RG、GL_RGB、GL_BGR、GL_RGBA、GL_BGRA、GL_深度分量和GL_模板索引。

之前在glTextStorage2D中指定的类型I使用GL_RGB8,其基本内部格式为GL_RGB,正确的版本是:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RGB, GL_UNSIGNED_BYTE, myTexture);

修复这两个问题导致出现纹理结果:)

 类似资料:
  • 标准着色器 Unity 标准着色器是一个内置着色器,具有非常全面的功能。它可以用于渲染『真实世界』的对象,例如,石头、木材、玻璃、塑料和金属,并支持各种各样的着色器类型和组合。通过使用或不使用材质编辑器中的各种纹理插槽和参数,可以很容易地启动或禁用其功能。 标准着色器还包括一个称为 物理着色器(Physically Based Shading,PBS) 的高级光照模型。物理着色器以模拟真实世界的方

  • 我是OpenGL的新手,在整理如何将纹理和着色器绑定到VBOs时遇到了困难。 我正在使用Cinder的纹理和着色器类。以下是我绘制方法的一部分: 在上面的代码中,如果我注释掉对mShader的调用。bind(),我的球体VBO将显示纹理(myImage)。我的着色器适用于普通(无纹理)形状,但当我在绘制任何带有包裹纹理的形状之前绑定着色器时,它会阻止纹理显示。 这是我使用的着色器的问题,还是我不理

  • 我想在FBO中加载两个纹理,其中一个纹理包含HDR图像,我的第一个目标是将图像从第一个纹理“复制”到第二个纹理(该纹理为空),并称为“下采样纹理”。 所以我创建FBO,加载我想用颜色_附件_0书写的纹理,并绑定它;然后初始化我的着色器程序并渲染一个四边形,其中包含我要在GL\u texture\u 0中读取的纹理。 然后我解开FBO并绑定“DownSamplingTex”,然后画一个四元组。 我不

  • 我有一个非常简单的OpenGL应用程序,只渲染一个带纹理的四边形。这是我的代码,效果很好(带纹理的四边形看起来很好): 然后我想介绍一个简单的着色器。所以我稍微修改了我的代码: 顶点着色器: 片段着色器: 现在我得到的只是一个黑色的四边形:-( 我已经尝试并测试了很多东西: 着色器编译良好(无错误) 有人知道为什么我在使用着色器时看不到我的纹理吗?

  • 我正在努力发送多个纹理到一个单一的着色器,并有一个奇怪的问题,在着色器中的两个采样器似乎得到相同的纹理数据。我知道还有很多其他的多纹理问题和答案(这里有一些我已经读过很多次了1,2,3),但一些bug正在逃避我,我开始失去我的弹珠。我很有信心我已经把一切都安排好了,但显然还是有一些问题。 所以,目前我有形状,材料,纹理,和着色器类。我的shape类是执行实际绘制的父类。它有一个具有着色器和纹理数组

  • 我正在学习opengl,我认为我非常了解片段着色器。我的直觉是片段着色器应用于每个像素一次,但最近在处理纹理时,我对它们的确切工作方式感到困惑。 首先,片段着色器通常会获取一系列纹理坐标,因此如果我有一个四边形,片段着色器将获取四边形的4个角的纹理坐标。现在我不明白的是采样过程,即获取纹理坐标并在该纹理坐标处获得适当颜色值的过程。具体来说,由于我只提供4个纹理坐标,opengl如何知道为颜色值采样