I've seen a lot of threads about transparency here, but none of them answer my question.
What I want to achieve is drawing a model at half transparency. This is for a level editor that will show where the next object will be at. I read about a blending tutorial being planned, but couldn't find it.
Also, is it possible to do this without having to have two copies of the same model, one with transparency and one without? There is a LOT of content, so the former wouldn't really be practical.
Thanks!
Hi Uber,
The easiest way to accomplish this effect is to keep an extra BasicEffect around for custom rendering the selected object outside the render manager.
Then render the current selected object (between the calls to Render and EndFrameRendering), and for each model part set the BasicEffect's Texture to the model part's texture (from the SunBurn effect), Alpha value to the transparency level you want, and make sure the device blend mode is set to Source: SourceAlpha Destination: InverseSourceAlpha.
This should provide a great looking "ghost object" effect that can be moved around the scene independent of the object's current location.
Let me know if this helps!
Follow me on Twitter – development and personal tweetsAwesome XNA Videos – Lighting, Rendering, and game videos
Thanks. Can you post an example of how to do this? If the model is loaded using SunBurn's content processors it will have a LightingEffect applied to it instead of BasicEffect, and since the ModelMesh's Effect property is read only how can I change it when drawing the ghost effect, without having to load two copies of the same model with different processors?
The ModelMeshPart's effect property is read / write, if you'd like to use the ModelMesh's built-in Draw method - just make sure to restore the SunBurn materials afterward (unless the scene is completely static and the objects are never resubmitted).
Or you can use the RenderMeshPart method from the SunBurn Custom Renderer starter kit - it sets up the effect's transforms (for both SunBurn effects and BasicEffect) and renders the ModelMeshPart. This kit also shows how to use the Model's CopyAbsoluteBoneTransformsTo method to get each mesh's meshToWorld (<edited this from objectToWorld) transform.
Oh I see, I was one level away from it. It renders now, but instead of being transparent and textured the object is completely white. Here's my drawing code:
(hmm, I don't see any code box option)
//submit sunburn objectsSunBurn.BeginRender(gameTime, view, projection);SunBurn.Render(); ScreenManager.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;ScreenManager.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;basicEffect.Alpha = .5f;basicEffect.World = world;basicEffect.View = view;basicEffect.Projection = projection;Effect prevEffect = null;foreach (ModelMesh mm in currentTileType.model.model.Meshes){ LightingEffect le = mm.Effects[0] as LightingEffect; foreach (ModelMeshPart mmp in mm.MeshParts) { prevEffect = mmp.Effect; mmp.Effect = basicEffect; basicEffect.Texture = le.DiffuseMapTexture; }}foreach (ModelMesh mm in currentTileType.model.model.Meshes){ foreach (ModelMeshPart mmp in mm.MeshParts) { if(prevEffect != null) mmp.Effect = prevEffect; }}SunBurn.EndRender();
Hmm, there are a lot of bad things going on in that code. ;)
Each ModelMeshPart contains a unique effect, so you'll need to get the LightingEffect and its texture for every part. The previous effect will always be the last one referenced, not necessarily the one originally removed from the part. The code doesn't call ModelMesh.Draw or get / set each part's meshToWorld transform on the effect.
It might be a lot easier to use the Custom Renderer kit's RenderMeshPart method as a template for rendering model parts without swapping and restoring effects.
And you can continue to use your existing rendering code (except for restoring the effect, which isn't needed) - something like (pseudo code):
foreach (ModelMesh mm in currentTileType.model.model.Meshes){ Matrix meshtoobject = bones[mm.ParentBone.Index]; foreach (ModelMeshPart mmp in mm.MeshParts) { LightingEffect le = mmp.Effect as LightingEffect; basicEffect.Texture = le.DiffuseMapTexture; RenderMeshPart(mm, mmp, meshtoobject , basicEffect, true, false, false); }}
Same thing; it's drawn in the correct position but is full white... What am I missing here?
SunBurn.BeginRender(gameTime, view, projection);SunBurn.Render(); ScreenManager.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;ScreenManager.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;basicEffect.Alpha = .5f;basicEffect.World = world;basicEffect.View = view;basicEffect.Projection = projection;foreach (ModelMesh mm in currentTileType.model.model.Meshes){ Matrix[] bones = new Matrix[currentTileType.model.model.Bones.Count]; currentTileType.model.model.CopyAbsoluteBoneTransformsTo(bones); Matrix meshtoobject = bones[mm.ParentBone.Index]; foreach (ModelMeshPart mmp in mm.MeshParts) { LightingEffect le = mmp.Effect as LightingEffect; basicEffect.Texture = le.DiffuseMapTexture; SunBurn.RenderMeshPart(mm, mmp, meshtoobject, basicEffect, true, false, false, world, view, projection); }}SunBurn.EndRender();
Make sure to set BasicEffect.TextureEnabled to true.
Doh. Was missing TextureEnabled as you said, and RenderState.AlphaTestEnable.
Now it works perfectly. Thanks for the help!
(might want to add this to the wiki or something, since I imagine it's a common scenario)
Hey there, to continue this thread for a bit longer, I was wondering if the following could/should work.
In a nutshell, I'm submitting all my dynamic objects to Sunburn once during initialization *except* the one I want to render with transparency.
Then after the RenderManager.Render() call, I do this:
// set transparency:
mGraphics.GraphicsDevice.RenderState.AlphaBlendEnable = true;
mGraphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha; mGraphics.GraphicsDevice.RenderState.DestinationBlend = Blend.One;
// submit the model:
mSceneInterface.ObjectManager.Submit(mMySceneObject);
The object renders where it should but without any transparency. The initial code I started with was the Windmill example so if you can imagine trying to make one of the Blades transparent, that may help.
Any help would be appreciated. Thanks.
Hi secluder,
SunBurn doesn't support Alpha Blended objects in its current status as it would require them to be sorted based on their distance from the camera and would bring some issues with the deferred rendering implementation.
You still can have alpha blended objects using a custom rendering pipeline.
You can see in this post, my implementation of a custom renderer that you can add to SunBurn SceneInterface (using the AddManager() method) that worked on Xna 3.1 (I still have to bring a Xna 4 version).
The principle is quite simple:
Make sure to change your RenderState to RenderState.AlphaBlend or Additive (depending on what you are trying to achieve) and render your models or geometry using standard XNA 4 Drawing capabilities (Xna effects and Models) between the call to SceneInterface.RenderManager.Render() and SceneInterface.EndFrameRendering.
Make sure also that you render them from far to close to camera.