 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
arpaagent
Joined: 06 Sep 2007 Posts: 10
|
Posted: Mon Sep 17, 2007 1:50 pm Post subject: Help with filling stencil buffer |
|
|
ok, I am trying to draw to only a certain portion of the screen by using stencilling, but I think i am having trouble filling in the stencil data. From snooping around the forums, it seems like the framebuffer alpha channel and the stencil buffer are one in the same. Is this correct? So, for example, if i want to fill the stencil buffer with 0xff and then draw a polygon with stencil value 0x00 in the stencil buffer, could I do it like this?
| Code: |
sceGuClearStencil( 0xff );
sceGuClear( GU_STENCIL_BUFFER_BIT );
// this lets us draw to the alpha channel without affecting color channels
sceGuPixelMask( 0x00ffffff );
// this will give us 0 in the alpha channel
sceGuColor( 0x00000000 );
// draw polygons in the shape of desired stencil
sceGumDrawArray( ... );
|
and then later, I could use the stencil values i created with blending...like this?? So that anything with a stencil value of 0xff would pass but anything with stencil value of 0x00 would not get drawn.
| Code: |
sceGuEnable( GU_BLEND );
sceGuBlendFunc( GU_ADD, GU_DST_ALPHA, GU_ONE_MINUS_DST_ALPHA, 0, 0 );
// draw polygons that will get stencilled
sceGumDrawArray( ... );
|
I've been messing around with this for a while now and I just can't get it to work like I want it to.
Any insight would be greatly appreciated! thanks!! _________________ woo
Last edited by arpaagent on Tue Sep 18, 2007 12:57 am; edited 1 time in total |
|
| Back to top |
|
 |
Smong
Joined: 04 Sep 2007 Posts: 82
|
Posted: Mon Sep 17, 2007 9:35 pm Post subject: |
|
|
I can't seem to find where sceGuStencilClear is defined, I have r2309 of the psptoolchain from about 2 weeks ago. _________________ (+[__]%) |
|
| Back to top |
|
 |
arpaagent
Joined: 06 Sep 2007 Posts: 10
|
Posted: Tue Sep 18, 2007 12:56 am Post subject: |
|
|
sorry, i meant sceGuClearStencil( );
edited my post _________________ woo |
|
| Back to top |
|
 |
Smong
Joined: 04 Sep 2007 Posts: 82
|
Posted: Tue Sep 18, 2007 5:05 am Post subject: |
|
|
Edit: post completely rewritten with (partial?) solution.
After looking at the gu/reflection and playing around with some code I have come to these conclusions:
- You need to enclose the sceGumDrawArray that you want to be affected by stencilling with sceGuEnable(GU_STENCIL_TEST).
- You need to call sceGuStencilFunc and sceGuStencilOp twice, once before drawing your stencil, then again before you draw the things you want stencilled.
- sceGuPixelMask isn't necessary, but you must set it back to 0 if you do call it.
- The blend function should be done on SRC, not DST.
- The relevant code in the reflection sample is between lines 188 and 205
Here's my test function:
| Code: | struct Vertex
{
float x, y, z;
};
#define DO_VERT(vert, xx, yy, zz) \
(vert)->x = xx; \
(vert)->y = yy; \
(vert)->z = zz; \
vert++;
/*
when setting up gu:
sceGuClearStencil(0x00);
sceGuEnable(GU_STENCIL_TEST); // Stencil test (might want to move this to only enclose the things you want stencilled)
sceGuEnable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
at the start of your rendering loop (note last flag):
sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT | GU_STENCIL_BUFFER_BIT);
before drawing stuff you want stencilled:
Gfx_StencilRectangle(...)
some parts copied from reflection sample:
Copyright (c) 2005 Jesper Svennevid
Copyright (c) 2005 McZonk <mczonk@gmx.net>
*/
void Gfx_StencilRectangle(int x, int y, int w, int h)
{
struct Vertex *vdata = sceGuGetMemory(sizeof(struct Vertex) * 4);
struct Vertex *v = vdata;
sceGuStencilFunc(GU_ALWAYS, 1, 1); // always set 1 bit in 1 bit mask
sceGuStencilOp(GU_KEEP, GU_KEEP, GU_REPLACE); // keep value on failed test (fail and zfail) and replace
sceGuDepthMask(GU_TRUE);
// turn off alpha (0) so drawing doesn't actually effect the color buffer only the stencil buffer
// if you turn alpha on (>0) then it will be give the stencilled area a background color
sceGuColor(0x00000000);
// draw polygons in the shape of desired stencil
DO_VERT(v, x, y, 0);
DO_VERT(v, x + w, y, 0);
DO_VERT(v, x, y + h, 0);
DO_VERT(v, x + w, y + h, 0);
// disable GU_TEXTURE_2D since we aren't using GU_TEXTURE_* flag
sceGuDisable(GU_TEXTURE_2D);
sceGumDrawArray(GU_TRIANGLE_STRIP,
GU_VERTEX_32BITF | GU_TRANSFORM_3D,
4, 0, vdata);
sceGuEnable(GU_TEXTURE_2D);
sceGuStencilFunc(GU_EQUAL, 1, 1); // allow drawing where stencil is 1
sceGuStencilOp(GU_KEEP, GU_KEEP, GU_KEEP); // keep the stencil buffer unchanged
sceGuDepthMask(GU_FALSE);
} |
It doesn't work 100% I can see some artifacts (text from psplink showing through), probably because I'm also drawing textures with alpha which mess up the stencil buffer. _________________ (+[__]%)
Last edited by Smong on Wed Sep 19, 2007 4:36 am; edited 1 time in total |
|
| Back to top |
|
 |
arpaagent
Joined: 06 Sep 2007 Posts: 10
|
Posted: Tue Sep 18, 2007 11:07 am Post subject: Makes Sense |
|
|
Smong, thanks for the insight
I think it makes a little more sense to me now. The stencilFunc is not only used for testing against the stencil to mask where objects are drawn, but it is also used to put values into the stencil buffer, using the GU_ALWAYS flag. Also, would it be correct to say that in the first StencilOp, the the fail conditions will never occur since the previous call to the StencilFunc is GU_ALWAYS, implying that any drawing done will result in a pass value for stencil purposes? Just trying to get a better grasp on what exactly is going on.
I also did notice that some text from pspDebugScreenPrint was showing up when I was messing with it earlier, although I thought that would be resolved by making a call to sceGuClear( ...GU_STENCIL_BUFFER_BIT... ). I guess I will have to play with it some more.
Later this evening I will try to recode up what i was doing and see if that solves my problems. I will let you know how it goes.
Thanks again! _________________ woo |
|
| Back to top |
|
 |
Smong
Joined: 04 Sep 2007 Posts: 82
|
Posted: Wed Sep 19, 2007 4:39 am Post subject: Re: Makes Sense |
|
|
| arpaagent wrote: | | Also, would it be correct to say that in the first StencilOp, the the fail conditions will never occur since the previous call to the StencilFunc is GU_ALWAYS, implying that any drawing done will result in a pass value for stencil purposes? | After some quick testing it seems like that is the case. I tried changing the GU_KEEP's to GU_REPLACE, GU_INVERT and GU_ZERO in the first sceGuStencilOp call and it didn't seem to make any difference. _________________ (+[__]%) |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|