How can I properly use Alphablend in the ModelDrawer.cs to display my .png files to preserve transparency.
If i turn off depthbuffer and leave Alphablend on - it looks perfect - that is the .png transparency (leaves on a tree)
but everything else on the other models in the simulation looks awkward.
Can you assist me with getting this to render correctly ?
I'm using the latest version .13. I can be more descriptive if I'm not clear enough.
Thanks!
Alphablend in ModelDrawer.cs
Re: Alphablend in ModelDrawer.cs
The ModelDrawer is designed as a debug drawing system. The 'instanced' version of the drawer is poorly suited to drawing transparent and nontransparent objects together since it batches everything together blindly. You could try creating two drawers and handle all the transparent geometry in the second one.
I strongly recommend against using the demos drawer as a normal game's renderer as there will likely be many more design conflicts like this one. It can draw blocks, spheres, capsules and such well, but trying to integrate more features into it will be ugly.
I strongly recommend against using the demos drawer as a normal game's renderer as there will likely be many more design conflicts like this one. It can draw blocks, spheres, capsules and such well, but trying to integrate more features into it will be ugly.
-
- Posts: 12
- Joined: Sat Jul 10, 2010 5:19 pm
Re: Alphablend in ModelDrawer.cs
Is the a hack fix that requires a small amount of code/movement of code that would allow me to get this to work that you might be able to assist with. My project may not require a lot of changes to the already written code - that why I'm asking.
Thanks in advance!
Your physics program is Awesome btw. I hope we can both be successful with it
Thanks in advance!
Your physics program is Awesome btw. I hope we can both be successful with it
Re: Alphablend in ModelDrawer.cs
The quickest and dirtiest solution I can think of off the top of my head is to have two ModelDrawers, say "opaqueModelDrawer" and "transparentModelDrawer." When creating and adding models to the drawers, add all opaque models to the opaque drawer, and add all transparent models to the transparent drawer.
Then, during the draw, draw the opaque model drawer first with the normal opaque renderstates. After that, enable transparency and draw the transparentModelDrawer.
The reason I didn't include disabling depth buffer writes was that they are needed to sort out which pixel is in front. This should work for things with 0% or 100% transparency, but does not handle partial transparency. This basically means your leaves have to have hard edges, so it's a binary alpha test rather than alpha 'blending.'
There are other, fancier, better ways of dealing with this issue, which Shawn Hargreaves explains better than I could: http://blogs.msdn.com/b/shawnhar/archiv ... jects.aspx
If you need to implement something a little fancier, you could look into the drawer's SelfDrawingModelDisplayObject which manages its own drawing completely. Of course, you can always use the drawer for what it can do, and custom implementations for what it cannot.
Then, during the draw, draw the opaque model drawer first with the normal opaque renderstates. After that, enable transparency and draw the transparentModelDrawer.
The reason I didn't include disabling depth buffer writes was that they are needed to sort out which pixel is in front. This should work for things with 0% or 100% transparency, but does not handle partial transparency. This basically means your leaves have to have hard edges, so it's a binary alpha test rather than alpha 'blending.'
There are other, fancier, better ways of dealing with this issue, which Shawn Hargreaves explains better than I could: http://blogs.msdn.com/b/shawnhar/archiv ... jects.aspx
If you need to implement something a little fancier, you could look into the drawer's SelfDrawingModelDisplayObject which manages its own drawing completely. Of course, you can always use the drawer for what it can do, and custom implementations for what it cannot.
Thanks!Your physics program is Awesome btw. I hope we can both be successful with it
-
- Posts: 12
- Joined: Sat Jul 10, 2010 5:19 pm
Re: Alphablend in ModelDrawer.cs
Just wanted to say thanks for the Tips on this.
Re: Alphablend in ModelDrawer.cs
hey this might help you.
in phone game i use this:
modelDrawer.draw(camera.viewMatrix, camera.projectionMatrix);
// lineDrawer.draw(camera.viewMatrix, camera.projectionMatrix);
//DRAW MODEL
drawModel(VehicleInput.snowBoard, Matrix.CreateTranslation(0, -1.2f, 0), VehicleInput.snowBoardTexture, true);
drawModel(VehicleInput.snowBoarder, Matrix.CreateScale(0.4f) * Matrix.CreateFromYawPitchRoll(0, -(float)Math.PI / 2, 0) * Matrix.CreateTranslation(0, -1.2f, 0), VehicleInput.shadowTexture, true);
//DRAW SHADOWS
GraphicsDevice.BlendState = BlendState.AlphaBlend;
drawShadow(VehicleInput.snowBoard, VehicleInput.snowBoardShadow, false, 0.25f);
drawShadow(VehicleInput.snowBoarder, VehicleInput.snowBoarderShadow, false, 0.25f);
GraphicsDevice.BlendState = BlendState.Opaque;
the shadows obviously need alpha blending, so i wrote my own drawer classes, which are the following:
it works really well for me, having these seperate classes to draw the diffrent stuff you want to draw. Make sure you draw all the transparant stuff at the end, the opaque stuff first!
(WorldTransForm is a copy of the vehicleinput.vehicle.body.worldtransform a public static matrix I use to pass it to the drawer to make it "stick" to the moving entity's).
good luck
public void drawMap(Model myModel)
{
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in myModel.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.PreferPerPixelLighting = true;
effect.LightingEnabled = true;
effect.DirectionalLight0.Enabled = true;
effect.DirectionalLight0.Direction = Vector3.Normalize(Light);
effect.DirectionalLight0.DiffuseColor = new Vector3(.5f, .5f, .5f);
effect.AmbientLightColor = new Vector3(.5f, .5f, .5f);
// effect.SpecularColor = new Vector3(0.8f, 0.8f, 0.6f);
// effect.SpecularPower = 16;
effect.TextureEnabled = true;
effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateTranslation(new Vector3(0, 0, 0));
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.Alpha = 1f;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}
}
public void drawModel(Model myModel, Matrix orientMatrix, Texture2D setTexture, bool SticksToSnowboard)
{
if (SticksToSnowboard == true)
{
orientMatrix = orientMatrix * VehicleInput.WorldTransForm;
}
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in myModel.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.PreferPerPixelLighting = true;
effect.LightingEnabled = true;
effect.DirectionalLight0.Enabled = true;
effect.DirectionalLight0.Direction = Vector3.Normalize(Light);
effect.DirectionalLight0.DiffuseColor = new Vector3(.5f, .5f, .5f);
effect.AmbientLightColor = new Vector3(.5f, .5f, .5f);
// effect.SpecularColor = new Vector3(0.8f, 0.8f, 0.6f);
// effect.SpecularPower = 16;
effect.TextureEnabled = true;
effect.World = transforms[mesh.ParentBone.Index] * orientMatrix;
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.Alpha = 1f;
effect.Texture = setTexture;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}
}
public void drawShadow(Model myModel, Matrix orientMatrix, bool SticksToSnowboard, float alpha)
{
if (SticksToSnowboard == true)
{
orientMatrix = orientMatrix * VehicleInput.WorldTransForm;
}
Texture2D TempTexture = null;
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in myModel.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.PreferPerPixelLighting = true;
effect.LightingEnabled = false;
effect.DirectionalLight0.Enabled = false;
effect.DirectionalLight0.Direction = Vector3.Normalize(Light);
effect.DirectionalLight0.DiffuseColor = new Vector3(.5f, .5f, .5f);
effect.AmbientLightColor = Vector3.Zero;
TempTexture = effect.Texture;
effect.TextureEnabled = true;
effect.Texture = VehicleInput.shadowTexture;
effect.World = transforms[mesh.ParentBone.Index] * orientMatrix;
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.Alpha = alpha;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
foreach (BasicEffect effect in mesh.Effects)
{
effect.Texture = TempTexture;
}
}
}
in phone game i use this:
modelDrawer.draw(camera.viewMatrix, camera.projectionMatrix);
// lineDrawer.draw(camera.viewMatrix, camera.projectionMatrix);
//DRAW MODEL
drawModel(VehicleInput.snowBoard, Matrix.CreateTranslation(0, -1.2f, 0), VehicleInput.snowBoardTexture, true);
drawModel(VehicleInput.snowBoarder, Matrix.CreateScale(0.4f) * Matrix.CreateFromYawPitchRoll(0, -(float)Math.PI / 2, 0) * Matrix.CreateTranslation(0, -1.2f, 0), VehicleInput.shadowTexture, true);
//DRAW SHADOWS
GraphicsDevice.BlendState = BlendState.AlphaBlend;
drawShadow(VehicleInput.snowBoard, VehicleInput.snowBoardShadow, false, 0.25f);
drawShadow(VehicleInput.snowBoarder, VehicleInput.snowBoarderShadow, false, 0.25f);
GraphicsDevice.BlendState = BlendState.Opaque;
the shadows obviously need alpha blending, so i wrote my own drawer classes, which are the following:
it works really well for me, having these seperate classes to draw the diffrent stuff you want to draw. Make sure you draw all the transparant stuff at the end, the opaque stuff first!
(WorldTransForm is a copy of the vehicleinput.vehicle.body.worldtransform a public static matrix I use to pass it to the drawer to make it "stick" to the moving entity's).
good luck
public void drawMap(Model myModel)
{
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in myModel.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.PreferPerPixelLighting = true;
effect.LightingEnabled = true;
effect.DirectionalLight0.Enabled = true;
effect.DirectionalLight0.Direction = Vector3.Normalize(Light);
effect.DirectionalLight0.DiffuseColor = new Vector3(.5f, .5f, .5f);
effect.AmbientLightColor = new Vector3(.5f, .5f, .5f);
// effect.SpecularColor = new Vector3(0.8f, 0.8f, 0.6f);
// effect.SpecularPower = 16;
effect.TextureEnabled = true;
effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateTranslation(new Vector3(0, 0, 0));
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.Alpha = 1f;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}
}
public void drawModel(Model myModel, Matrix orientMatrix, Texture2D setTexture, bool SticksToSnowboard)
{
if (SticksToSnowboard == true)
{
orientMatrix = orientMatrix * VehicleInput.WorldTransForm;
}
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in myModel.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.PreferPerPixelLighting = true;
effect.LightingEnabled = true;
effect.DirectionalLight0.Enabled = true;
effect.DirectionalLight0.Direction = Vector3.Normalize(Light);
effect.DirectionalLight0.DiffuseColor = new Vector3(.5f, .5f, .5f);
effect.AmbientLightColor = new Vector3(.5f, .5f, .5f);
// effect.SpecularColor = new Vector3(0.8f, 0.8f, 0.6f);
// effect.SpecularPower = 16;
effect.TextureEnabled = true;
effect.World = transforms[mesh.ParentBone.Index] * orientMatrix;
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.Alpha = 1f;
effect.Texture = setTexture;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}
}
public void drawShadow(Model myModel, Matrix orientMatrix, bool SticksToSnowboard, float alpha)
{
if (SticksToSnowboard == true)
{
orientMatrix = orientMatrix * VehicleInput.WorldTransForm;
}
Texture2D TempTexture = null;
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in myModel.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.PreferPerPixelLighting = true;
effect.LightingEnabled = false;
effect.DirectionalLight0.Enabled = false;
effect.DirectionalLight0.Direction = Vector3.Normalize(Light);
effect.DirectionalLight0.DiffuseColor = new Vector3(.5f, .5f, .5f);
effect.AmbientLightColor = Vector3.Zero;
TempTexture = effect.Texture;
effect.TextureEnabled = true;
effect.Texture = VehicleInput.shadowTexture;
effect.World = transforms[mesh.ParentBone.Index] * orientMatrix;
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.Alpha = alpha;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
foreach (BasicEffect effect in mesh.Effects)
{
effect.Texture = TempTexture;
}
}
}
-
- Posts: 12
- Joined: Sat Jul 10, 2010 5:19 pm
Re: Alphablend in ModelDrawer.cs
Marvin - Thank you for your response! I appreciate it very much. I have been so focused on assets for my game in last few weeks that I forgot to check back in the thread for updates. Thanks again!