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

OpenGL纹理未通过GLSL渲染

白哲茂
2023-03-14

所以我有一个非常简单的glsl着色器,可以用纹理和平行光渲染对象。

现在我有一个非常艰难的时间试图得到的纹理显示,其他一切工作,除此之外。

当我禁用着色器(glUseProgram(0))时,纹理以黑色和白色渲染,但当我启用它时,整个网格是单一颜色,没有纹理,当我尝试不同的纹理时,它会改变颜色。

这就是我加载纹理的方式

data = CImg<unsigned char>(src);
glGenTextures(1, &m_textureObj);
glBindTexture(GL_TEXTURE_2D, m_textureObj);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, data.width(), data.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

这就是我如何绑定我的纹理

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

这是我的顶点着色器

#version 330

layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 TexCoord;
layout (location = 2) in vec3 Normal;

uniform mat4 gWVP;
uniform mat4 gWorld;

out vec2 TexCoord0;
out vec3 Normal0;

void main()
{
    gl_Position = (gWVP * gWorld) * vec4(Position, 1.0);
    TexCoord0 = TexCoord;
    Normal0 = (gWorld * vec4(Normal, 0.0)).xyz;
}

这是我的碎片着色器

#version 330

in vec2 TexCoord0;
in vec3 Normal0;                                                                    

out vec4 FragColor;                                                                 

struct DirectionalLight                                                             
{                                                                                   
    vec3 Color;                                                                     
    float AmbientIntensity;                                                         
    float DiffuseIntensity;                                                         
    vec3 Direction;                                                                 
};                                                                                  

uniform DirectionalLight gDirectionalLight;                                         
uniform sampler2D gSampler;                                                         

void main()                                                                         
{                                                                                   
    vec4 AmbientColor = vec4(gDirectionalLight.Color, 1.0f) *                       
                    gDirectionalLight.AmbientIntensity;                         

    float DiffuseFactor = dot(normalize(Normal0), -gDirectionalLight.Direction);    

    vec4 DiffuseColor;                                                              

    if (DiffuseFactor > 0) {                                                        
        DiffuseColor = vec4(gDirectionalLight.Color, 1.0f) *                        
                   gDirectionalLight.DiffuseIntensity *                         
                   DiffuseFactor;                                               
    }                                                                               
    else {                                                                          
        DiffuseColor = vec4(0, 0, 0, 0);                                            
    }                                                                               

    FragColor = texture2D(gSampler, TexCoord0.xy) *
            (AmbientColor + DiffuseColor);
}

最后但并非最不重要的是,我告诉我的着色器使用正确的纹理

glUniform1i(GetUniformLocation("gSampler"), 0);

我在网上阅读了大量关于如何正确完成这个简单任务的文章,并以一堆不同的配置运行它,结果却变得沮丧。

如果有人能指出我做错了什么,我会很激动,我肯定我错过了一个愚蠢的细节,但我似乎找不到它。请不要让我参考https://www.opengl.org/wiki/Common_Mistakes#Creating_a_complete_texture谢谢你的阅读。

这就是我创建网格并将其上传到GPU的方式。这是顶点构造器顶点(x,y,z,u,v)

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

unsigned int Indices[] = {
        0, 3, 1,
        1, 3, 2,
        2, 3, 0,
        1, 2, 0
    };
    Vertex Vertices[4] = {
        Vertex(-1.0f, -1.0f, 0.5773f, 0.0f, 0.0f),
        Vertex(0.0f, -1.0f, -1.15475f, 0.5f, 0.0f),
        Vertex(1.0f, -1.0f, 0.5773f,  1.0f, 0.0f),
        Vertex(0.0f, 1.0f, 0.0f, 0.5f, 1.0f)
    };
    Mesh *data = new Mesh(Vertices, 4, Indices, 12);

    glGenBuffers(1, &vbo);
        glGenBuffers(1, &ibo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

            glEnableVertexAttribArray(0);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
            glEnableVertexAttribArray(1);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(12));
            glEnableVertexAttribArray(2);
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(24));

            glBufferData(GL_ARRAY_BUFFER, data->count*Vertex::Size(),  data->verts, GL_STATIC_DRAW);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, data->indsCount*sizeof(unsigned int), data->inds, GL_STATIC_DRAW);

    unsigned int Vertex::Size() {
        return 32;
    }

 /*In the update function*/
 glDrawElements(GL_TRIANGLES, data->indsCount, GL_UNSIGNED_INT, 0);

