How to create a wireframe material? [SOLVED]

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

How to create a wireframe material? [SOLVED]

Post by oringe »

How can I create a simple wireframe material?

I'm looking for a simple solution. I just want to set the MaterialType to WIREFRAME and have the wireframe render the edges on top of an underlying texture layer, but the wireframe material is not transparent on the faces.

I'm sure there are a number of ways to do this, I just need to be pointed in the right direction.

Thanks, :D
Last edited by oringe on Sat Mar 23, 2013 7:52 pm, edited 1 time in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: How to create a wireframe material?

Post by hybrid »

Simples way is to enable the wireframe debug on the nodes you need this. If you want better quality, you have to render the node twice, second time with texture off, wireframe on, depth test to lesser-equal, and depth bias just slightly on. This will render the wireframe on top of the existing mesh, and avoid z-fighting in order to get whole wires.
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

Re: How to create a wireframe material?

Post by oringe »

Thanks hybrid. But I am a little confused because I'm a noob;
How do I turn the "texture off" ? node->setMaterialTexture (void) ?
And by "wireframe on" do you mean ->setMaterialFlag ( EMF_WIREFRAME )? of the same texture?
Also I couldn't find a depth test attribute, did you mean the SMaterial's ZBuffer attribute? which is ECFN_LESSEQUAL by default?
How do I change the "depth bias" ?

thnx again, :)
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

Re: How to create a wireframe material?

Post by oringe »

Here is one solution I figured out. It's not perfect, but it works. Please feel free to comment on your perceived strengths / weaknesses of this solution : )

I create a cube with my desired texture and another cube_w that is the wireframe. I render the scene, then turn the cube's visibility off, clear the zbuffer, and render again.
That's two renders per frame, but the second is only wireframes so it's fast.

Code: Select all

 
    cube->setMaterialTexture (0, driver->getTexture("./textures/gray.jpg"));
    cubew->setMaterialFlag (video::EMF_WIREFRAME, true);
    // ...
    driver->beginScene(true, true, video::SColor(255,200,200,200));
 
    cube->setVisible (true);
    smgr->drawAll();
 
    cube->setVisible (false);
    driver->clearZBuffer ();
    smgr->drawAll();
 
    driver->endScene();
 
Better solutions are welcome...
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: How to create a wireframe material?

Post by mongoose7 »

If you make cubew slightly larger than cube and don't clear the depth buffer, you will get a visible wireframe only on the fron surfaces. At the moment, you can see the wireframe through the cube.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: How to create a wireframe material?

Post by hybrid »

You can set the depth bias by setting PolygonOffsetFactor to, e.g., 1. This will render surfaces at a little shifted depth value, in order to make sure they are rendered on top of exactly aligned planes. So you don't have to change the cube's size.
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

Re: How to create a wireframe material?

Post by oringe »

@hybrid
I really appreciate your help, man, but I'm not finding this PolygonOffsetFactor. I did: grep PolygonOffset * in the irrlicht /include and /source folders. No matches. ?? :?
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

Re: How to create a wireframe material?

Post by oringe »

@mongoose7
Thanks for the scaled wireframe idea. I've seen that technique before in Blender, but I don't like the extra step of having to scale everything up the slightest bit. Plus for complex shapes you have to scale along the normals if you don't want wires disappearing under the mesh. Messy.
Last edited by oringe on Fri Jul 08, 2011 3:34 am, edited 1 time in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: How to create a wireframe material?

Post by hybrid »

Ok, sorry. This means that it will be added for Irrlicht 1.8, you can find that code in the SVN/trunk development version of Irrlicht.
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

Re: How to create a wireframe material?

Post by oringe »

Edit:
Here is a slightly simpler solution than my previous:
No need for two separate cubes. Just change the texture, wireframe flag and clear zBuffer between renders of the same node to achieve the wireframe effect:

Code: Select all

 
            node->setMaterialTexture( 0, driver->getTexture("./textures/sydney.bmp") );
            node->setMaterialFlag (video::EMF_WIREFRAME, false);
                smgr->drawAll();
 
            node->setMaterialTexture (0, driver->getTexture("./textures/white.jpg"));
            node->setMaterialFlag (video::EMF_WIREFRAME, true);
            driver->clearZBuffer ();
                smgr->drawAll();
 
@mongoose7
However, mongoose was right. Some wires are showing through on more complex meshes:
Image
:(
Anyone have any ideas how to prevent this, and get a clean wireframe??
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: How to create a wireframe material?

Post by hybrid »

Yes, don't clear the zbuffer. You need to cope with z-fighting, though. And then you need to scale the mesh along the normals, or use the depth bias.
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

Re: How to create a wireframe material?

Post by oringe »

@hybrid
Yes, thanks again for help! I'm currently looking into the new code in the SVN/trunk and trying to put something together.
Will edit this post once I know more...
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: How to create a wireframe material?

Post by mongoose7 »

You could also nudge the mesh towards the camera before rendering the wireframe.
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

Re: How to create a wireframe material?

Post by oringe »

EDIT: Jul 15, 14:03 = fixed a few things in the code, and simplified a little
@mongoose7
Incorporating hybrid's suggestion about the polygonOffsetFactor is quite complicated. Better to just wait until the next release, and then figure that one out.
In the meantime, here is my function to nudge the wireframe towards the camera prior to rendering.
It mostly works. I used an ugly magic constant of 0.1 for the nudge-vector length. I imagine with different sized meshes this number would have to be adjusted appropriately by some formula.
The wireframe looks alright, but there are a few wires dipping into the mesh and a few extending too far out.
This definitely feels ugly and messy, and doesn't satisfy my desire for a clean solution.
I'm waiting for the 1.8 release and hoping this polygonOffset will do the trick.
Any other ideas anyone?

Code: Select all

 
    vector3df nudge_vec (cam->getPosition() - wireframe_node->getPosition());
    nudge_vec.setLength (0.1);  // magic constant!
    wireframe_node->setPosition (wireframe_node->getPosition() + nudge_vec);
 
    smgr->drawAll();
 
    wireframe_node->setPosition (mesh_node->getPosition());  // back to original position
 
Last edited by oringe on Fri Jul 15, 2011 5:08 am, edited 2 times in total.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: How to create a wireframe material?

Post by mongoose7 »

You need

Code: Select all

vec = cam->getPosition() - node->getPosition();  <== points to the camera
vec.normalise();
vec *= 0.1f;
But why don't you have

Code: Select all

node1->setMesh(mesh);
node1->setPosition(v);
node2->setMesh(mesh);
node2->setPosition(v + vec);
node2->setMaterialFlag(video::EMF_WIREFRAME);   <== not sure about this
Post Reply