Draw text on a 3D plane sharpDX - c#

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

Related

Take a screenshot without the UI elements in Unity [duplicate]

This question already has answers here:
Can I take a photo in Unity using the device's camera?
(8 answers)
Closed 1 year ago.
I am trying to capture what the camera sees in phone in an AR app and take a photo of it. What I found was to take a screenshot of the device and then save that as an image. However, I want to take a screenshot of what the camera sees instead of the screen. That is without any 2D or 3D elements created in the application. Just purely what the camera sees. How do I do this?
public void Start() {
StartCoroutine ("SaveImage");
}
WaitForEndOfFrame frameEnd = new WaitForEndOfFrame ();
IEnumerator SaveImage() {
// Create a texture the size of the screen, RGB24 format
int width = Screen.width;
int height = Screen.height;
yield return frameEnd;
var tex = new Texture2D (width, height, TextureFormat.RGB24, false);
// Read screen contents into the texture
tex.ReadPixels (new Rect (0, 0, width, height), 0, 0);
tex.Apply ();
byte[] bytes = tex.EncodeToPNG ();
Destroy (tex);
var form = new WWWForm ();
form.AddField ("plant", plantComponentID);
form.AddBinaryData ("image", bytes, "screenShot.png", "image/png");
yield return null;
}
Interesting question.
What I would try is to set up a RenderTexture, and tell a camera in your scene to render to it. Then I would try to use the
ImageConversion class to get my camera eye screenshot to a file.
This is just what my attempt would be. Not sure if that is the correct way, so providing that just in case it helps. I would be glad to know the outcome of your attempt in case you try it :)

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 weird terrain tearing

Let me post the images first...
Solid shot where tearing occurs
And wireframe shot of that place
I am mostly using mostly using Riemers tutorial while the render code is..
Main render
public void Render()
{
device.Clear(Color.CornflowerBlue);
RasterizerState rs = new RasterizerState();
rs.CullMode = cullmode;
rs.FillMode = fillmode;
device.RasterizerState = rs;
effect.Parameters["xView"].SetValue(camera.ViewMatrix);
effect.Parameters["xProjection"].SetValue(camera.ProjectionMatrix);
effect.Parameters["xWorld"].SetValue(Matrix.Identity);
effect.Parameters["xEnableLighting"].SetValue(true);
effect.Parameters["xLightDirection"].SetValue(lightDirection);
effect.Parameters["xAmbient"].SetValue(0.5f);
globals.game.terrain.Render();
globals.game.spriteBatch.Begin();
globals.console.Render();
globals.game.spriteBatch.End();
}
Terrain.Render()
public void Render()
{
globals.game.graphics.effect.CurrentTechnique = globals.game.graphics.effect.Techniques["Colored"];
globals.game.graphics.effect.Parameters["xWorld"].SetValue(worldMatrix);
foreach (EffectPass pass in globals.game.graphics.effect.CurrentTechnique.Passes)
{
pass.Apply();
globals.game.graphics.device.Indices = indexBuffer;
globals.game.graphics.device.SetVertexBuffer(vertexBuffer);
globals.game.graphics.device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, indices.Length / 3);
}
}
I was stuck with this problem for pretty long now (not knowing if it is caused by my coding skills, xna or some g-card configuration...) so i wonder if someone have some ideas what might cause it?
Temporarily comment out the spritebatch begin, draw, & end code and see if that makes a difference. It may or may not depending on the vertex order in the buffer.
If it does help, your solution can be found here: http://blogs.msdn.com/b/shawnhar/archive/2010/06/18/spritebatch-and-renderstates-in-xna-game-studio-4-0.aspx

XNA 3.1 Custom shader for certain sprites

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.

Extreme tearing when I move the camera quickly

I am creating a minecraft clone, and whenever I move the camera even a little bit fast there is a big tear between the chunks as shown here:
Each chunk is 32x32x32 cubes and has a single vertex buffer for each kind of cube, in case it matters. I am drawing 2D text on the screen as well, and I learned that I had to set the graphic device state for each kind of drawing. Here is how I'm drawing the cubes:
GraphicsDevice.Clear(Color.LightSkyBlue);
#region 3D
// Set the device
device.BlendState = BlendState.Opaque;
device.DepthStencilState = DepthStencilState.Default;
device.RasterizerState = RasterizerState.CullCounterClockwise;
// Go through each shader and draw the cubes of that style
lock (GeneratedChunks)
{
foreach (KeyValuePair<CubeType, BasicEffect> KVP in CubeType_Effect)
{
// Iterate through each technique in this effect
foreach (EffectPass pass in KVP.Value.CurrentTechnique.Passes)
{
// Go through each chunk in our chunk map, and pluck out the cubetype we care about
foreach (Vector3 ChunkKey in GeneratedChunks)
{
if (ChunkMap[ChunkKey].CubeType_TriangleCounts[KVP.Key] > 0)
{
pass.Apply(); // assign it to the video card
KVP.Value.View = camera.ViewMatrix;
KVP.Value.Projection = camera.ProjectionMatrix;
KVP.Value.World = worldMatrix;
device.SetVertexBuffer(ChunkMap[ChunkKey].CubeType_VertexBuffers[KVP.Key]);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, ChunkMap[ChunkKey].CubeType_TriangleCounts[KVP.Key]);
}
}
}
}
}
#endregion
The world looks fine if I'm standing still. I thought this might be because I'm in windowed mode, but when I toggled full screen the problem persisted. I also assume that XNA is double buffered by itself? Or so google has told me.
I had a similar issue - I found that I had to call pass.Apply() after setting all of the Effect's parameters...
The fix so far has been to use 1 giant vertex buffer. I don't like it, but that's all that seems to work.

Categories