Sign in to follow this  
QuadMV

How to overwrite something after its already drawn

Recommended Posts

Hey all, I don’t think this is possible, but wanted to see what everyone else thought? I have a few areas where I want to do something similar, but I’ll give one example for now since it should work (or not) in all cases. This is all one frame: Let’s assume I draw a wall (a simple poly with two triangles) right in front of the player. Next I want to make an opening in the wall a hole, maybe by design, maybe it was broken, whatever Is there a tricky way to do this? I really don’t want to have to split the wall into a lot of triangles in order to get the hole. I was hoping there is a trick with the z buffer or stencil buffer or shaders, to somehow draw a wall ( w/ 2 tris) but exclude a particular shape (any shape) out of it so I see what’s through it? Any ideas, or do I need to do this in the triangles? If I’ve been too vague in my questioning just say so and I’ll try to elaborate more. Thanks. Quad

Share this post


Link to post
Share on other sites
Hi there QuadMV,
How are you doing?

The Problem
"Making holes in walls"

The Solution
Here are a few options, generally you wouldn't make holes in walls but if you need it for a map or so it might be better to use a mesh. if not you can also modify the vertices in the vertex buffer and just check for vertices in a range and remove them and weld the other vertices to form a wall. I don't think you might be able to do it with stencilling, I will have to check for you... but right now I have to run to class...


Take care buddy, I hope some of this information was informative, I will check when I get back. Cheerio.

Share this post


Link to post
Share on other sites
There's at least 2 ways I can think of to do that:

1. with a texture with an alpha channel, just make the part you want have a 0 alpha value and use alpha blending.

2. This one has various sub-points :D
2.1. Enable stencil write and make it set the stencil values to 1
2.2. Draw the geometry you want as the hole (the square you were talking about)
2.3. Disable stencil writes
2.4. Enable stencil tests to pass only with stencil values of 0
2.5. Draw your wall

If you don't know how to use the stencil buffer or don't know how it works, a quick [google] search on "stencil buffers" will give you some clues.

[edit] Point enumeration corrected (just learned that after 2.4 is 2.5 and not 2.4 again [grin])
[edit2] Corrected urls

[Edited by - Kamikaze15 on August 31, 2005 4:42:36 PM]

Share this post


Link to post
Share on other sites
Thanks everyone.

Fruny, although the simplest idea, I don't think it's quite that simple. Unless all the triangles being drawn are presorted manually, I can't assume what will be drawn or when. Therefore, something I want behind the wall would possibly appear in front of the wall. I still need the depth buffer to ensure things that should be occluded are.

Kamikaze15, I think you’re describing what I want. I’ll have to play with the stencil buffer a bit to understand how to use it better.

In this day and age, is the stencil buffer still a good tool to use, or are there other ramifications that make it bad? Will I take much of a performance hit for this vs the other option of making my hole a full 3d model?

Thanks to all


Share this post


Link to post
Share on other sites
Nice, That's what I want exactly.

In a nutshell, this is what I've extracted from that DOC:


First step - Generate the outline of the hole
=============================================
glEnable(GL_STENCIL_TEST) = Enable Stencil Bufffer Testing
glColorMask(0, 0, 0, 0) = Disable rendering to the frame buffer
glStencilFunc(GL_ALWAYS, 1, 1) = Allow all pixels to pass the test
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE) = Replace the current value with the new one
glDepthMask(GL_FALSE) = Disable depth buffer writing


Second step - Draw the objects, using the stencil buffer to mask out the shape of the hole
==========================================================================================
glColorMask(1, 1, 1, 1) = Re-Enable writes to the frame buffer
glDepthMask(GL_TRUE) = Re-Enable depth buffer writes
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP) = Keep the current stencil buffer values (don't replace or overwrite)
glStencilFunc(GL_ALWAYS, 1, 1) = Allow all pixels to pass the test
glStencilFunc(GL_NOTEQUAL, 1, 1) = Only render where the value is not equal 1 (render around the mask)




Do we have a directx stencil buffer expert that can easily convert all the commands above into their directx equivalent? It would save me a lot of time and I’d really appreciate it.

Thanks

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Normally, a wall is three dimensional, and so the outline of the hole would be dependent on the viewing angle. In which case you'd need to design the geometry appropriately.

Share this post


Link to post
Share on other sites
By tweaking kamikaze's first method, it can work. Use alphatest, not really sure how to use it though, but thats what you can use. But heres what you need to do for the second method
///////////////////////////////////////////////////////////////
// First step- generate the outline of the hole.
///////////////////////////////////////////////////////////////
//enable stencil buffer
Device->SetRenderState(D3DRS_STENCILENABLE, true);
//Disable write to back and z buffer
Device->SetRenderState(D3DRS_ZWRITEENABLE, false);
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
//Allow all pixels to pass the test
Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
//Set the reference value to 1, and not mask any values
Device->SetRenderState(D3DRS_STENCILREF, 0x1);
Device->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
Device->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
//Replace the the passing pixels with the stencil ref (0x1) and keep if z-buffer fails
Device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);

///////////////////////////////////////////////////////////////
//Render the hole
///////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////
//Second step - Draw the objects without the hole in the middle
///////////////////////////////////////////////////////////////
//Re-enable writes to z and back buffer
Device->SetRenderState(D3DRS_ZWRITEENABLE, true);
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
//Keep the current stencil values
Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
//Render where the stencil buffer doesn't equal the stencil ref(0x1)
Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_NOTEQUAL);

///////////////////////////////////////////////////////////////
//Render the wall
///////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////
//Third step - Reset everything back to normal
///////////////////////////////////////////////////////////////
//Disable stencil test
Device->SetRenderState(D3DRS_STENCILENABLE, false);

But make sure that when you clear the device, make sure you clear the stencil buffer like this:
Device->Clear(0,0,
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | /* and the most important:*/ D3DCLEAR_STENCIL,
0xff000000/*clear to your color...*/,
1.0f/*z-buffer*/,
0/*and your favorite, stencil buffer*/);

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this