简体   繁体   English

GLSL纹理函数仅向天空框返回黑色

[英]GLSL Texture Function Returning Only Black For Sky Box

I'm attempting to generate a sky box for my OpenGL scene by using GLSL to texture quads. 我正在尝试通过使用GLSL为四边形纹理来为OpenGL场景生成一个天空盒。 However, the sky box simply becomes black when I attempt to use the texture to generate the sky box color. 但是,当我尝试使用纹理生成天空盒颜色时,天空盒只是变成黑色。 The sky box works when I manually set the color, so I have basically narrowed the problem down to something being wrong with how I'm setting up the texture. 当我手动设置颜色时,天空盒可以工作,因此我基本上将问题缩小到我设置纹理的方式有问题。 I also messed around with a bunch of different eyeDirection vector values for the texture function, and I still get only a black square. 我还弄乱了纹理函数的一堆不同的eyeDirection矢量值,但仍然只得到一个黑色正方形。

Here is my Fragment Shader: 这是我的片段着色器:

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

Here is my vertex shader: 这是我的顶点着色器:

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

Here is where I initialize the texture: 这是我初始化纹理的地方:

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

}

Here is where I attempt to draw/render the sky box: 这是我尝试绘制/渲染天空盒的地方:

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

You are enabling mipmapped sampling for your cube texture here: 您将在此处为多维数据集纹理启用mipmapped采样:

glTexParameteri(GL_TEXTURE_CUBE_MAP,
                GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

However, you are not creating mipmaps for your texture. 但是,您没有为纹理创建mipmap。 In spec language, this means that your texture is not "mipmap complete", which in turn makes it not "texture complete". 在规范语言中,这意味着您的纹理不是“ mipmap完整的”,从而使它不是“纹理完整的”。 The result of sampling an incomplete texture is BLACK . 采样不完整纹理的结果为BLACK

The easiest way to create mipmaps is by calling glGenerateMipmap() after your texture data has been specified, ie after all the glTexImage2D() calls for the 6 sides: 创建glGenerateMipmap()的最简单方法是在指定纹理数据后,即在所有glTexImage2D()调用6面之后 ,调用glGenerateMipmap()

glGenerateMipmap(GL_TEXTURE_CUBE_MAP);

If you don't need mipmaps, you can simply set the value of the filter parameter to not use mipmaps: 如果不需要mipmap,则只需将filter参数的值设置为不使用mipmap:

glTexParameteri(GL_TEXTURE_CUBE_MAP,
                GL_TEXTURE_MIN_FILTER, GL_LINEAR);

What you attempted to do with creating a sampler object is not going to help here. 您尝试创建采样器对象所做的事情在这里无济于事。 Sampler objects are useful if you want to sample the same texture with multiple different sampling attributes . 如果要使用多个不同的采样属性采样 相同的纹理 ,则采样器对象很有用。 Say you wanted to sample the same texture with both GL_LINEAR and GL_NEAREST in the same shader, you could do that by creating two sampler objects for this texture. 假设您要在同一着色器中使用GL_LINEARGL_NEAREST对相同的纹理进行采样,则可以通过为此纹理创建两个采样器对象来实现。 I don't think it's a very common use case, but there are situations where it comes in handy, and it was impossible to do before sampler objects were introduced. 我认为这不是一个非常普遍的用例,但是在某些情况下它派上用场,并且在引入采样器对象之前是不可能做到的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM