2014-05-10 76 views
0

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

所以,这里是我在做什么的摘录:

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

render方法:

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。

+0

您不使用'sampler2D'对立方体贴图进行采样,而是使用'samplerCube'和3D纹理坐标来表示查找方向。我不确定你目前正在用2D坐标来做什么? –

+0

哦!非常感谢!我已经改变了片段着色器,现在它可以工作(纹理仍然是扭曲的,但是我认为我会自己去做)。 – pedjjj

+0

这里工作片段着色器: '#version 130 in vec4 VertPosition; in vec4 VertNormal; in vec4 VertColor; in vec4 VertTexture; //顶点着色器的插值,类似于教程:-) uniform vec3 lightPos; uniform samplerCube skyBoxTextureSampler; //从教程中知道要访问哪个纹理:-) void main() { vec4 color = VertColor; gl_FragColor = texture(skyBoxTextureSampler,VertTexture.xyz); //看起来像纹理本身没有加载,因为这也会产生黑色的vec2(0.8f,0.2f)); // \t // vec4(1.0f,1.0f,0.9f,1.0f); // }' – pedjjj

回答

0

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