OpenGL / GLSL: Render ke kubus peta?


13

Saya mencoba mencari cara merender adegan saya ke peta kubus. Saya sudah terjebak dalam hal ini sebentar dan berpikir saya akan meminta bantuan kalian. Saya baru mengenal OpenGL dan ini adalah pertama kalinya saya menggunakan FBO.

Saat ini saya memiliki contoh kerja menggunakan file bmp cubemap, dan tipe sampel samplerCube dalam shader fragmen dilampirkan ke GL_TEXTURE1. Saya tidak mengubah kode shader sama sekali. Saya hanya mengubah fakta bahwa saya tidak akan memanggil fungsi yang memuat file bmp cubemap dan mencoba menggunakan kode di bawah ini untuk merender ke cubemap.

Anda dapat melihat di bawah ini bahwa saya juga melampirkan tekstur lagi ke GL_TEXTURE1. Ini terjadi ketika saya mengatur seragam:

glUniform1i(getUniLoc(myProg, "Cubemap"), 1);

dapat mengaksesnya di fragmen shader saya via uniform samplerCube Cubemap.

Saya memanggil fungsi di bawah ini seperti ini:

cubeMapTexture = renderToCubeMap(150, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);

Sekarang, saya menyadari di loop gambar di bawah ini bahwa saya tidak mengubah arah tampilan untuk melihat ke bawah + x, -x, + y, -y, + z, -z axis. Saya benar-benar hanya ingin melihat sesuatu berfungsi terlebih dahulu sebelum mengimplementasikannya. Saya pikir saya setidaknya harus melihat sesuatu pada objek saya seperti kode sekarang.

Saya tidak melihat apa-apa, hanya hitam lurus. Saya telah membuat latar belakang saya tetap putih objeknya hitam. Saya telah menghapus pencahayaan, dan mewarnai hanya untuk mencicipi tekstur cubemap dan masih hitam.

Saya pikir masalahnya mungkin tipe format ketika mengatur tekstur saya yaitu GL_RGB8, GL_RGBA tapi saya juga sudah mencoba:

GL_RGBA, GL_RGBA GL_RGB, GL_RGB

Saya pikir ini akan menjadi standar karena kita membuat tekstur yang melekat pada framebuffer, tetapi saya telah melihat contoh berbeda yang menggunakan nilai enum yang berbeda.

Saya juga telah mencoba mengikat tekstur peta kubus di setiap panggilan undian yang ingin saya gunakan peta kubus:

glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapTexture);

Juga, saya tidak membuat buffer kedalaman untuk FBO yang saya lihat di sebagian besar contoh, karena saya hanya ingin buffer warna untuk peta kubus saya. Saya benar-benar menambahkan satu untuk melihat apakah itu masalahnya dan masih mendapatkan hasil yang sama. Aku bisa membayangkan itu ketika aku mencoba.

Setiap bantuan yang dapat mengarahkan saya ke arah yang benar akan dihargai.

GLuint renderToCubeMap(int size, GLenum InternalFormat, GLenum Format, GLenum Type)
    {

    // color cube map
    GLuint textureObject;
    int face;
    GLenum status;

    //glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE1);
    glGenTextures(1, &textureObject);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureObject);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    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);

    for (face = 0; face < 6; face++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, InternalFormat, size, size, 0, Format, Type, NULL);
    }

    // framebuffer object
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, textureObject, 0);

    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    printf("%d\"\n", status);
        printf("%d\n", GL_FRAMEBUFFER_COMPLETE);

    glViewport(0,0,size, size);

    for (face = 1; face < 6; face++) {

        drawSpheres();
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, textureObject, 0);

    }

     //Bind 0, which means render to back buffer, as a result, fb is unbound
       glBindFramebuffer(GL_FRAMEBUFFER, 0);

       return textureObject;
    }

Sudahkah Anda diuji untuk melihat bahwa drawSpheresfungsi Anda benar-benar menarik sesuatu yang terlihat? Apakah fungsi sebenarnya menggambar sesuatu? Apa yang terjadi jika Anda berubah drawSpheresuntuk menghapus framebuffer?
Nicol Bolas

