在OpenGL 4.5中纹理框 - (不起作用)

时间:2016-06-08 08:06:59

标签: 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;
};

这是我的Box-class。

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();
    }
};

我也为它设置了纹理(根据opengl的可行例子),但它确实起作用。

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);
}

这是我的着色器: 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);
}

和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));
}

现在它绘制一个没有任何纹理的黑盒子。我是OpenGL的新手,我找不到问题所在。

2 个答案:

答案 0 :(得分:3)

您的代码存在很多问题。看起来你试图用一种方式写它,然后尝试用另一种方式写它,导致某种类型的弗兰肯斯坦代码,它不是真的这样或那样。

glGenTextures(4, tex);
//glCreateTextures(GL_TEXTURE_2D, 4, tex);//4.5
glTextureStorage2D(tex[0], 0, GL_RGBA32F, 2, 2); 

这是一个很好的例子。您使用非DSA glGenTextures来电,但是您立即转身并使用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);

这里有两个问题。首先,正如BDL所提到的,您的数据描述不正确。您已经通过了GLubyte,但是您告诉OpenGL您正在通过GLfloat。不要骗OpenGL。

其次,internal format。因为您使用了未经过大小写的内部格式(并且因为您不在OpenGL ES中),所以您的实现选择的格式将是 unsigned normalized 。它不会是一个32位浮点格式。如果您需要其中一个,则必须明确要求GL_RGBA32F

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

在创建可变存储纹理时,总是设置mipmap范围:

glTexParameteri(GL_TEXTURE2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE2D, GL_TEXTURE_MAX_LEVEL, 0); //It's a closed range.

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

答案 1 :(得分:0)

您的代码存在以下几个问题:

数据类型与数据不匹配

数据采用无符号字节格式(GLubyte checkImage[128][128][4]),每像素大小为4字节(每个通道1个字节),但是告诉OpenGL它是GL_FLOAT格式的,每个像素需要16个字节(每个通道4个字节)。

数据存储

见246Nt。

的回答

<强>的mipmap /过滤器

默认情况下,OpenGL将缩小过滤器设置为GL_LINEAR_MIPMAP_LINEAR,该过滤器要求用户为纹理提供有效的mipmap。可以将此过滤器更改为GL_LINEARGL_NEAREST,不需要mipmap(请参阅glTexParameteri),也可以生成mipmap(glGenerateMipmaps)。