Sprite Masking

Started by
14 comments, last by marshdabeachy 17 years, 11 months ago
You can mask using the stencil buffer. (It does seem a little strange to go through all this trouble to "fake" 3D on hardware that excels in doing realtime 3D, but I guess it's a requirement for the class.)
Advertisement
The 4 (tu,tv) pairs go into the vertices that you use to draw your quads. (Making your quad out of 2 triangles, you will need 6 vertices but 2 of them are repeated. There is lots of information on this available.) So your vertex structure might have an X, Y, Z, TU, and TV for each vertex. Then when you render those 6 vertices as a triangle strip (or triangle list) DirectX will reference your TU and TV to decide how to texture the quad.

The sprite interface is designed to automate most of this process (drawing 2D textured quads) but it doesn't do anything special that you can't do "by hand". Just look up how to render a textured quad and then feed the vertices the TU and TV that you calculated. (Your screen position for the quad will be determined by what you put in .X, .Y, and .Z, although .Z might not be relevent if you're using screen coordinates.) Then DrawPrimitive will stretch your pixels to make them fit inside your quad, even if the quad is distorted in some way.

Don't get caught up too much in the '2d vs 3d' stuff, because all 3d hardware does is draw textured quads very fast. Usually those quads are arranged to give a 3d appearance but you can use them however you please and still get excellent performance. Also, I dont think the stencil buffer is useful here (correct me if I'm wrong) because he's trying to 'mask' the image SOURCE and not the image DESTINATION. It might be a terminology issue? I think it's more of an 'extract' operation or something than a masking operation.
Destination would be easier, but theoretically it could be done both ways. Look, here's a physical working example of what I'm trying to do:

http://flash.isnan.net/index.php?height=400&width=550&bg=FFFFFF&url=masking.swf&name=Masking%20Example

Just wait for it to load, it's like 500 kb. Move with the arrow keys. Turn the mask on and off with Enter.

That's ALL I'm trying to do. I looked up stencil buffers and it looks like overkill, if it's even applicable in the first place. There's no way to do this with the sprite interface? I have to access the individual verticies?

[Edited by - marshdabeachy on May 7, 2006 2:14:38 PM]
The sprite interface just automates the task of making a simple sprite, but since your task isn't particularly simple you might have to do it by hand. You seriously don't have to write any new code. Even the most basic samples will show you how to draw 2 textured triangles with 6 vertices to make a quad. Copy and paste, and insert your special code to calculate the TU and TVs! You want to understand what's going on and not just use a 'black box' sprite interface and pray it works for you anyways.

This is absolutely the way to do what your samples wants. I don't know how much more help people can give you because you're trying to do the same thing that EVERY beginner does, draw some triangles!! You may be caught up in the differences between 2D and 3D APIs, there's no (easy) way to do certain things in 3D that are trivially easy in 2D. You're not working with pixels anymore, you're working with vertices/vertex buffers, textures, and DrawPrimitive. There's just no way around that fact... when I got started I couldn't believe that there was no easy way to just 'draw' a background to the screen from a basic bitmap, but it's true. Any workarounds that involve pixel processing, etc. are waaay too slow for normal use; you've just got to use the pipeline and even though it is actually more complicated for certain simple 2D tasks, the benefits of scaling, rotation, translucency, etc. more than make up for it.

To make a DX program similar to that Flash sample you posted, you would just have 4/6 vertices that sit in the middle of the screen and never move. Every time the point of view changes/rotates, you update the texture coordinates. That's all there is to it.
Just a few more thoughts, sorry if it's too much to swallow all at once:

I still think terminology here is the issue. You're asking people how to NOT DRAW a part of your texture onto a quad. The question you could be asking instead is how TO DRAW a specific part of a texture onto a quad. It's significantly different than the 2D approach.

I understand if you're trying to do this the 'hard way' for a programming project or whatever, but the 'right way' is to have ONE quad be your ground. Set the vertices up in the XZ plane (or whatever) and then just move/rotate the camera matrix (or the transformation matrix if you prefer) and render. It will look better and it's trivially easy -- you don't even need texture coordinates. Just draw the entire ground every frame on a quad from like (-100,0,-100) to (100,0,100) or something. Much faster, easier, and allows the GPU to do the work that you're doing by hand.

Your comment
Quote:'It's not possible to do it in one go, because behind each mask the image is a different size. The lower on the screen the mask is, the larger the image it's masking is. If you did it all on one go, you'd be looking at a flat map.'
doesn't make sense. You're just trying to draw a perspective-correct ground. The only reason it would look flat would be if the camera was up high and looking straight down (perpendicular). If the camera is low and looking straight ahead (parallel to the ground) the ground will be drawn with the texture converging to a vanishing point/horizon the way Mario Kart does. Plus you get the massive benefit of essentially getting infinite little 'masking rectangles' because the GPU is designed to draw textures in perspective, and it can do it far more efficiently than you can, and most importantly, in parallel with your engine.

Basically I am saying that if you get it to work your way you will just be approximating the results obtained from the '3D' way. Good luck however you approach it, be sure to post some screenshots. Note that you can still have 2D sprites for all your objects, characters, etc. even if you draw the ground in '3D'.
Ok, I finally got it working. Took some funky trig, but I got it drawing perspective without using the z-axis. I'll post a screen after I get this next thing fixed.

This is just a follow-up question. Is there any way to prevent textures from tiling? If you drive off the map, it would ideally just fill the empty area with a solid color. Is this possible?

[edit] Nevermind, got it fixed here: http://www.gamedev.net/community/forums/topic.asp?topic_id=393205

Here is a shot of it. Remember, no z-axis used at all.

http://i3.tinypic.com/zv90mh.jpg

[Edited by - marshdabeachy on May 16, 2006 2:08:58 AM]

This topic is closed to new replies.

Advertisement