Iya. Saya melakukan dua operan. Satu dalam kode di atas, sebenarnya 6 panggilan di atas. Lalu saya panggil drawSpheres saat merender ke framebuffer 0 dan itu muncul.
Joey Green

Juga, saya telah mengatur latar belakang saya menjadi putih. Bukankah warna putih setidaknya muncul di tekstur?
Joey Green

Apakah kode Anda berfungsi dengan baik untuk FBO normal? Cara saya memahaminya, peta kubus seharusnya hanya enam tekstur, dan Anda harus membuat masing-masing secara terpisah ..
Jari Komppa

Jawaban:


10

Yah, saya tidak dapat menjamin bahwa ini akan membantu Anda mengetahui apa yang terjadi. Anda hanya belum memposting informasi yang cukup tentang apa yang Anda lakukan untuk melacak kesalahan tertentu. Meskipun saya dapat memperbaiki satu hal dari Anda dengan sangat cepat:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, textureObject, 0);

...

for (face = 1; face < 6; face++) {
    drawSpheres();
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, textureObject, 0);
}

Ini hanya akan menelepon drawSpheres lima kali. Saya kira Anda ingin menyebutnya 6 kali.

Tapi saya bisa mengirim jawaban yang berfungsi. Perhatikan bahwa kode ini dirancang untuk berjalan di samping seri tutorial saya , jadi ini merujuk pada kode yang tidak ada. Tapi ini terutama hal-hal seperti membuat jerat dan sebagainya; tidak ada yang benar-benar penting.

Inilah poin-poin penting. Shader untuk objek bola utama.

Vertex shader:

#version 330

layout(std140) uniform;

layout(location = 0) in vec4 position;
layout(location = 2) in vec3 normal;

out vec3 modelSpaceNormal;

uniform Projection
{
    mat4 cameraToClipMatrix;
};

uniform mat4 modelToCameraMatrix;

void main()
{
    gl_Position = cameraToClipMatrix * (modelToCameraMatrix * position);
    modelSpaceNormal = normal;
}

Shader fragmen:

#version 330

in vec3 modelSpaceNormal;

uniform samplerCube cubeTexture;

out vec4 outputColor;

void main()
{
    outputColor = texture(cubeTexture, modelSpaceNormal);
//  outputColor = vec4(normalize(modelSpaceNormal), 1.0);
}

Penciptaan tekstur cubemap yang akan digunakan sebagai target render:

void CreateCubeTexture()
{
    glGenTextures(1, &g_cubeTexture);
    glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    std::vector<GLubyte> testData(CUBE_TEXTURE_SIZE * CUBE_TEXTURE_SIZE * 256, 128);
    std::vector<GLubyte> xData(CUBE_TEXTURE_SIZE * CUBE_TEXTURE_SIZE * 256, 255);

    for(int loop = 0; loop < 6; ++loop)
    {
        if(loop)
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + loop, 0, GL_RGBA8,
                CUBE_TEXTURE_SIZE, CUBE_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &testData[0]);
        }
        else
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + loop, 0, GL_RGBA8,
                CUBE_TEXTURE_SIZE, CUBE_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &xData[0]);
        }
    }

    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}

Saya benar-benar mengisi tekstur dengan data (daripada melewati NULL ke glTexImage2D) sebagai bantuan debugging. Ini memastikan bahwa semuanya berfungsi sebelum mulai menggunakan tekstur sebagai target render.

Juga, perhatikan bahwa saya memberikan BASE_LEVEL dan MAX_LEVEL. Saya selalu melakukannya dengan tekstur saya segera setelah penciptaan. Ini hanya kebiasaan yang baik, karena OpenGL terkadang pilih-pilih tentang kelengkapan tekstur dan piramida mipmap. Daripada mengingat aturan, saya hanya mengaturnya dengan nilai yang benar secara agama.

