[MDX2] How to fill a 3D polygon with texture brush

Started by
18 comments, last by wong_bo 17 years, 10 months ago
Thank you remigius for your last post. Sorry for the late reply as I was sidetracked recently.

I managed to get it work with MDX2 and pretty happy with your solution. I've got some final questions:

1. I only use 2 colors for our bitmap: black background and white foreground. Any black color in the bitmap should be treated as transparent when rendering. In the following image, part of the triangle at the back should be able to see through the front triangle.

Image and video hosting by TinyPic

2. I want to be able to replace the foreground white color of the bitmap to any specified color. For example, I want yellow cross and green circle pattern in the 2 triangles respectively.

Is there a solution for this?
Advertisement
I solved the 2nd problem by using PositionColoredTextured structure for m_triangle array and specify the appropriate color for the triangle.

I am still facing the 1st problem of having a transparent (alpha blended?) texture. It seems I have to use something like the following code, but I don't know the exact parameter I should use. Could anyone help me?
m_device.SetRenderState(RenderStates.AlphaBlendEnable, true);m_device.SetRenderState(RenderStates.SourceBlend, (int)Blend.???);m_device.SetRenderState(RenderStates.DestinationBlend, (int)Blend.???);m_device.SetTextureState(0, TextureStates.AlphaOperation, (int)TextureOperation.???);

and more SetTextureState()??? I hope I can find an article to clearly explain all these operations and parameters.
I just updated the sample project again to include this functionality.

You can specify a color when you load the texture which should be transparant, like this:

// note the last colorkey argument, which specifies which color to treat as transparentt = TextureLoader.FromFile(e.Device, @"..\..\media\t1.png",     16, 16, 1, Usage.None, Format.A8R8G8B8, Pool.Default,     Filter.Linear, Filter.Linear, unchecked((int)0xff000000));


Then you can use the following arguments to set up alpha blending:

// Set up alpha blendingdevice.RenderState.AlphaBlendEnable = true;device.RenderState.SourceBlend = Blend.SourceAlpha;device.RenderState.DestinationBlend = Blend.InvSourceAlpha;


Since this will leave only the non-black pixels visible in our example, we can just use a single color for the rendering. This can be done through the vertex colors as you used, or through the TextureFactor constant, like this:

// Set up color operationsdevice.TextureState[0].ColorArgument1 = TextureArgument.TFactor;device.TextureState[0].ColorOperation = TextureOperation.SelectArg1;device.RenderState.TextureFactor = c1;


I've also adjusted the shader to provide the same functionality. There seems to be a very minor filtering issue with this though, so the textures look a bit 'blurred' (the alpha isn't as clearly defined as through the FFP). It looks nice enough, but if anyone could check out the sample, I'd like to know what causes this difference from the FFP (the reference device also shows this result).
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
remigius, you are the man! Many thanks for the sample code.

Now the only problem I am facing is that only the 2nd triangle appears to be transparent to the first. Not the otherway around.

To test this, I changed your code of drawing 2nd triangle. Instead of rotating it, I did a translation:
//world = Matrix.RotationZ((float)appTime) * world;world = Matrix.Translation(0, 0.5f, 0.5f) * world;

Now the first triangle (red) is still opaque to the 2nd triangle (green).

But if I change the code to:
world = Matrix.Translation(0, 0.5f, -0.5f) * world;

The 2nd triangle(green) looks transparent to the 1st triangle(red).

Image and video hosting by TinyPic

What I need is whenever one triangle is on top of the other triangle, its fill pattern should cover the bottom triangle, but the bottom triangle's fill pattern should still be able to see through the top triangle's transparent area that is not filled.

I'm not completely awake yet over here, but I think this is due to the typical limitation of alpha blending. With the alpha blending the sample uses now, you're responsible for sorting your objects from back-to-front in respect to the camera, so underlying objects are rendered first.

So you'll either will have to do this sort yourself every frame (which shouldn't be too hard or inefficient) or you could switch to alpha testing instead of alpha blending. With alpha testing you can essentially only define transparent regions, while alpha blending supports nifty stuff like additive blending. To use alpha testing, change the alpha blend setup lines to this:

device.RenderState.AlphaTestEnable = true;device.RenderState.ReferenceAlpha = 0x08; // or any other appropriate valuedevice.RenderState.AlphaFunction = CompareFunction.GreaterEqual;
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
I think maybe I asked too many questions. But I feel I am getting so close to the solution with the guidance.

Alpha testing sorted out the depth problem without having to write any extra code (which could be difficult to maintain). Now the problem is that it fills the triangles with pattern that is thicker than the original image (the original images are shown at the bottom-left corner of the attached picture). The good thing is that now the anti-aliasing blur is gone.

Image and video hosting by TinyPic

I suspect that anti-aliasing is still being used underneath and the result image is then projected as silhouette. That's why the patterns looks like they were drawn using a thicker pen. If I switch to TextureFilter.Point instead of TextureFilter.Linear, the pattern becomes normal size but then I got this twitching effect when rotating.

The best effect would be:
1. Using the original image drawing width.
2. No anti-aliasing effect.
3. The top triangle should be able to cover the bottom triangle.
4. No twitching when rotate.

By the way, what does
device.RenderState.ReferenceAlpha = 0x08;

mean? Should I provide an ARGB value?
yap, use ReferenceAlpha (8bit value), use a very high value like 250 (or 0xFA) to make sure only very opaque parts are rendered. alternatively you could use just alpha blending, but then you might have a z-buffer problem again (you have to render back to front if you use soft alpha blending).
Microsoft DirectX MVP. My Blog: abi.exdream.com
It worked!

I set ReferenceAlpha = 100 and my pattern rendered perfectly. I tested and the ReferenceAlpha range from 70 to 120 works alright with my patterns. Now I can enjoy my patterns being rendered clearly and occlude each other.

Thanks again everyone.
I was reading this thread and was wondering how you fixed the twitching of the texture. Thanks in advance!
There was a time that I had the twitching problem even though I followed remigius' instruction to set
device.SamplerState[0].MinFilter = TextureFilter.Linear;device.SamplerState[0].MagFilter = TextureFilter.Linear;device.SamplerState[0].MipFilter = TextureFilter.Linear;

Then after few changes in my code, the problem just gone. I am not sure what I did in my code.

Setting all those 3 filters to linear is the only advice I can give. Are you still having the twitching problem after setting all the filters? If so, maybe you can download remigius' code and compare the device.SamplerState[0] (maybe other properties like device.RenderState and device.TextureState[0]) with your code in debug mode.

Good luck.

This topic is closed to new replies.

Advertisement