【问题标题】:OpenGL GL_TEXTURE_CUBE_MAP no textures / blackOpenGL GL_TEXTURE_CUBE_MAP 无纹理/黑色
【发布时间】:2014-06-28 02:10:18
【问题描述】:

我想做一个简单的 CG 任务:绘制一个带有 6 面纹理的天空图立方体。已经阅读了很多教程,但是纹理存在一些问题。立方体的所有 6 个面都是完全黑色的(但是如果我在片段着色器中用简单的 vec4(1.0f, ...) 替换纹理(..)调用,墙壁将被着色,所以它必须是纹理)。

所以,这是我正在做的事情的摘录:

void SkyCube::init() {
    mShader = new Shader("./Shader/skybox.vs", "./Shader/skybox.fs");

    // from: https://www.opengl.org/wiki/Common_Mistakes#Creating_a_Cubemap_Texture

    glEnable(GL_TEXTURE_CUBE_MAP);
    glGenTextures(1, &mTextureId);
    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureId);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);

    // now load the textures from TGA files and make them available to OpenGL
    TgaLoader * tgaLoader = new TgaLoader();
    string texturefilenames[] = {"back", "front", "bottom", "top", "left", "right"};
    int texturedefs[] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
    for (int i = 0; i < 6; i++) {
        tgaLoader->loadTga(mTextures[i], "data/skycube/" + texturefilenames[i] + ".tga");
        glTexImage2D(texturedefs[i], 0, GL_RGB, mTextures[i].width, mTextures[i].height,
                0, GL_BGR, GL_UNSIGNED_BYTE, mTextures[i].imageData);
    }
    delete tgaLoader;

    mVboSkyCube = this->generateSkyCubeVBO(vec3(-1.0f, -1.0f, -1.0f), vec3(1.0f, 1.0f, 1.0f));

    glDisable(GL_TEXTURE_CUBE_MAP);
}

generateSkyCubeVBO 方法基本上是生成所有顶点和纹理归一化坐标:

