在 OpenGL 4.5 中对盒子进行纹理处理 -(不起作用)

Nat*_*amm -1 c++ opengl

我画了一个盒子。我添加了处理 vao 和 vbo 的基本类。

class BasicObject_V2
{
public:
    BasicObject_V2(GLuint typeOfPrimitives = 0){
        this->typeOfPrimitives = typeOfPrimitives;
        switch (this->typeOfPrimitives){
            case GL_QUADS: numVertsPerPrimitive = 4; break;
}}
void allocateMemory(){
        glGenVertexArrays(1, &vaoID);
        glBindVertexArray(vaoID);

        glGenBuffers(1, &vboID);
        glBindBuffer(GL_ARRAY_BUFFER, vboID);

        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertexAttributes), &vertices[0], GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 48, (const void*)0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 48, (const void*)12);
        glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 48, (const void*)24);
        glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 48, (const void*)40);

        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glEnableVertexAttribArray(2);
        glEnableVertexAttribArray(3);
    }

    GLuint vboID;
    GLuint vaoID;
    GLuint typeOfPrimitives;
    GLuint numVertsPerPrimitive;

    int getNumberOfVertices(){
        return vertices.size();
    }

    struct vertexAttributes{
        glm::vec3 pos;
        glm::vec3 normal;
        glm::vec4 color;
        glm::vec2 texCoord;
    };

    std::vector<vertexAttributes> vertices;
};
Run Code Online (Sandbox Code Playgroud)

这是我的 Box 类。

class Box_V2 : public BasicObject_V2 {
public:

    Box_V2(float width = 1, float height = 1, float length = 1) : BasicObject_V2(GL_QUADS) {
        float wHalf = width / 2.0f;
        float hHalf = height / 2.0f;
        float lHalf = length / 2.0f;
        vertexAttributes va;
        glm::vec3 corners[8];
        corners[0] = glm::vec3(-wHalf, -hHalf, lHalf);
        corners[1] = (...)
        glm::vec3 normals[6];
        normals[0] = glm::vec3(0, 0, 1); // front
        //(...)

        // FRONT
        va.pos = corners[0];
        va.normal = normals[0];
        va.texCoord = glm::vec2(0.0, 0.0);
        vertices.push_back(va);
        //...
        allocateMemory();
    }
};
Run Code Online (Sandbox Code Playgroud)

我还为其设置了纹理(根据 opengl superible 示例),但它确实有效。

static GLubyte checkImage[128][128][4];
void makeCheckImage(void)
{
    int i, j, c;
    for (i = 0; i<128; i++) {
        for (j = 0; j<128; j++) {
            c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0)) * 255;
            checkImage[i][j][0] = (GLubyte)c;
            checkImage[i][j][1] = (GLubyte)c;
            checkImage[i][j][2] = (GLubyte)c;
            checkImage[i][j][3] = (GLubyte)255;     
        }}}

void init(){
    glClearColor(0.7, 0.4, 0.6, 1);

    //Create a Texture
    makeCheckImage();

    //Texure 
    glGenTextures(4, tex);
    //glCreateTextures(GL_TEXTURE_2D, 4, tex);//4.5
    glTextureStorage2D(tex[0], 0, GL_RGBA32F, 2, 2);    
    glBindTexture(GL_TEXTURE_2D, tex[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGBA, GL_FLOAT, checkImage);
    //glTextureSubImage2D(tex[0], 0, 0, 0, 2, 2, GL_RGBA, GL_FLOAT, checkImage);//4.5

    //load the shader
    programID = loadShaders("vertex.vsh", "fragment.fsh");
    glUseProgram(programID);

    //create a box 
    box_v2 = new Box_V2();

    glBindTexture(GL_TEXTURE_2D, tex[0]);   
}}

    void drawing(BasicObject* object){
       glBindVertexArray(object->vaoID);
       glDrawArrays(object->typeOfPrimitives, 0, object->getNumberOfVertices() * object->numVertsPerPrimitive);
       glBindVertexArray(0);
}
Run Code Online (Sandbox Code Playgroud)

