c++ - GLSL 纹理函数只为天空盒返回黑色

标签 c++ visual-studio opengl glsl

我正在尝试通过使用 GLSL 对四边形进行纹理化来为我的 OpenGL 场景生成一个天空盒。但是,当我尝试使用纹理生成天空盒颜色时,天空盒只是变成了黑色。天空盒在我手动设置颜色时起作用,所以我基本上将问题缩小到我设置纹理的方式有问题。我还为纹理函数弄乱了一堆不同的 eyeDirection vector 值,但我仍然只得到一个黑色方 block 。

这是我的片段着色器:

#version 450 compatibility

layout(binding=0) uniform samplerCube currTexture;

smooth in vec3 eyeDirection;

out vec4 fragmentColor;

void main() {
    fragmentColor = texture(currTexture, eyeDirection);
    //fragmentColor = vec4(eyeDirection, 1.0);
}

这是我的顶点着色器:

#version 450

uniform mat4 projection;
uniform mat4 modelView;

in vec4 aPosition;

smooth out vec3 eyeDirection;

void main() {
    mat3 inverseModelView = inverse(mat3(modelView));
    vec3 unprojected = (inverse(projection) * aPosition).xyz;
    eyeDirection = inverseModelView * unprojected;
    // eyeDirection = aPosition.xyz;

    //gl_Position = aPosition.xyww;
    gl_Position = new vec4(aPosition.x, aPosition.y, 1.0, aPosition.w );
} 

这里是我初始化纹理的地方:

// initializes all the necessary texture values
void TrainView::initTextures() {
    // loading in texture maps
    SDL_Surface* xPos = IMG_Load("SkyBoxXpos.png");
    SDL_Surface* xNeg = IMG_Load("SkyBoxXneg.png");
    SDL_Surface* yPos = IMG_Load("SkyBoxYpos.png");
    SDL_Surface* yNeg = IMG_Load("SkyBoxYneg.png");
    SDL_Surface* zPos = IMG_Load("SkyBoxZpos.png");
    SDL_Surface* zNeg = IMG_Load("SkyBoxZneg.png");

    if (!xPos) 
        printf("IMG_Load: %s\n", IMG_GetError());
    if (!xNeg) 
        printf("IMG_Load: %s\n", IMG_GetError());
    if (!yPos) 
        printf("IMG_Load: %s\n", IMG_GetError());
    if (!yNeg) 
        printf("IMG_Load: %s\n", IMG_GetError());
    if (!zPos) 
        printf("IMG_Load: %s\n", IMG_GetError());
    if (!zNeg) 
        printf("IMG_Load: %s\n", IMG_GetError());
        // handle error

    glGenTextures(1, &skyBoxTexture);
    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_CUBE_MAP);
    glBindTexture(GL_TEXTURE_CUBE_MAP, skyBoxTexture);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    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);

    // files are 24-bit bmp files
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, xPos->w, xPos->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, xPos->pixels);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, xNeg->w, xNeg->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, xNeg->pixels);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, yPos->w, yPos->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, yPos->pixels);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, yNeg->w, yNeg->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, yNeg->pixels);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, zPos->w, zPos->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, zPos->pixels);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, zNeg->w, zNeg->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, zNeg->pixels);

    glBindTexture(GL_TEXTURE_CUBE_MAP, NULL);

}

这是我尝试绘制/渲染天空盒的地方:

// handles everything for drawing the sky box
void TrainView::drawSkyBox(){

    glUseProgram(skyBoxShader);
    glActiveTexture(GL_TEXTURE0);

    glBindTexture(GL_TEXTURE_CUBE_MAP, skyBoxTexture);

    int loc = glGetUniformLocation(skyBoxShader, "modelView");

    GLfloat mvFl[16], projFl[16];

    glGetFloatv(GL_MODELVIEW_MATRIX, mvFl);

    glUniformMatrix4fv(loc, 1, GL_FALSE, mvFl);

    loc = glGetUniformLocation(skyBoxShader, "projection");

    glGetFloatv(GL_PROJECTION_MATRIX, projFl);
    glUniformMatrix4fv(loc, 1, GL_FALSE, projFl);

    loc = glGetUniformLocation(skyBoxTexture, "currTexture");
    glUniform1i(loc, 0);

    // not sure if this is necessary or done as intended by opengl
    GLuint sampler;
    glGenSamplers(1, &sampler);
    glBindSampler(0, sampler);

    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);

    glBegin(GL_QUADS);
        glVertex3f(-1.0, -1.0, 0.0);
        glVertex3f(1.0, -1.0, 0.0);
        glVertex3f(1.0, 1.0, 0.0);
        glVertex3f(-1.0, 1.0, 0.0);
    glEnd();

    glUseProgram(NULL);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
}

最佳答案

您正在为您的立方体纹理启用 mipmapped 采样:

glTexParameteri(GL_TEXTURE_CUBE_MAP,
                GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

但是,您并未为纹理创建 mipmap。在规范语言中,这意味着您的纹理不是“完整的 mipmap”,这反过来又使其不是“完整的纹理”。采样不完整纹理的结果是黑色

创建 mipmap 最简单的方法是调用 glGenerateMipmap()你的纹理数据被指定之后,即在所有的 glTexImage2D() 要求 6 个方面:

glGenerateMipmap(GL_TEXTURE_CUBE_MAP);

如果你不需要mipmaps,你可以简单地设置filter参数的值不使用mipmaps:

glTexParameteri(GL_TEXTURE_CUBE_MAP,
                GL_TEXTURE_MIN_FILTER, GL_LINEAR);

您尝试创建采样器对象的操作在这里无济于事。如果您想使用多个不同的采样属性相同的纹理进行采样,则采样器对象很有用。假设您想在同一着色器中使用 GL_LINEARGL_NEAREST 对同一纹理进行采样,您可以为此纹理创建两个采样器对象。我不认为这是一个非常常见的用例,但在某些情况下它会派上用场,而在引入采样器对象之前这是不可能做到的。

关于c++ - GLSL 纹理函数只为天空盒返回黑色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30021125/

相关文章:

c++ - 工厂方法中的访问冲突

java - JOGL 没有渲染任何东西

c++ - C std::lower_bound,使用重载运算符作为二进制谓词 comp?

c++ - sizeof 空结构在 C 中为 0,在 C++ 中为 1,为什么?

c++ - C++ 静态简单类型是否按顺序初始化?

.net - Visual Studio 数据库版 : What is causing "ModelException: At least one identifier expected."?

c++ - 大括号初始化列表中的对象创建顺序

opengl - 如何在 libgdx 中正确设置 FrameBuffer 的宽度和高度?

c++ - 如何使用 Opengl 库显示文本文件中的 3D 点

c++ - boost 库中的 Nelder-Mead 算法