SOLVED Backface culling doesn't work from every camera angle

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

SOLVED Backface culling doesn't work from every camera angle

Post by pandoragami »

Hi all,

I guess the name of this thread doesn't fully explain the problem so here goes. The code posted works fine but if you move the camera around a green cube you'll notice that at one camera angle the backface culling doesn't cut the faces but if you move 180 degrees or so on the other side you will see parts of the cube begin to cull out of existence leaving only pieces of it till most or all of it is gone?

The question I have is how do I backface cull from every possible camera angle?

Another question (on a similar note) I have is can I use a single

Code: Select all

drawVertexPrimitiveList
call to draw multiple types of

Code: Select all

irr::video::SMaterial
. I notice I need to call

Code: Select all

cube_material.BackfaceCulling = true;
        cube_material.Wireframe = false;
        cube_material.EmissiveColor.set(0x00ff00);
        driver->setMaterial(cube_material);
before

Code: Select all

drawVertexPrimitiveList
but what if I want to draw a cube with six different colors; one for each face, would it be possible to make one call to it?


thanks here's the code.

Code: Select all

 
 
#include <irrlicht.h>
 
using namespace irr;
 
int main()
{
    IrrlichtDevice* device = 0;
 
    device = createDevice( video::EDT_OPENGL, core::dimension2d<u32>(640, 480));
 
    if (device == 0)
        return 1;
 
    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    gui::IGUIEnvironment* gui = device->getGUIEnvironment();
 
    //driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
    driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
 
    scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS( 0, 50.0f, 0.01f, -1, 0, 0, false, 0.0f, false, true);
    cam->setPosition(core::vector3df(0,0,0));
    cam->setTarget(core::vector3df(0,0,0));
    device->getCursorControl()->setVisible(false);
 
    irr::video::SMaterial cube_material;
 
    cube_material.BackfaceCulling = true;
    cube_material.Wireframe = false;
    cube_material.EmissiveColor.set(0x00ff00);
    driver->setMaterial(cube_material);
 
    driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());
 
    irr::u16 cube_i[24];
 
    for(int index = 0; index < 24; index++)
        cube_i[index] = index;
 
    int a, x, y, z;
    a = 1;
    x = y = z = 0;
 
    irr::video::S3DVertex cube_v[24];
            // bottom face
    cube_v[0].Pos.set(x, y, z);
    cube_v[1].Pos.set(a+x, y, z);
    cube_v[2].Pos.set(a+x ,y, a+z);
    cube_v[3].Pos.set(x, y, a+z);
            // top face
    cube_v[4].Pos.set(x, a+y, z);
    cube_v[5].Pos.set(a+x, a+y, z);
    cube_v[6].Pos.set(a+x, a+y, a+z);
    cube_v[7].Pos.set(x, a+y, a+z);
            // front face
    cube_v[8].Pos.set(x,y,z);
    cube_v[9].Pos.set(x, a+y, z);
    cube_v[10].Pos.set(a+x, a+y, z);
    cube_v[11].Pos.set(a+x, y, z);
            // back face
    cube_v[12].Pos.set(x, y, a+z);
    cube_v[13].Pos.set(x, a+y, a+z);
    cube_v[14].Pos.set(a+x, a+y, a+z);
    cube_v[15].Pos.set(a+x, y, a+z);
            // draw
    cube_v[16].Pos.set(x+a, y, z);//red 1
    cube_v[17].Pos.set(x+a, y, a+z);
    cube_v[18].Pos.set(a+x, a+y, a+z);
    cube_v[19].Pos.set(a+x, y + a, z);
            // right face
    cube_v[20].Pos.set(x,y,z);//red 0
    cube_v[21].Pos.set(x, y, a + z);
    cube_v[22].Pos.set(x, a+y, a+z);
    cube_v[23].Pos.set(x, a+y, z);
 
    while(device->run())
    if (device->isWindowActive())
    {
        driver->beginScene(true, true, video::SColor(255,0,0,0));
        smgr->drawAll();
 
        cube_material.BackfaceCulling = true;
        cube_material.Wireframe = false;
        cube_material.EmissiveColor.set(0x00ff00);
        driver->setMaterial(cube_material);
 
        driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());
        driver->drawVertexPrimitiveList(cube_v, 24, cube_i, 6, irr::video::EVT_STANDARD, irr::scene::EPT_QUADS, irr::video::EIT_16BIT);
 
        driver->endScene();
        device->sleep(50);
    }
 
    device->drop();
 
    return 0;
}
 
 
 
Last edited by pandoragami on Sun Nov 09, 2014 8:04 am, edited 1 time in total.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Backface culling doesn't work from every camera angle?

Post by mongoose7 »

When setting the position of the cube vertices, you can also set their colour. Your problem is hardly likely to be backface culling. Maybe you could post a screenshot.

Backface culling means not rendering triangles which face away from the camera. So I guess you can see these triangles? A bit tricky for cube, so I guess, therefore, that some front faces are not being rendered. So your problem is winding - the order that you specify the vertices. So change the order and see how you go.