VertexBufferObjectAttribs* SkyCube::generateSkyCubeVBO(const vec3 &mi, const vec3 &ma) {
    vector<vec3> vertices;
    vector<vec3> normals;
    vector<vec2> textureUV;
    // tofo liste mit texture koords
    // 00 01
    // 10 11
    // 2d vec

    vertices.push_back(vec3(mi.x, ma.y, mi.z));
    vertices.push_back(vec3(mi.x, ma.y, ma.z));
    vertices.push_back(vec3(ma.x, ma.y, ma.z));
    vertices.push_back(vec3(ma.x, ma.y, mi.z));

    normals.push_back(vec3(0.0f, 1.0f, 0.0f));
    normals.push_back(vec3(0.0f, 1.0f, 0.0f));
    normals.push_back(vec3(0.0f, 1.0f, 0.0f));
    normals.push_back(vec3(0.0f, 1.0f, 0.0f));

    textureUV.push_back(vec2(0.0f, 0.0f));
    textureUV.push_back(vec2(0.0f, 1.0f));
    textureUV.push_back(vec2(1.0f, 0.0f));
    textureUV.push_back(vec2(1.0f, 1.0f));


    vertices.push_back(vec3(mi.x, mi.y, mi.z));
    vertices.push_back(vec3(ma.x, mi.y, mi.z));
    vertices.push_back(vec3(ma.x, mi.y, ma.z));
    vertices.push_back(vec3(mi.x, mi.y, ma.z));

    normals.push_back(vec3(0.0f, -1.0f, 0.0f));
    normals.push_back(vec3(0.0f, -1.0f, 0.0f));
    normals.push_back(vec3(0.0f, -1.0f, 0.0f));
    normals.push_back(vec3(0.0f, -1.0f, 0.0f));

    textureUV.push_back(vec2(0.0f, 0.0f));
    textureUV.push_back(vec2(0.0f, 1.0f));
    textureUV.push_back(vec2(1.0f, 0.0f));
    textureUV.push_back(vec2(1.0f, 1.0f));


    vertices.push_back(vec3(mi.x, mi.y, mi.z));
    vertices.push_back(vec3(mi.x, ma.y, mi.z));
    vertices.push_back(vec3(ma.x, ma.y, mi.z));
    vertices.push_back(vec3(ma.x, mi.y, mi.z));

    normals.push_back(vec3(0.0f, 0.0f, -1.0f));
    normals.push_back(vec3(0.0f, 0.0f, -1.0f));
    normals.push_back(vec3(0.0f, 0.0f, -1.0f));
    normals.push_back(vec3(0.0f, 0.0f, -1.0f));

    textureUV.push_back(vec2(0.0f, 0.0f));
    textureUV.push_back(vec2(0.0f, 1.0f));
    textureUV.push_back(vec2(1.0f, 0.0f));
    textureUV.push_back(vec2(1.0f, 1.0f));


    vertices.push_back(vec3(mi.x, mi.y, ma.z));
    vertices.push_back(vec3(ma.x, mi.y, ma.z));
    vertices.push_back(vec3(ma.x, ma.y, ma.z));
    vertices.push_back(vec3(mi.x, ma.y, ma.z));

    normals.push_back(vec3(0.0f, 0.0f, 1.0f));
    normals.push_back(vec3(0.0f, 0.0f, 1.0f));
    normals.push_back(vec3(0.0f, 0.0f, 1.0f));
    normals.push_back(vec3(0.0f, 0.0f, 1.0f));

    textureUV.push_back(vec2(0.0f, 0.0f));
    textureUV.push_back(vec2(0.0f, 1.0f));
    textureUV.push_back(vec2(1.0f, 0.0f));
    textureUV.push_back(vec2(1.0f, 1.0f));


    vertices.push_back(vec3(mi.x, mi.y, mi.z));
    vertices.push_back(vec3(mi.x, mi.y, ma.z));
    vertices.push_back(vec3(mi.x, ma.y, ma.z));
    vertices.push_back(vec3(mi.x, ma.y, mi.z));

    normals.push_back(vec3(-1.0f, 0.0f, 0.0f));
    normals.push_back(vec3(-1.0f, 0.0f, 0.0f));
    normals.push_back(vec3(-1.0f, 0.0f, 0.0f));
    normals.push_back(vec3(-1.0f, 0.0f, 0.0f));

    textureUV.push_back(vec2(0.0f, 0.0f));
    textureUV.push_back(vec2(0.0f, 1.0f));
    textureUV.push_back(vec2(1.0f, 0.0f));
    textureUV.push_back(vec2(1.0f, 1.0f));


    vertices.push_back(vec3(ma.x, mi.y, mi.z));
    vertices.push_back(vec3(ma.x, ma.y, mi.z));
    vertices.push_back(vec3(ma.x, ma.y, ma.z));
    vertices.push_back(vec3(ma.x, mi.y, ma.z));

    normals.push_back(vec3(1.0f, 0.0f, 0.0f));
    normals.push_back(vec3(1.0f, 0.0f, 0.0f));
    normals.push_back(vec3(1.0f, 0.0f, 0.0f));
    normals.push_back(vec3(1.0f, 0.0f, 0.0f));

    textureUV.push_back(vec2(0.0f, 0.0f));
    textureUV.push_back(vec2(0.0f, 1.0f));
    textureUV.push_back(vec2(1.0f, 0.0f));
    textureUV.push_back(vec2(1.0f, 1.0f));


    GLuint nrVertices = vertices.size();
    VertexBufferObjectAttribs::DATA *attrData = new VertexBufferObjectAttribs::DATA[nrVertices];

    for (GLuint i = 0; i < nrVertices; ++i) {
        vec3 v = vertices[i];
        vec3 n = normals[i];
        vec2 t = textureUV[i];

        attrData[i].vx = v.x;
        attrData[i].vy = v.y;
        attrData[i].vz = v.z;
        attrData[i].vw = 1.0f;

        attrData[i].nx = n.x;
        attrData[i].ny = n.y;
        attrData[i].nz = n.z;
        attrData[i].nw = 0.0f;

        attrData[i].tx = t.x;
        attrData[i].ty = t.y;
        attrData[i].tz = 0.0f;
        attrData[i].tw = 0.0f;
    }

    VertexBufferObjectAttribs *vbo = new VertexBufferObjectAttribs();
    vbo->setData(attrData, GL_STATIC_DRAW, nrVertices, GL_QUADS);

    vbo->addAttrib(VERTEX_POSITION);
    vbo->addAttrib(VERTEX_NORMAL);
    vbo->addAttrib(VERTEX_COLOR);
    vbo->addAttrib(VERTEX_TEXTURE);
    vbo->bindAttribs();

    delete[] attrData;

    return vbo;
}

效果很好,所有纹理都已成功加载。 顶点着色器:

// OpenGL 3.3
#version 130

// following is probably not really needed
#define VERT_POSITION   0
#define VERT_NORMAL     1
#define VERT_COLOR  2
#define VERT_TEXTURE    3

uniform mat4x4 matModel;
uniform mat4x4 matView;
uniform mat4x4 matProjection;