这是我的顶点类http://pastebin.com/iYwjEdTQ

编辑

我已经解决了!我用老方法绑定顶点,在ratchet freak向我展示了如何正确绑定它之后,我注意到我正在将纹理坐标绑定到位置2,但在位置1中我正在寻找的着色器中。

glEnableVertexAttribArray(2);
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(24));

(frag着色器)

layout (location = 1) in vec2 TexCoord;

所以我把片段着色器改为

layout (location = 2) in vec2 TexCoord;

现在它工作得很好。感谢ratchet freak和birdypme的帮助我会接受ratchet freak的答案,因为这会引导我找到解决方案,但你们都把我引向了正确的方向。

共有2个答案

姚培
2023-03-14

一般来说,应该使用sizeof()而不是硬编码的偏移量,以避免糟糕的意外情况。

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(0));
    glEnableClientState(GL_NORMAL_ARRAY);
    glNormalPointer(GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(3*sizeof(float)));
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(6*sizeof(float)));

在顶点。H

    static unsigned int Size() {
        return 8*sizeof(float);
    }

然而,这不太可能正确回答你的问题。我不是为了保留顶点而删除我的答案。h pastebin,这可能很重要,但一旦发布了有效答案,我可能会删除它。

笪涛
2023-03-14

这就是你的问题:

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(0));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(12));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(24));

这将使用旧的和不推荐的固定函数样式规范,而不是您希望使用的glvertexattributepointer:

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(12));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(24));

我看到的另一个问题是您的Vertex类在构造函数中不采用法线。Vertex::size()应该等于sizeof(Vertex)

 类似资料:
  • 我正在尝试使用OpenGL GLSL着色器渲染到纹理。首先,我尝试用白色填充30x30纹理的每个像素。我将顶点着色器索引从0传递到899,表示纹理的每个像素。对吗?顶点着色器: 片段着色器:

  • 我有一个有两个纹理的全屏四块。 我想根据用户选择混合任意形状的两个纹理。 例如,quad一开始是100%texture0,而texture1是透明的。 为了实现任意形状,我假设我需要创建一个与texture0和texture1大小相同的alpha mask纹理? 然后我把纹理传递给frag shader来检查值,如果值是0,那么texture0,如果值是1,那么混合texture0和texture

  • 纹理根本不渲染,几何体都是黑色的。 截图:http://i.imgur.com/ypMdQY4.png 代码:http://pastebin.com/SvB8rxxt 我也会链接到我试图渲染的纹理和transformations.py模块,但是我没有被允许放置两个以上链接的声誉。谷歌搜索“现代opengl 02”会给你前者的教程,“转换py”会给你后者。 搜索“纹理材料开始”以查找纹理材料的设置位

  • 问题内容: 屏幕外渲染到纹理绑定的屏幕外帧缓冲对象应该是微不足道的,但是我遇到了一个问题,我无法解决问题。 我的完整示例程序(目前仅2D!)在这里: http://pastebin.com/hSvXzhJT 请参阅下面的一些说明。 我正在创建一个RGBBA纹理对象512x512,并将其绑定到FBO。此时完全不需要2D深度或其他渲染缓冲区。 以下极其简单的着色器可渲染此纹理: 顶点着色器: 在aPo

  • 使用LWJGL的OpenGL版本1.1和2D纹理,我发现自己卡住了... 出于某种原因,LWJGL引擎不会在2D图层上渲染加载的纹理...相反,我得到了一个白色正方形... 我假设我很有可能在代码的某个地方遗漏了什么..以下是与此类事件相关的全部代码.. 加载OpenGL环境: 进入2D绘图模式(用于绘制纯色正方形的功能-通过glcolor函数进行测试,然后通过glvertex调用尺寸): 加载映

  • 我做了一个在上面渲染天空盒和粒子的应用程序。我想添加一些效果,我需要使用帧缓冲区来渲染天空盒、粒子颜色、深度和位置以分离纹理。然后我想使用简单的着色器来使用这些纹理中的值并以适当的方式混合它们。我为纹理、帧缓冲区和屏幕四边形(渲染简单的矩形)编写了辅助类,但不幸的是——当我尝试使用它时没有任何渲染。 当绑定帧缓冲区被注释掉时,我的场景如下所示: 修改着色器表明深度和位置值计算正确。因此问题在于纹理