【问题标题】:Layered rendering cubemap in one pass一次通过分层渲染立方体贴图
【发布时间】:2018-12-16 15:50:22
【问题描述】:

我正在尝试使用几何着色器和 gl_Layer 制作动态立方体贴图,其中每个面都有自己的纹理,但它不像预期的那样工作。或者我有一个什么都没有的黑色立方体贴图,或者我什么都没有......

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

void init(void) {
    //Triangle test
    GLfloat data[] = {
            0, 0, 0,
            1, 0, 0,
            0, 1, 0
    };

    glGenVertexArrays(1, &_vaoTriangles);
    glBindVertexArray(_vaoTriangles);
    glEnableVertexAttribArray(0);
    glGenBuffers(1, &_vboPoints);
    glBindBuffer(GL_ARRAY_BUFFER, _vboTriangles);
    glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0);
    glBindBuffer(GL_ARRAY_BUFFER ,0);
    glBindVertexArray(0);

    const GLfloat skybox[] = {
            // positions
            -1.0f,  1.0f, -1.0f,
            -1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,

            -1.0f, -1.0f,  1.0f,
            -1.0f, -1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f,  1.0f,
            -1.0f, -1.0f,  1.0f,

            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f,  1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,

            -1.0f, -1.0f,  1.0f,
            -1.0f,  1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f, -1.0f,  1.0f,
            -1.0f, -1.0f,  1.0f,

            -1.0f,  1.0f, -1.0f,
            1.0f,  1.0f, -1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            -1.0f,  1.0f,  1.0f,
            -1.0f,  1.0f, -1.0f,

            -1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f,  1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f,  1.0f,
            1.0f, -1.0f,  1.0f
    };

    glGenVertexArrays(1, &_vao);
    glBindVertexArray(_vao);
    glEnableVertexAttribArray(0);
    glGenBuffers(1, &_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(skybox), skybox, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0);
    glBindBuffer(GL_ARRAY_BUFFER ,0);
    glBindVertexArray(0);

    glGenTextures(1, &texture_cubemap);
    glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
    int face;
    for(face = 0; face < 6; face++)
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+face, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    glGenFramebuffers(1, &_fbo);
    glBindFramebuffer(1, _fbo);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_cubemap, 0);

//    glGenRenderbuffers(1, &_depthFbo);
//    glBindRenderbuffer(GL_RENDERBUFFER, _depthFbo);
//    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 256, 256);
//    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthFbo);

//    GLenum drawBuffers[1] = {GL_COLOR_ATTACHMENT0};
//    glDrawBuffers(1, drawBuffers);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

这里是渲染:

void render(void) {
    glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
    glViewport(0, 0, 256, 256);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.2, 0.2, 0.2, 0);
    glUseProgram(pIdTriangles);
    glBindVertexArray(_vaoTriangles);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);
    glUseProgram(0);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, width, height);
    glClearColor(0, 0, 0, 1.0);
    glUseProgram(pId);
//...Matrices stuff
    glBindVertexArray(_vao);
    gl4duSendMatrices();
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
    glUniform1i(glGetUniformLocation(pId, "skybox"), 0);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);
    glUseProgram(0);

我的天空盒着色器:

//Vertex shader
#version 330


layout(location=0) in vec3 positionSkybox;

uniform mat4 projectionMatrix;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
out vec3 UV;

void main() {
    vec4 pos = projectionMatrix * viewMatrix /* modelMatrix */* vec4(positionSkybox, 1);
    gl_Position = pos.xyww;
    UV = positionSkybox;
}

//Fragment shader
#version 330

//layout(location=0) in vec4 outColor;

out vec4 fragColor;
uniform samplerCube skybox;
in vec3 UV;

void main() {
    fragColor = texture(skybox, UV);
}

以及模型的着色器:

//Vertex shader
#version 330

layout(location=0) in vec3 positionTriangles;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

void main() {
    gl_Position = /*projectionMatrix */ /*viewMatrix */ modelMatrix * vec4(positionTriangles, 1);
}

//Geometry shader
#version 330

layout(triangles) in;
layout(triangle_strip, max_vertices=18) out;

uniform mat4 projectionMatrix;

