XNA 3.1 Custom shader for certain sprites - c#

I'm trying for hours now to solve this problem..
So.. I want to use different shaders on every Sprite I draw on the screen.
I tried to make different RenderTarget2Ds but no success.
No matter how hard I try to make the Graphicsdevice.Clear() Transparent, it just won't work.
(I use xna 3.1)
So all my sprites blocking the other sprites because I can't make the background transparent :\
Any idea ?
Code I use (it's a method):
graphicsDevice.SetRenderTarget(0, r2d);
graphicsDevice.Clear(ClearColor);
spriteBatch.Begin();
spriteBatch.Draw(
tex,
Dest,
Source,
moodcolor,
this.RotationAngle,
new Vector2(0, 0),
Zoom,
spriteEffect,
this.Z_Index);
spriteBatch.End();
graphicsDevice.SetRenderTarget(0, null);
graphicsDevice.Clear(ClearColor);
for (int i = 0; i < efs.Count; i++)
{
efs[i].effect.CurrentTechnique = efs[i].effect.Techniques["Deferred"];
foreach (EffectPass pass in efs[i].effect.CurrentTechnique.Passes)
{
spriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
efs[i].effect.Begin();
pass.Begin();
spriteBatch.Draw(r2d.GetTexture(), Vector2.Zero, Color.White);
spriteBatch.End();
pass.End();
efs[i].effect.End();
}
}
Update!
You don't have to use RenderTarget2D!
It's important to keep AlphaBlend!
This is solution for anybody who came across the same problem!
Solution snippet:
foreach (EffectPass pass in efs[ObjShaders[i].ShaderID].effect.CurrentTechnique.Passes)
{
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
efs[ObjShaders[i].ShaderID].effect.Begin();
pass.Begin();
spriteBatch.Draw(
tex,
Dest,
Source,
moodcolor,
this.RotationAngle,
new Vector2(0, 0),
Zoom,
spriteEffect,
this.Z_Index);
spriteBatch.End();
pass.End();
efs[ObjShaders[i].ShaderID].effect.End();
}

Reading your question again, perhaps all you need to do is
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
Now if your sprite textures have an alpha channel, they will be blended correctly.

Related

Draw text on a 3D plane sharpDX

I searched and didn't find a way to do that.
I want to attach labels to 3D objects using sharpDX in HoloLens app.
anyone knows how?
thanks
edit:
so I decided to convert the text to image and then put it as texture on a plane made of 2 triangles mesh.
so now I tried this code:
https://gist.github.com/naveedmurtuza/6600103
but can't include the references, how do I fix that?
thanks
I wrote a game using SharpDx a few years ago, here's a video of it:
https://www.youtube.com/watch?v=tDRmIY6-8Z4
If I understand you correctly, you want 3D-texts just as the ones I'm using to explain the game elements? If so, you might get some ideas from this source code:
protected override bool draw(Camera camera, DrawingReason drawingReason, ShadowMap shadowMap)
{
if (drawingReason != DrawingReason.Normal)
return true;
camera.UpdateEffect(Effect);
foreach (var item in Items)
{
Effect.World = Matrix.BillboardRH(item.Target.Position + item.GetOffset(item), camera.Position, -camera.Up, camera.Front);
Effect.DiffuseColor = item.GetColor(item);
SpriteBatch.Begin(SpriteSortMode.Deferred, Effect.GraphicsDevice.BlendStates.NonPremultiplied, null, Effect.GraphicsDevice.DepthStencilStates.DepthRead, null, Effect.Effect);
SpriteBatch.DrawString(Font, item.Text, Vector2.Zero, Color.Black, 0, Font.MeasureString(item.Text) / 2, item.GetSize(item), 0, 0);
SpriteBatch.End();
}
Effect.GraphicsDevice.SetDepthStencilState(Effect.GraphicsDevice.DepthStencilStates.Default);
Effect.GraphicsDevice.SetBlendState(Effect.GraphicsDevice.BlendStates.Opaque);
return true;
}
Full game code is open source and available here:
https://github.com/danbystrom/Larv/blob/master/src/factor10.VisionThing/FloatingText/FloatingTexts.cs#L32

XNA Spritebatch.End() with Class doesn't work when started

XNA spritebatch.End(); with a class doesn't work and it is saying: 'XNA Framework Reach profile requires TextureAddressMode to be Clamp when using texture sizes that are not powers of two.' when started. And it doesn't show any error's either. How can I solve this? Please help!!
public override void Draw()
{
Statics.SPRITEBATCH.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, null,null);
Statics.SPRITEBATCH.Draw(this.background, Vector2.Zero, Color.White);
foreach (var item in Tuyaux)
{
item.Draw();
}
Statics.SPRITEBATCH.Draw(this.sand, new Vector2(0, 529), Color.White);
Scroll.Draw();
Bird.Draw();
Statics.SPRITEBATCH.DrawString(this.Font, "Score : " + this.score.ToString(), new Vector2(10, 10), Color.Red);
if (Bird.dead)
{
// rode gloed over het spel als het gameover is.
Statics.SPRITEBATCH.Draw(Statics.PIXEL, new Rectangle(0,0, Statics.GAME_WIDTH,Statics.GAME_HEIGHT), new Color(1f, 0f, 0f, 0.3f));
// gameover achtergrond laten zien.
Statics.SPRITEBATCH.Draw(this.gameover, new Vector2(0, 80), Color.White);
}
Statics.SPRITEBATCH.End();
base.Draw();
}
The problem is exactly what the exception tells you:
You are targetting the Reach profile, so either all your texture dimensions must be powers of two or you have to use clamp as adress mode. So:
If you don't need wrapping, try replacing SamplerState.LinearWrap with SamplerState.LinearClamp in your Statics.SPRITEBATCH.Begin call.
If you need wrapping textures, make sure all of them have dimensions that are powers of two
Last but not least, if it is an option for you, you may simply use the HiDef profile instead of Reach

