OpenGL / GLSL: Küp haritasına gönderilsin mi?


13

Sahnemi bir küp haritasına nasıl dönüştüreceğimizi anlamaya çalışıyorum. Bu konuda biraz takılı kaldım ve sizden biraz yardım isteyebileceğimi düşündüm. OpenGL'de yeniyim ve ilk kez FBO kullanıyorum.

Şu anda bir cubemap bmp dosyası kullanarak çalışan bir örnek var ve parça gölgelendirici samplerCube örnek türü GL_TEXTURE1 eklenir. Gölgelendirici kodunu hiç değiştirmiyorum. Ben sadece cubemap bmp dosyasını yükleme ve bir cubemap render için aşağıdaki kodu kullanmaya çalışıyorum olmayacak aslında değiştiriyorum.

Aşağıda, dokuyu tekrar GL_TEXTURE1'e eklediğimi görebilirsiniz. Üniformayı ayarladığımda şöyle olur:

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

üzerinden parça gölgelendiricimden erişebilir uniform samplerCube Cubemap.

Aşağıdaki işlevi böyle çağırıyorum:

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

Şimdi, aşağıdaki çizim döngüsünde + x, -x, + y, -y, + z, -z eksenini aşağıya bakmak için görünüm yönünü değiştirmediğimi anlıyorum. Gerçekten bunu uygulamadan önce ilk önce çalışan bir şey görmek istiyordum. Kod en azından benim nesne üzerinde bir şey görmek gerektiğini düşündüm.

Hiçbir şey görmüyorum, sadece düz siyah. Arka planımı beyaz yaptım, nesne siyah. Sadece kübemap dokusunu örneklemek için aydınlatmayı ve renklendirmeyi kaldırdım ve hala siyahım.

Ben GL_RGB8, GL_RGBA olan benim doku ayarlarken sorun biçim türleri olabilir düşünüyorum ama ben de denedim:

GL_RGBA, GL_RGBA GL_RGB, GL_RGB

Bir çerçeve arabelleğe eklenen bir dokuya render yaptığımız için bunun standart olacağını düşündüm, ancak farklı enum değerleri kullanan farklı örnekler gördüm.

Ayrıca, küp haritasını kullanmak istediğim her çizim çağrısında küp haritası dokusunu ciltlemeyi denedim:

glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapTexture);

Ayrıca, çoğu örnekte gördüğüm FBO için bir derinlik tamponu oluşturmuyorum, çünkü sadece küp haritam için renk tamponunu istiyorum. Aslında sorunun bunun olup olmadığını görmek için bir tane ekledim ve hala aynı sonuçları aldım. Denediğimde bunu geçiştirebilirdim.

Beni doğru yönde gösterebilecek herhangi bir yardım takdir edilecektir.

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

drawSpheresİşlevinizin gerçekten görünür bir şey çizdiğini test ettiniz mi? İşlev aslında bir şey çiziyor mu? drawSpheresYalnızca çerçeveyi temizlemeyi değiştirirseniz ne olur ?
Nicol Bolas

Evet. İki geçiş yapıyorum. Yukarıdaki kodlardan biri, aslında yukarıdaki 6 çağrı. O zaman framebuffer 0 için render yaparken drawSpheres çağırıyorum ve ortaya çıkıyor.
Joey Green

Ayrıca, arka planımı beyaza ayarladım. Beyaz renk en azından dokuda görünmez mi?
Joey Green

Kodunuz normal bir FBO için iyi çalışıyor mu? Anladığım kadarıyla, bir küp haritası sadece altı doku olmalı ve her birini ayrı ayrı işlemek zorundasınız ..
Jari Komppa

Yanıtlar:


10

Bunun neler olduğunu anlamanıza yardımcı olacağını garanti edemem. Belirli hataları takip etmek için ne yaptığınız hakkında yeterli bilgi göndermediniz. Senin bir şeyi gerçekten çabuk düzeltebilmeme rağmen:

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

Bu sadece drawSpheres beş kez arayacaktır . Sanırım 6 kez aramak istedin.

Ama çalışan bir cevap gönderebilirim . Bu kodun öğretici serilerimle birlikte çalışacak şekilde tasarlandığını unutmayın, bu nedenle mevcut olmayan koda başvuruyor. Ama bu esas olarak kafesler oluşturmak gibi şeyler; gerçekten önemli bir şey yok.

İşte göze çarpan noktalar. Ana küre nesnesi için gölgelendiriciler.

Tepe noktası gölgelendiricisi:

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

Parça gölgelendirici:

#version 330

in vec3 modelSpaceNormal;

uniform samplerCube cubeTexture;

out vec4 outputColor;

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

Oluşturma hedefi olarak kullanılacak kübapap dokusunun oluşturulması:

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

Aslında doku (bir hata ayıklama yardımcısı olarak NULL geçirerek yerine glTexImage2D yerine) veri doldurun. Dokuyu bir render hedefi olarak kullanmaya başlamadan önce her şeyin çalışmasını sağlar.

Ayrıca, bir BASE_LEVEL ve MAX_LEVEL sağladığımı unutmayın. Bunu yaratımdan hemen sonra her zaman dokularımla yaparım. Bu sadece iyi bir alışkanlıktır, çünkü OpenGL bazen doku bütünlüğü ve mipmap piramidi hakkında seçici olabilir. Kuralları hatırlamak yerine, onları dini olarak doğru değerlere ayarladım.

İşte ana çizim fonksiyonu:

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

Bu DrawFace, cubemap'in verilen yüzünü çizen referansı yapar . Bu aşağıdaki gibi uygulanır:

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

Bu işlev, her yüze ayrı bir arka plan rengi, ayrı bir küre rengi vermek ve küreyi (kamera alanında) bu yüz için düzgün bir şekilde konumlandırmak için kullandığım bir dizi genel tabloya başvurur.

Dikkat çeken noktalar DrawFacebunlar.

Genel bir kural olarak , devletin belirlendiğine dair kesin bilgim yoksa, bu durumu ben belirledim. Her aradığımda görünümü ayarlıyorum DrawFace. Projeksiyon matrisini her seferinde ayarladım. Bunlar gereksiz; Şu anki FBO ve derinlik oluşturucu ile yaptığım gibi display, çağıran döngüden önce onları tekrar ayarlayabilirdim DrawFace.

Ama aynı zamanda her yüz için farklı olan tamponları temizlerim (çünkü her yüz farklı bir renge sahiptir).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.