out vec4 colors;
void main() {
    int i, layer;
    for(layer = 0; layer < 6; ++layer){
        gl_Layer = layer;
        for(i = 0; i < gl_in.length(); i++){
            gl_Position = /*projectionMatrix */ gl_in[0].gl_Position;
            colors = vec4(0, 1, 0, 1);
            EmitVertex();
        }
    }
    EndPrimitive();
}

//Fragment shader 
#version 330

out vec4 fragColor;

in vec4 colors;
void main() {
    fragColor = colors;//vec4(1, 0, 0, 1);
}

感谢您的帮助...

编辑: 我的天空盒仅在以下情况下工作:

    glBindFramebuffer(GL_FRAMEBUFFER, **0**);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, 256, 256);
    glClearColor(0.2, 0.2, 0.2, 0);
    glUseProgram(pIdTriangles);
    glBindVertexArray(_vaoTriangles);
//Draw the triangles

    glBindFramebuffer(GL_FRAMEBUFFER, **_fbo**);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, width, height);
    glClearColor(0, 1, 0, 1);
    glUseProgram(pId);
//Draw the skybox

但必须在默认帧缓冲区上渲染的是天弓,对吗?

【问题讨论】:

  • 对不起,它是 pIdTriangles ... pIdTriangles 是我绘制三角形并拥有顶点、几何和片段着色器的 pId。 pId 是天空盒。

标签: opengl glsl opengl-3 geometry-shader


【解决方案1】:

您必须为每层完成一个图元,在迭代层的循环中移动EndPrimitive()

此外,在您的代码中,三角形的第一个顶点被使用了三次,但第二个和第三个坐标被遗漏了。 将gl_in[0].gl_Position 更改为gl_in[i].gl_Position

要渲染立方体贴图的不同面,您需要为立方体贴图的每一面使用不同的视图矩阵。您必须“看”每个方向(右、左、前、后、上和下)。
投影矩阵必须是透视投影,视场角为 90 度,纵横比为 1.0: 另请参阅教程"OpenGL: One-pass rendering to a cube map",了解更多详细信息。

例如作者:usnig glm::lookAtglm::perspective

glm::mat4 cubeView[6] =
{ 
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec3(0.0f,-1.0f, 0.0f)), // +X
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f,-1.0f, 0.0f)), // -X
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)), // +Y
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f,-1.0f, 0.0f), glm::vec3(0.0f, 0.0f,-1.0f)), // -Y
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec3(0.0f,-1.0f, 0.0f)), // +Z
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 0.0f,-1.0f), glm::vec3(0.0f,-1.0f, 0.0f)), // -Z
};

glm::mat4 cubeProj = glm::perspective(glm::radians(90.0f), 1.0f, near_plane, far_plane);
uniform mat4 cubeProjMatrix;
uniform mat4 cubeViewMatrix[6];

void main() {
    int i, layer;
    for(layer = 0; layer < 6; ++layer){
        gl_Layer = layer;
        for(i = 0; i < gl_in.length(); i++)
        {
            gl_Position = cubeProjMatrix * cubeViewMatrix[layer] * gl_in[i].gl_Position;
            colors = vec4(0, 1, 0, 1);
            EmitVertex();
        }
        EndPrimitive(); // <---- insert 
    }
    //EndPrimitive();   // <---- delete
}

【讨论】:

  • 感谢您的回答。我照你说的做了,但没有任何改变。我的屏幕从帧缓冲区中的 glClearColor 变为全灰色,仅此而已...
  • 编辑:我启用了 GL_DEPTH_TEST 和 GL_CULL_FACE 但是当我评论时我得到了一个黑色立方体......为什么......?
  • 好的,但也没有任何改变,在绝望中,我切换了 fbo id(为天空盒绑定 fbo,为三角形绑定 0),我从几何着色器中获得了绿色,但没有三角形。
  • 我有一个三角形,但前提是我为他设置了一个视图和模型矩阵。而且它不是在立方体的每个面上......我想我做了一些奇怪的事情。编辑:我是否必须让 bindFramebuffer 绑定到天空盒的 fbo 和模型到 0?如果没有,我仍然会得到一个黑色立方体......我真的不明白为什么
  • 非常感谢,我试试看……不过最后一个问题,skybox我得在framebuffer中绑定到0,对吧?因为我看到的几个教程都是 0,在我的情况下,如果我将它绑定到 0,我只有一个黑色立方体......
猜你喜欢
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多