Drawn quads, lines, points in opentk don't show up right

I've got drawing sprites to work with OpenTK in my 2d game engine now. Only problem I'm having is that custom drawn objects with opengl (anything but sprites really) show up as the background color. Example:
I'm Drawing a 2.4f width black line here. There's also a quad and a point in the example, but they do not overlap anything that's actually visible. The line overlaps the magenta sprite, but the color is just wrong. My question is: Am I missing an OpenGL feature, or doing something horrible wrong?
These are the samples of my project concerning drawing: (you can also find the project on https://github.com/Villermen/HatlessEngine if there's questions about the code)
Initialization:
Window = new GameWindow(windowSize.Width, windowSize.Height);
//OpenGL initialization
GL.Enable(EnableCap.PointSmooth);
GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest);
GL.Enable(EnableCap.LineSmooth);
GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.ClearColor(Color.Gray);
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
GL.ClearDepth(1d);
GL.DepthRange(1d, 0d); //does not seem right, but it works (see it as duct-tape)
Every draw cycle:
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
//reset depth and color to be consistent over multiple frames
DrawX.Depth = 0;
DrawX.DefaultColor = Color.Black;
foreach(View view in Resources.Views)
{
CurrentDrawArea = view.Area;
GL.Viewport((int)view.Viewport.Left * Window.Width, (int)view.Viewport.Top * Window.Height, (int)view.Viewport.Right * Window.Width, (int)view.Viewport.Bottom * Window.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(view.Area.Left, view.Area.Right, view.Area.Bottom, view.Area.Top, -1f, 1f);
GL.MatrixMode(MatrixMode.Modelview);
//drawing
foreach (LogicalObject obj in Resources.Objects)
{
//set view's coords for clipping?
obj.Draw();
}
}
GL.Flush();
Window.Context.SwapBuffers();
DrawX.Line:
public static void Line(PointF pos1, PointF pos2, Color color, float width = 1)
{
RectangleF lineRectangle = new RectangleF(pos1.X, pos1.Y, pos2.X - pos1.X, pos2.Y - pos1.Y);
if (lineRectangle.IntersectsWith(Game.CurrentDrawArea))
{
GL.LineWidth(width);
GL.Color3(color);
GL.Begin(PrimitiveType.Lines);
GL.Vertex3(pos1.X, pos1.Y, GLDepth);
GL.Vertex3(pos2.X, pos2.Y, GLDepth);
GL.End();
}
}
Edit: If I disable the blendcap before and enable it after drawing the line it does show up with the right color, but I must have it blended.
I forgot to unbind the texture in the texture-drawing method...
GL.BindTexture(TextureTarget.Texture2D, 0);

Debugging SpriteBatch.Draw [duplicate]

This question already has answers here:
Xna draw order not working right
(2 answers)
Closed 9 years ago.
Problem: When an if clause is put around a spriteBatch.Draw statement, it seems to affect other spriteBatch.Draw that is outside the if clause .
This is (part of) the code in the Draw method:
if(OvertakeMouseHover == true)
{
spriteBatch.Draw(OvertakeButton, OvertakeButtonPosition, Color.White);
}
spriteBatch.Draw(Car1, Car1Position, Color.White);
spriteBatch.Draw(Car2, Car2Position, Color.White);
And this is the code setting OvertakeMouseHover:
if (mouse.X > OvertakeButtonPosition.X && mouse.X < OvertakeButtonPosition.X + OvertakeButton.Width &&
mouse.Y > OvertakeButtonPosition.Y && mouse.Y < OvertakeButtonPosition.Y + OvertakeButton.Height)
{
//Overtake button mouseover
OvertakeMouseHover = true;
}
else
{
OvertakeMouseHover = false;
}
When running the above code, OvertakeButton appears as expected (ie when the mouse is hovering over its location). Car2 appears as expected (all the time). However Car1, rather than appearing all the time, appears and disappears with the OvertakeButton, as though spriteBatch.Draw(Car1...) is within the if statement.
The following code makes all 3 sprites appear all the time:
//if(OvertakeMouseHover == true)
//{
spriteBatch.Draw(OvertakeButton, OvertakeButtonPosition, Color.White);
//}
spriteBatch.Draw(Car1, Car1Position, Color.White);
spriteBatch.Draw(Car2, Car2Position, Color.White);
I can't for the life of me work out why spriteBatch.Draw(Car1..) is affected by the if statement, but it definitely looks like it is to me. All ideas welcome!
EDIT - and this code makes all 3 sprite appear and disappear with the MouseHover. It's as though the bracket is one line lower than it should be:
if (OvertakeMouseHover == true)
{
spriteBatch.Draw(OvertakeButton, OvertakeButtonPosition, Color.White);
spriteBatch.Draw(Car1, Car1Position, Color.White);
}
spriteBatch.Draw(Car2, Car2Position, Color.White);
EDIT 2. Okay this is to do with the image appearing in front/behind of my background. In which case the issue is to do with sorting. How do I force the sorting order? I assumed it was just back to front in order of the code but that doesn't seem to be it.
EDIT 3. Entire draw method. Currently investigating what the various sort options do.
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Backtofront, BlendState.AlphaBlend);
spriteBatch.Draw(RaceBackground, BackgroundPosition, Color.White);
spriteBatch.Draw(Car1, Car1Position, Color.White);
spriteBatch.Draw(Car2, Car2Position, Color.White);
if (OvertakeMouseHover == true)
{
spriteBatch.Draw(OvertakeButton, OvertakeButtonPosition, Color.White);
}
string output = Car1Speed.ToString();
// Find the center of the string
Vector2 FontOrigin = Font1.MeasureString(output) / 2;
// Draw the string
spriteBatch.DrawString(Font1, output, FontPos, Color.LightGreen,
0, FontOrigin, 1.0f, SpriteEffects.None, 0.5f);
spriteBatch.End();
// TODO: Add your drawing code here
base.Draw(gameTime);
You should call SpriteBatch.Begin with SpriteSortMode.Deferred
Deferred guarantees that your sprites will be drawn in the order that you called the Draw method for them.
Deferred
Sprites are not drawn until End is called. End will apply graphics
device settings and draw all the sprites in one batch, in the same
order calls to Draw were received. This mode allows Draw calls to two
or more instances of SpriteBatch without introducing conflicting
graphics device settings. SpriteBatch defaults to Deferred mode.
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritesortmode.aspx
according to the documentation, BackToFront says that it works the same as deferred, except that it takes depth into account, but you might be running into a bug with it. This is not the first time that I would have seen this bug.
If you use SpriteSortMode.BackToFront you need to specify the depth of each sprite, otherwise the game will draw them at the same time, making them to "flicker".
You may need to use a different SpriteBatch.Draw overload that has float layerDepth parameter, something like this one:
public void Draw (
Texture2D texture,
Vector2 position,
Nullable<Rectangle> sourceRectangle,
Color color,
float rotation,
Vector2 origin,
float scale,
SpriteEffects effects,
float layerDepth
)
Or better, as Sam I am previously wrote, use SpriteSortMode.Deferred which is easier to use and understand.