(GPUs only render triangles. They don't render "cubes" so they have no idea what the back and front of your cube are. The GPU just sees 12 triangles to be rendered.)
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: Backface culling doesn't work from every camera angle?

Post by pandoragami »

mongoose7 wrote:When setting the position of the cube vertices, you can also set their colour.
Would it be something like

Code: Select all

cube_v[0].Col.set(a,r,g,b)
?
mongoose7 wrote:Your problem is hardly likely to be backface culling. Maybe you could post a screenshot.
Here's the back of the cube
Image
This is the front of the cube
Image
mongoose7 wrote: Backface culling means not rendering triangles which face away from the camera. So I guess you can see these triangles? A bit tricky for cube, so I guess, therefore, that some front faces are not being rendered. So your problem is winding - the order that you specify the vertices. So change the order and see how you go.
(GPUs only render triangles. They don't render "cubes" so they have no idea what the back and front of your cube are. The GPU just sees 12 triangles to be rendered.)
Ok, the indices are declared just by doing a for loop

Code: Select all

for(int index = 0; index < 24; index++)
        cube_i[index] = index;

I'm guessing that would be wrong. My guess is the ordering would need to be reshuffled where the backs of the polygons are always either facing in or out of the cube.

I checked this tutorial for OpenGL rendering a cube http://en.wikibooks.org/wiki/OpenGL_Pro ... utorial_05

Would this be the solution for setting the indices? I'll try it anyways, but let me know if I'm wrong.

Code: Select all

GLushort cube_elements[] = {
    // front
    0, 1, 2,
    2, 3, 0,
    // top
    3, 2, 6,
    6, 7, 3,
    // back
    7, 6, 5,
    5, 4, 7,
    // bottom
    4, 5, 1,
    1, 0, 4,
    // left
    4, 0, 3,
    3, 7, 4,
    // right
    1, 5, 6,
    6, 2, 1,
  };
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: Backface culling doesn't work from every camera angle?

Post by pandoragami »

I tried using the tutorial here to make the cube, works now
http://irrlicht.sourceforge.net/tut_toka.html

here's the code for sake of reference,

Code: Select all

#include <irrlicht.h>
 
using namespace irr;
 
int main()
{
    IrrlichtDevice* device = 0;
 
    device = createDevice( video::EDT_OPENGL, core::dimension2d<u32>(640, 480));
 
    if (device == 0)
        return 1;
 
    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
 
    scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS( 0, 50.0f, 0.01f, -1, 0, 0, false, 0.0f, false, true);
    cam->setPosition(core::vector3df(0,0,0));
    cam->setTarget(core::vector3df(0,0,0));
    device->getCursorControl()->setVisible(false);
 
    irr::video::SMaterial cube_material;
 
    cube_material.BackfaceCulling = true;
    cube_material.Wireframe = false;
    cube_material.Lighting = false;
    cube_material.EmissiveColor.set(0x000000);
    driver->setMaterial(cube_material); 
    driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());
 
    irr::video::S3DVertex Vertices[8]; 
    irr::u16 indices[] =
    {0,1,2,
      0,2,3,
      1,6,2,
      1,5,6,
      0,5,1,
      0,4,5,
      0,3,7,
      0,7,4,
      2,7,3,
      2,6,7,
      4,6,5,
      4,7,6 };
 
    int CUBEX = 5.0;
    int CUBEY = 5.0;
    int CUBEZ = 5.0;
 
 
    Vertices[0] = irr::video::S3DVertex    (
                -CUBEX/2,-CUBEY / 2,-CUBEZ/2, 1,1,0,
                irr::video::SColor(255,0,255,0), 0, 1);
 
 Vertices[1] = irr::video::S3DVertex(
               CUBEX/2,-CUBEY / 2,-CUBEZ/2, 1,0,0,
               irr::video::SColor(255,0,0,255), 1, 1);
 
 Vertices[2] = irr::video::S3DVertex(
               CUBEX/2,-CUBEY / 2, CUBEZ/2, 0,1,1,
               irr::video::SColor(255,255,0,0), 1, 0);
 
 Vertices[3] = irr::video::S3DVertex(
               -CUBEX/2,-CUBEY / 2, CUBEZ/2, 0,0,1,
               irr::video::SColor(255,255,255,0), 0, 0);
 
 Vertices[4] = irr::video::S3DVertex(
               -CUBEX/2, CUBEY / 2,-CUBEZ/2, 0,0,1,
               irr::video::SColor(255,0,255,255), 0, 0);
 
 Vertices[5] = irr::video::S3DVertex(
               CUBEX/2, CUBEY / 2,-CUBEZ/2, 0,0,1,
               irr::video::SColor(255,255,0,255), 0, 0);
 
 Vertices[6] = irr::video::S3DVertex(
               CUBEX/2, CUBEY / 2, CUBEZ/2, 0,0,1,
               irr::video::SColor(255,0,0,0), 0, 0);
 
 Vertices[7] = irr::video::S3DVertex(
               -CUBEX/2, CUBEY / 2, CUBEZ/2, 0,0,1,
               irr::video::SColor(255,255,255,255), 0, 0);
 
    while(device->run())
    if (device->isWindowActive())
    {
        driver->beginScene(true, true, video::SColor(255,255,255,255));
        smgr->drawAll();
 
        cube_material.BackfaceCulling = true;
        cube_material.Wireframe = false;
        cube_material.Lighting = false;
        driver->setMaterial(cube_material);
        driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());
        driver->drawVertexPrimitiveList( &Vertices, 8, &indices, 12, irr::video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
 
        driver->endScene();
        device->sleep(50);
    }
 
    device->drop();
 
    return 0;
}
 
Post Reply