How to draw textures on a model - c#

The following code is a complete XNA 3.1 program almost unaltered to that code skeleton Visual Studio is creating when creating a new project.
The only things I have changed are
imported a .x model to the content folder of the VS solution.
(the model is a simple square with a texture spanning over it - made in Google Sketchup and exported with several .x exporters)
in the Load() method I am loading the .x model into the game.
The Draw() method uses a BasicEffect to render the model.
Except these three things I haven't added any code.
Why does the model does not show the texture ? What can I do to make the texture visible ?
This is the texture file (a standard SketchUp texture from the palette):
And this is what my program looks like - as you can see: No texture!
This is the complete source code of the program:
namespace WindowsGame1 {
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game {
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Game1() {
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize() {
// TODO: Add your initialization logic here
base.Initialize();
}
Model newModel;
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent() {
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: usse this.Content to load your game content here
newModel = Content.Load<Model>(#"aau3d");
foreach (ModelMesh mesh in newModel.Meshes) {
foreach (ModelMeshPart meshPart in mesh.MeshParts) {
meshPart.Effect = new BasicEffect(this.GraphicsDevice, null);
}
}
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent() {
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime) {
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime) {
if (newModel != null) {
GraphicsDevice.Clear(Color.CornflowerBlue);
Matrix[] transforms = new Matrix[newModel.Bones.Count];
newModel.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in newModel.Meshes) {
foreach (BasicEffect effect in mesh.Effects) {
effect.EnableDefaultLighting();
effect.TextureEnabled = true;
effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY(0)
* Matrix.CreateTranslation(new Vector3(0, 0, 0));
effect.View = Matrix.CreateLookAt(new Vector3(200, 1000, 200), Vector3.Zero, Vector3.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),
0.75f, 1.0f, 10000.0f);
}
mesh.Draw();
}
}
base.Draw(gameTime);
}
}
}

I think you're trying to do too much. It will depend on what is in the ".x" file, but these CAN contain all the shaders needed to color and texture the model.
I believe the problem is that after loading the model, you are overriding the model's Effects with a BasicEffect, which doesn't know about the texture you want to use for your Model.
The easiest thing to do I think would be to comment out the code relating to the BasicEffect in LoadContent. The setting of "EnableDefaultLighting()" and/or "TextureEnabled" might be unnecessary too.

I had some problems using .x models in the past. Try using .fbx to export your files. Once exported from your 3D app put both the model asset and its texture in the same map within your project. Do not rename it since the name of the texture is in the .FBX which might not be readable.

Related

Monogame shader doesn't draw anything

I'm brand new to working with shaders and I'm trying to learn how to use them with Monogame. I've been reading a few tutorials online about them and I'm already running into problems. It may be that the tutorials are outdated? When I apply the effect I just get a blank, cornflowerblue, screen.
#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif
texture ScreenTexture;
sampler TextureSampler = sampler_state {
Texture = <ScreenTexture>;
};
float4 PixelShaderFunction(float2 TextureCoordinate : TEXCOORD0) : COLOR0{
float4 color = tex2D(TextureSampler, TextureCoordinate);
return color;
}
technique Plain {
pass Pass1 {
PixelShader = compile PS_SHADERMODEL PixelShaderFunction();
}
};
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace ShaderTest {
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game {
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Effect shader1;
Texture2D peach;
public Game1() {
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize() {
// TODO: Add your initialization logic here
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent() {
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
shader1 = Content.Load<Effect>("shader1");
peach = Content.Load<Texture2D>("peach");
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// game-specific content.
/// </summary>
protected override void UnloadContent() {
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime) {
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime) {
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
shader1.CurrentTechnique.Passes[0].Apply();
spriteBatch.Draw(peach, new Vector2(0, 0), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
without shader:
with shader:

Sprite not appearing in monogame?

I am currently getting back in to MonoGame but for some reason I am having an issue drawing a simple sprite to the screen.
I am using VS2015 community, created a new multiplatform MonoGame project, and then right-clicked on the Content folder and added existing item to load my 'player.png' image in to the project.
I then wrote the following code to load the image and draw to the screen:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace BulletHell
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D playerImage;
Player player;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
player = new Player(100, 100, playerImage);
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
playerImage = Content.Load<Texture2D>("player");
player.Image = playerImage;
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// game-specific content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
// TODO: Add your drawing code here
spriteBatch.Begin();
spriteBatch.Draw(playerImage, new Vector2(0, 0), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Any idea why the sprite is not being displayed?
Thanks
Upon looking at your code again I noticed that base.LoadContent(); is missing in your LoadContent method. If you re-add this it should draw it

spriteBatch is Null

I'm creating a game and for the moment I have 3 classes, greenpaddle, ball, and Game1.
When i run my game, the debugger hops down to my spriteBatch.Begin();
and says NullReferenceException Unhandled.
This is my Game1.cs:
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Ball ball;
GreenPaddle gPaddle;
Texture2D BackGround;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = 500;
}
protected override void Initialize()
{
gPaddle = new GreenPaddle();
ball = new Ball(gPaddle);
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
BackGround = Content.Load<Texture2D>("pongBG");
gPaddle.LoadContent(Content);
ball.LoadContent(Content);
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
gPaddle.Update(gameTime);//Error Line
ball.Update(gameTime);
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();//Error Line
spriteBatch.Draw(BackGround, new Vector2(0f, 0f), Color.White);
gPaddle.Draw(spriteBatch);
ball.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
Don't know what's wrong, this have never happened to me.
Because you initialized spritebatch...
spriteBatch = new SpriteBatch(GraphicsDevice);
...It shouldn't be null unless one of your other classes is changing it.
Things you can try:
-Put a breakpoint on it in load content, I don't know why it wouldn't be called, but just check in case, make sure that LoadContent() is being called.
-Rebuild you project and make sure your changes are being saved.
...As I was writing this answer and testing the code on my machine I finally found the error. I'll leave the advice above in case anyone else has one of those issues.
You are not calling base.Initialize in your Initialize() method. This method calls the internal XNA stuff, which results in your LoadContent() being called.
It is also a good idea to call base.LoadContent in the LoadContent() method, you should always call the base method on any overridden method.

Can't get an Awesomium render onto the screen in XNA

I'm currently using this code that someone recommended to combine Awesomium and XNA, however I'm having an issue... Whenever I try to draw the resulting Texture2d the component gives me, I get:
You may not call SetData on a resource while it is actively set on the GraphicsDevice. Unset it from the device before calling SetData.
Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Awesomium.Core;
namespace ProjectTest
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
AwesomiumComponent uiHud;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
Rectangle rect = new Rectangle(100, 100, 500, 500);
uiHud = new AwesomiumComponent(this, rect);
this.Components.Add(uiHud);
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
uiHud.WebView.LoadURL("http://www.google.com/");
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
//uiHud.Update(gameTime);
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
Vector2 pos = new Vector2(10, 10);
spriteBatch.Begin();
spriteBatch.Draw(uiHud.WebViewTexture, pos, Color.White);
spriteBatch.End();
//uiHud.Draw(gameTime);
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
What exactly am I doing wrong?
Your SpriteBatch is setting the web texture into the graphics device's first texture stage and never unsetting it. This is causing Awesomium's Draw() method to fail, because it's trying to call SetData() on a texture that's still in use.
After spriteBatch.End(), unset the texture stage:
GraphicsDevice.Textures[0] = null;

lander of game, not landing on the landing pad but passing through

i want to get the lander of this xna game to successfully touchdown on the landing pad, and then play the sound, however, it passes right through and the sound still plays. the complete code for this is:
namespace MoonLander
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class BasicLunarLander : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SoundEffectInstance EndGameSoundInstance;
Texture2D BackgroundImage;
Texture2D LandingImage;
SoundEffect EndGameSound;
int LanderPosX;
int LanderPosY;
Texture2D LandingPadImage;
public BasicLunarLander()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
LanderPosX = 100;
LanderPosY = 0;
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
BackgroundImage = Content.Load<Texture2D>("background");
LandingImage = Content.Load<Texture2D>("lander");
LandingPadImage = Content.Load<Texture2D>("landingpad");
EndGameSound = Content.Load<SoundEffect>("crowdcheer");
EndGameSoundInstance = EndGameSound.CreateInstance();
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
LanderPosY = LanderPosY + 2;
}
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
LanderPosY = LanderPosY - 2;
}
if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
LanderPosX = LanderPosX - 2;
}
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
LanderPosX = LanderPosX + 2;
}
// TODO: Add your update logic here
Rectangle rectLander = new Rectangle(LanderPosX, LanderPosY, LandingImage.Width, LandingImage.Height);
Rectangle rectLandingPad = new Rectangle(350, 500, LandingPadImage.Width, LandingPadImage.Height);
if (rectLander.Intersects(rectLandingPad))
{
EndGameSoundInstance.Play();
}
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
// TODO: Add your drawing code here
spriteBatch.Begin();
spriteBatch.Draw(BackgroundImage, Vector2.Zero, Color.White);
spriteBatch.Draw(LandingImage, new Vector2(LanderPosX, LanderPosY), Color.White);
spriteBatch.Draw(LandingPadImage, new Vector2(350,500), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Hope you can help me with this issue, thank you all for your time.
Its because you're not doing anything about preventing movement after the lander has landed (the condition has been met). The sound plays of course, because that is what you did code.
Add a variable detecting if it has landed and declare it inside your class
bool _hasLanded = false;
then wrap the key detection in your update method (for up, down, left and right keys) inside and if:
if(!_hasLanded)
{
//keypresses go here
}
and finally, inside your if where you check to see if the rectangles intersect, add
_hasLanded = true;
That should prevent you from being able to move the lander once it has touched the landing pad.

Categories