简体   繁体   中英

C/C++ OpenGL Occlusion Culling

I'm trying out raw OpenGL, so I decided to code very, very simple game based on 3d blocks, something a'la retarded Minecraft game, just to improve my skills.

Last problems I've met with were cullings. I've finally figured out how to make Frustum Culling and Backface Culling, and they both work well, but unfortunatelly I have no idea how to code Occlusion Culling to not display boxes that are covered by other boxes that are closer to player.

Just for test in main draw loop I'm looping through all boxes, later I'll change it to a more efficient way, now this is how the code looks like:

for( std::map< std::string, Cube* >::iterator it = Cube::cubesMap.begin( ); it !=  Cube::cubesMap.end( ); it++ )
{
    cube = ( *it ).second;

    if( !cube )
        continue;

    (...)

    if( Camera::cubeInFrustum( cube->position.x, cube->position.y, cube->position.z, 0.5f ) && cube->isInRoundDistance( 80 ) )
        cube->draw( );
}

And Cube::Draw:

void Cube::draw( )
{
    glPushMatrix( );
    glTranslatef( position.x, position.y, position.z );

    if( showSide1 == false && showSide2 == false && showSide3 == false && showSide4 == false && showSide5 == false && showSide6 == false )
    {
        glPopMatrix( );
        return;
    }

    GLfloat cube[] = 
    {
        -0.5f, -0.5f,  0.5f,// Front face
         0.5f, -0.5f,  0.5f,
        -0.5f,  0.5f,  0.5f,
         0.5f,  0.5f,  0.5f,
        -0.5f, -0.5f, -0.5f,// Back face
        -0.5f,  0.5f, -0.5f,
         0.5f, -0.5f, -0.5f,
         0.5f,  0.5f, -0.5f,
        -0.5f, -0.5f,  0.5f,// Left face
        -0.5f,  0.5f,  0.5f,
        -0.5f, -0.5f, -0.5f,
        -0.5f,  0.5f, -0.5f,
         0.5f, -0.5f, -0.5f,// Right face
         0.5f,  0.5f, -0.5f,
         0.5f, -0.5f,  0.5f,
         0.5f,  0.5f,  0.5f,
        -0.5f,  0.5f,  0.5f,// Top face
         0.5f,  0.5f,  0.5f,
        -0.5f,  0.5f, -0.5f,
         0.5f,  0.5f, -0.5f,
        -0.5f, -0.5f,  0.5f,// Bottom face
        -0.5f, -0.5f, -0.5f,
         0.5f, -0.5f,  0.5f,
         0.5f, -0.5f, -0.5f 
    };

    float textures[] =
    {
        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 

        0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 

        0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 

        0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 

        0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 

        0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f
    };

    //ss << position.x + 2 << ", " << position.y << ", " << position.z << std::endl;

    glVertexPointer(3, GL_FLOAT, 0, cube);
    glTexCoordPointer(2, GL_FLOAT, 0, textures);

    if( showSide1 || showSide2 || showSide3 || showSide4 )
        glBindTexture(GL_TEXTURE_2D, imageSides->texture);

    if( showSide1 )
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    if( showSide2 )
        glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);

    if( showSide3 )
        glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);

    if( showSide4 )
        glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);

    if( showSide5 )
    {
        glBindTexture(GL_TEXTURE_2D, imageUp->texture);
        glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
    }

    if( showSide6 )
    {
        glBindTexture(GL_TEXTURE_2D, imageDown->texture);
        glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
    }

    glPopMatrix( );
}

I'm pretty sure it's inefficient, as I said earlier, this code will be optimized soon. Now I'm trying to make it working. The bool variables showSide are made for detection, if there is box with other box next to it, the sides between them won't be drawn.

I've been looking and googling how to make the occlusion culling, but I failed, there are only laconic informations or theory.

My question is, could anyone help me how to not draw covered blocks? I heard there is GLEW which I've compiled and injected, it has two following lines: glBeginQuery(GL_SAMPLES_PASSED_ARB, query); glEndQuery(GL_SAMPLES_PASSED);

Apparently Query is helpful to solve my problem, but I unsuccessfully tried to use it with Google on many ways, firstly no cubes were drawn, secondly game was drawn as earlier, covered cubes also.

Generally, you shouldn't expect a graphical API to do the work for you - its job is rendering, and your job is making sure it has as little to render as possible.

I recommend reading this blog: http://www.sea-of-memes.com/summary/blog_parts.html

It is about someone developing a minecraft-ish engine from scratch, and goes over everything from occlusion to lighting to transparency. In fact, the very first part should answer your question pretty well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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