Inilah fungsi gambar utama:

void display()
{
    //Draw the cubemap.
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, g_framebuffer);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, g_depthbuffer);

    for(int loop = 0; loop < 6; ++loop)
        DrawFace(loop);

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

    //Draw the main scene.
    //The projection matrix is in a uniform buffer.
    ProjectionBlock projData;
    projData.cameraToClipMatrix = glm::perspective(90.0f,
        (g_viewportSize.x / (float)g_viewportSize.y), g_fzNear, g_fzFar);

    glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    glViewport(0, 0, (GLsizei)g_viewportSize.x, (GLsizei)g_viewportSize.y);

    glClearColor(0.75f, 0.75f, 1.0f, 1.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glutil::MatrixStack modelMatrix;
    modelMatrix.ApplyMatrix(g_viewPole.CalcMatrix());

    if(g_pSphere)
    {
        glutil::PushStack push(modelMatrix);

        glUseProgram(g_progMain.theProgram);
        glUniformMatrix4fv(g_progMain.modelToCameraMatrixUnif, 1, GL_FALSE,
            glm::value_ptr(modelMatrix.Top()));

        glActiveTexture(GL_TEXTURE0 + g_cubeTexUnit);
        glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

        g_pSphere->Render("lit");

        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

        glUseProgram(0);
    }

    glutPostRedisplay();
    glutSwapBuffers();
}

Ini mengacu pada DrawFace, yang menggambarkan wajah yang diberikan cubemap. Itu diimplementasikan sebagai berikut:

void DrawFace(int iFace)
{
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
        GL_TEXTURE_CUBE_MAP_POSITIVE_X + iFace, g_cubeTexture, 0);

    GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
    if(status != GL_FRAMEBUFFER_COMPLETE)
        printf("Status error: %08x\n", status);

    //The projection matrix is in a uniform buffer.
    ProjectionBlock projData;
    projData.cameraToClipMatrix = glm::perspective(90.0f, 1.0f, g_fzNear, g_fzFar);

    glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    glViewport(0, 0, (GLsizei)CUBE_TEXTURE_SIZE, (GLsizei)CUBE_TEXTURE_SIZE);

    const glm::vec4 &faceColor = g_faceColors[iFace];
    glClearColor(faceColor.x, faceColor.y, faceColor.z, faceColor.w);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if(g_pSphere)
    {
        glutil::MatrixStack modelMatrix;
        modelMatrix.Translate(g_faceSphereLocs[iFace]);

        glUseProgram(g_progUnlit.theProgram);
        glUniformMatrix4fv(g_progUnlit.modelToCameraMatrixUnif, 1, GL_FALSE,
            glm::value_ptr(modelMatrix.Top()));

        const glm::vec4 &sphereColor = g_faceSphereColors[iFace];
        glUniform4fv(g_progUnlit.objectColorUnif, 1, glm::value_ptr(sphereColor));

        glActiveTexture(GL_TEXTURE0 + g_cubeTexUnit);
        glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

        g_pSphere->Render("flat");

        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
        glUseProgram(0);
    }
}

Fungsi ini membuat referensi ke satu set tabel global yang saya gunakan untuk memberikan setiap wajah warna latar belakang yang berbeda, warna bola yang berbeda, dan untuk memposisikan bola (dalam ruang kamera) dengan benar untuk wajah itu.

Poin yang menonjol DrawFaceadalah ini.

Sebagai aturan umum, kecuali jika saya memiliki pengetahuan tertentu bahwa negara diatur, saya menetapkan negara itu. Saya mengatur viewport setiap kali saya menelepon DrawFace. Saya mengatur matriks proyeksi setiap kali. Itu berlebihan; Saya bisa mengaturnya kembali displaysebelum loop yang memanggil DrawFace, sama seperti yang saya lakukan dengan FBO dan kedalaman renderbuffer saat ini.

Tetapi saya juga menghapus buffer, yang berbeda untuk setiap wajah (karena setiap wajah memiliki warna yang berbeda).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.