这是我的着色器:VS:

#version 450 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec4 color;
layout(location = 3) in vec2 texCoord;

uniform mat4 rotate;(...)

out vec4 v_normal;
out vec4 v_color;
out vec4 v_pos;
out vec2 v_texCoord;

void main(){
    v_normal = rotate*vec4(normal,1);//*model;
    v_color=color;
    v_texCoord=texCoord;
    gl_Position = rotate*scale*trans*vec4(pos.xyz, 1);
}
Run Code Online (Sandbox Code Playgroud)

还有FS:

#version 450 core
in vec4 v_color;
in vec2 v_texCoord;
uniform sampler2D ourTexture;
out vec4 outColor;

void main(){ 
  //outColor=texelFetch(ourTexture, ivec2(gl_FragCoord.xy), 0); //4.5  
  outColor=texture(ourTexture,v_texCoord*vec2(3.0, 1.0));
}
Run Code Online (Sandbox Code Playgroud)

现在它绘制了一个黑色的盒子,上面没有任何纹理。我是 OpenGL 新手,我找不到问题出在哪里。

Nic*_*las 5

您的代码有很多问题。看起来你试图以一种方式编写它,然后尝试以另一种方式编写它,导致某种弗兰肯斯坦的代码,它实际上不是一种方式或另一种方式。

glGenTextures(4, tex);
//glCreateTextures(GL_TEXTURE_2D, 4, tex);//4.5
glTextureStorage2D(tex[0], 0, GL_RGBA32F, 2, 2); 
Run Code Online (Sandbox Code Playgroud)

这是一个完美的例子。您使用非 DSAglGenTextures呼叫,但您立即转身并使用DSA glTextureStorage2D呼叫就可以了。你不能这样做。为什么?因为tex[0]还没有创建。

glGenTextures只分配纹理的名称,而不分配其状态数据。只有绑定纹理才能获取内容。这就是 DSA 引入这些glCreate*功能的原因;他们为对象分配名称和状态。这也是为什么glCreateTextures要设定一个目标;该目标是纹理对象状态的一部分。

简而言之,注释掉的调用始终是正确的。查看编写的代码,glTextureStorage2D调用失败并出现 OpenGL 错误(仅供参考:打开 KHR_debug 以查看何时发生错误)。

那么,让我们看看如果我们去掉失败的部分,您的代码会是什么样子:

glGenTextures(4, tex);
glBindTexture(GL_TEXTURE_2D, tex[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGBA, GL_FLOAT, checkImage);
Run Code Online (Sandbox Code Playgroud)

这里有两个问题。首先,正如 BDL 提到的,您的数据描述不正确。你正在传递GLubytes,但你告诉 OpenGL 你正在传递GLfloats。不要对 OpenGL 撒谎。

其次,有内部格式。因为您使用了未调整大小的内部格式(并且因为您不在 OpenGL ES 领域),所以您的实现选择的格式将是unsigned normalized。它不会是 32 位浮点格式。如果您想要其中之一,则必须明确要求,并使用GL_RGBA32F.

此外,因为您为纹理分配了可变存储(即:因为glTextureStorage2D失败),所以现在遇到了问题。您只分配了一层 mipmap 级别,但默认过滤模式将尝试从多个 mipmap 中获取。并且您永远不会将纹理的mipmap 范围设置为仅从第一个开始采样。所以你的纹理不完整。不可变的存储纹理将使 mipmap 范围与您分配的范围相匹配,但可变的存储纹理就不太好了。

创建可变存储纹理时,您应该始终设置 mipmap 范围:

glTexParameteri(GL_TEXTURE2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE2D, GL_TEXTURE_MAX_LEVEL, 0); //It's a closed range.
Run Code Online (Sandbox Code Playgroud)

最后,您将纹理绑定到单元 0 进行渲染(主要是偶然的,因为您从未调用过glActiveTexture)。但你不必费心通过将ourTexture统一值设置为 0 来通知你的着色器。