xna 3d model shown broken

i just try draw a simple 3d model(many model (.fbx) tested) with basicEffect in xna 4.0 , and there is no other object like 2d spritebatchs or text or ...
but it does not shown correctly , i searched it and did some solution but no one work
like set
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
although i did not draw anything else ! and what is funny i already work with 3d model without problem !
here is my draw code and a result screenshot
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
foreach (ModelMesh mesh in m_Model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
BasicEffect effect = (BasicEffect)meshPart.Effect;
effect.View = Matrix.CreateLookAt(new Vector3(0, 100, 1000), Vector3.Zero, Vector3.Up);
effect.World = bones[mesh.ParentBone.Index] * (Matrix.CreateWorld(Vector3.Zero, Vector3.Right, Vector3.Up));
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.0001f, 1000000f);
effect.EnableDefaultLighting();
}
mesh.Draw();
}
base.Draw(gameTime);
}
ty for your time
The near clip value in your projection Matrix is most likely causing this. Try setting it to 1.0f instead of 0.0001f. If that doesn't solve the problem completely, bring the far clip down to something like 10000f.
edit - noticing that your camera is over 1000 units away from your model, you can even set the near clip to 5f or 10f to gain depth read precision if needed.
Its the problem of depth buffer, you are using the spritebrite to draw something which changes your default depth buffer off.
Make it on before drawing 3d model mesh.
After calling SpriteBatch.End(), add this code:
device.DepthStencilState = DepthStencilState.Default;

Categories