attribute vec4 Position;
attribute vec4 Normal;
attribute vec4 Color;
attribute vec4 Texture;

out vec4 VertPosition;
out vec4 VertNormal;
out vec4 VertColor;
out vec4 VertTexture;

void main()
{      
    VertPosition = Position; 
    VertNormal   = Normal;
    VertColor    = Color;
    VertTexture  = Texture;

    gl_Position = matProjection * matView * matModel * vec4(Position.xyz, 1);
}

片段着色器:

// OpenGL 3.3
#version 130

in vec4 VertPosition;
in vec4 VertNormal;
in vec4 VertColor;
in vec4 VertTexture; // Interpolated values from the vertex shaders, similar to the tutorial :-)

uniform vec3 lightPos;
uniform sampler2D skyBoxTextureSampler; // to know which texture to access, from the tutorial :-)

void main()
{
    vec4 color = VertColor;
    gl_FragColor = texture( skyBoxTextureSampler, VertTexture.xy);   //vec4( 1.0f, 1.0f, 0.9f, 1.0f); //
}

渲染方法:

void SkyCube::render(const Transform& trans) {
    mat4 projection = trans.projection;
    mat4 view = trans.view;
    mat4 model = mat4::identitiy();

    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
    glEnable(GL_TEXTURE_CUBE_MAP);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureId);

    mShader->bind();

    mShader->setMatrix("matProjection", projection, GL_TRUE);
    mShader->setMatrix("matView", view, GL_TRUE);
   // mShader->setMatrix("Texture")

    model = mat4::scale(20.0f, 20.0f, 20.0f);
    mShader->setMatrix("matModel", model, GL_TRUE);

    // set the texture
    mShader->seti("skyBoxTextureSampler", 0);


    mVboSkyCube->render();

    mShader->release();

    glPopClientAttrib();
    glPopAttrib();
}

VBO 对象的渲染方法如下:

void VertexBufferObjectAttribs::render() {
    GLint size = m_attribLocations.size();
    glBindBuffer(GL_ARRAY_BUFFER, m_bufferId);
    for (GLint i = 0; i < size; ++i) {
        GLint attribLoc = m_attribLocations[i];
        glVertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, sizeof (DATA), ((GLchar*) NULL + 4 * sizeof (GLfloat) * i));
    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    for (GLint i = 0; i < size; ++i)
        glEnableVertexAttribArray(m_attribLocations[i]);


    if (m_useIndexBuffer) {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferId);

        if (m_dynamicRendering) {
            glDrawElements(m_primitiveMode, m_nrDynamicIndices, GL_UNSIGNED_INT, 0);
        } else {
            glDrawElements(m_primitiveMode, m_nrIndices, GL_UNSIGNED_INT, 0);
        }
    } else {
        if (m_dynamicRendering) {
            glDrawArrays(m_primitiveMode, 0, m_nrDynamicVertices);
        } else {
            glDrawArrays(m_primitiveMode, 0, m_nrVertices);
        }
    }


    for (GLint i = 0; i < size; ++i)
        glDisableVertexAttribArray(m_attribLocations[i]);

}

如果我将此代码与教程中的步骤进行比较,我看不出有任何缺失或顺序错误。

请注意,我不能使用更新的 GLSL 版本,因为我当前的 Linux 版本仅支持 1.3。

【问题讨论】:

  • 您不使用sampler2D 对立方体贴图进行采样,而是使用samplerCube 和表示查找方向的3D 纹理坐标。我不确定您目前正在尝试使用 2D 坐标做什么?
  • 哦!非常感谢!我已经更改了片段着色器,现在它可以工作了(纹理仍然失真,但我想我会自己解决这个问题:)
  • 这里是工作片段着色器:#version 130 in vec4 VertPosition; in vec4 VertNormal; in vec4 VertColor; in vec4 VertTexture; // Interpolated values from the vertex shaders, similar to the tutorial :-) uniform vec3 lightPos; uniform samplerCube skyBoxTextureSampler; // to know which texture to access, from the tutorial :-) void main() { vec4 color = VertColor; gl_FragColor = texture( skyBoxTextureSampler, VertTexture.xyz); // looks like the texture itself is not loaded, because this also yields black vec2( 0.8f, 0.2f));// //vec4( 1.0f, 1.0f, 0.9f, 1.0f); // }

标签: opengl textures glsl


【解决方案1】:

好的,所以答案 - 正如上面评论中已经写的那样,问题在于着色器包含一个 sampler2D,而它应该使用的是 samplerCube。这是因为在 C++ 代码中我也相应地使用了 ...Cube 函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多