| Topic: Deferred rendering issue in XNA 4
|
|
 | Deferred rendering issue in XNA 4 | |  |
| Poster | : stownend | | Posts | : 2 | | Country | : England | | City | : York |
| | | | Posted by stownend on 08/03/2012 at 11:57:20
| | Hi,
I have followed your book and created an XNA 4 version of recipe 6-11 that works fine for a single light. However when I add another light I get an error on the line within the function "AddLight" where it sets the value of xPreviousShadingContents to the shadingMap created by the previous light.
The error is "The render target must not be set on the device when it is used as a texture".
I guess this is one of the many differences between XNA 2 and XNA 4 when using RenderTargets. I have resolved all of the other issues but cannot find a workaround for this one.
Any ideas?
Regards,
Steve. | |
|
| | | | | | Poster | : stownend | | Posts | : 2 | | Country | : England | | City | : York |
| | | | Posted by stownend on 08/03/2012 at 16:18:28
| | Ok, I found the answer :-)
Basically rather than using the same RenderTarget for each light, you need to alternate between 2 RenderTargets eg:-
// This fix enables re-using a RenderTarget
// texture in XNA 4. You have to swap between 2
// RenderTargets rather than just using 1
if (currentShadingTarget == 0)
{
device.SetRenderTarget(shadingTarget);
currentShadingTarget = 1;
}
else
{
device.SetRenderTarget(shadingTarget2);
currentShadingTarget = 0;
}
This is not very elegant but seems to work. | |
|
| | | | | | Poster | : Anonymous | | Posts | : | | Country | : | | City | : |
| | | | Posted by Anonymous on 23/04/2012 at 10:25:22
| | Hi stownend
Would it be possible for you to post your XNA 4.0 code?
I've been attempting to convert the deferred shading code myself without success - The lights display, but look very funky.
Being able to see some correctly updated code would help enormously!
Many thanks! | |
|
| | | | | | Poster | : Anonymous | | Posts | : | | Country | : | | City | : |
| | | | Posted by Anonymous on 25/04/2012 at 11:45:41
| | In case anyone can help;
Here are a couple of images of the issue I'm experiencing;


A zip of the entire project can be found here;
https://skydrive.live.com/redir.aspx?cid=373793b21a237ab3&resid=373793B21A237AB3!138&parid=root
The source 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 Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace _6_11_Deferred_Shadow_Mapping
{
public struct SpotLight
{
public Vector3 Position;
public float Strength;
public Vector3 Direction;
public float ConeAngle;
public float ConeDecay;
public Matrix ViewMatrix;
public Matrix ProjectionMatrix;
}
public partial class Game1 : Microsoft.Xna.Framework.Game
{
const int NumberOfLights = 6;
GraphicsDeviceManager graphics;
GraphicsDevice device;
QuakeCamera fpsCam;
Effect effect1Scene;
Effect effect2Lights;
Effect effect3Final;
Effect effectShadowMap;
VertexPositionTexture[] fsVertices;
VertexPositionNormalTexture[] wallVertices;
VertPosTexNormTan[] towerVertices;
int[] towerIndices;
RenderTarget2D colorTarget;
RenderTarget2D normalTarget;
RenderTarget2D depthTarget;
RenderTarget2D shadingTarget;
RenderTarget2D shadingTarget2;
RenderTarget2D shadowTarget;
Texture2D colorMap;
Texture2D normalMap;
Texture2D depthMap;
Texture2D shadingMap;
Texture2D shadowMap;
Texture2D blackImage;
Texture2D wallTexture;
SpotLight[] spotLights;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
//fpsCam = new QuakeCamera(GraphicsDevice.Viewport, new Vector3(0.0f, 40.0f, 60.0f), 0, -MathHelper.Pi / 6.0f);
fpsCam = new QuakeCamera(GraphicsDevice.Viewport, new Vector3(6.0f, 4.0f, 4.0f), 0, -MathHelper.Pi / 30.0f);
spotLights = new SpotLight[NumberOfLights];
base.Initialize();
}
protected override void LoadContent()
{
device = graphics.GraphicsDevice;
effect1Scene = Content.Load<Effect>("Deferred1Scene");
effect2Lights = Content.Load<Effect>("Deferred2Lights");
effect3Final = Content.Load<Effect>("Deferred3Final");
effectShadowMap = Content.Load<Effect>("ShadowMap");
PresentationParameters pp = device.PresentationParameters;
int width = pp.BackBufferWidth;
int height = pp.BackBufferHeight;
colorTarget = new RenderTarget2D(device, width, height, false, SurfaceFormat.Color, DepthFormat.Depth24);
normalTarget = new RenderTarget2D(device, width, height, false, SurfaceFormat.Color, DepthFormat.None);
depthTarget = new RenderTarget2D(device, width, height, false, SurfaceFormat.Single, DepthFormat.None);
shadingTarget = new RenderTarget2D(device, width, height, false, SurfaceFormat.Color, DepthFormat.None);
shadingTarget2 = new RenderTarget2D(device, width, height, false, SurfaceFormat.Color, DepthFormat.None);
shadowTarget = new RenderTarget2D(device, width, height, false, SurfaceFormat.Single, DepthFormat.None);
blackImage = new Texture2D(device, width, height, false, SurfaceFormat.Color);
wallTexture = Content.Load<Texture2D>("wall");
InitSceneVertices();
InitFullscreenVertices();
towerVertices = InitTowerVertices();
towerIndices = InitTowerIndices(towerVertices);
towerVertices = GenerateNormalsForTriangleList(towerVertices, towerIndices);
}
private void InitFullscreenVertices()
{
fsVertices = new VertexPositionTexture[4];
int i = 0;
fsVertices[i++] = new VertexPositionTexture(new Vector3(-1, 1, 0f), new Vector2(0, 0));
fsVertices[i++] = new VertexPositionTexture(new Vector3(1, 1, 0f), new Vector2(1, 0));
fsVertices[i++] = new VertexPositionTexture(new Vector3(-1, -1, 0f), new Vector2(0, 1));
fsVertices[i++] = new VertexPositionTexture(new Vector3(1, -1, 0f), new Vector2(1, 1));
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
if (gamePadState.Buttons.Back == ButtonState.Pressed)
this.Exit();
MouseState mouseState = Mouse.GetState();
KeyboardState keyState = Keyboard.GetState();
fpsCam.Update(mouseState, keyState, gamePadState);
//---
//update lights
float coneAngle = MathHelper.PiOver4;
float time = (float)gameTime.TotalGameTime.TotalMilliseconds / 1000.0f;
float sine = (float)Math.Sin(time);
for (int i = 0; i < NumberOfLights; i++)
{
Matrix yRot = Matrix.CreateRotationY(time / 2.0f + (float)i * MathHelper.Pi * 2.0f / (float)NumberOfLights);
Matrix xRot = Matrix.CreateRotationX(-MathHelper.PiOver2 + sine + 0.4f);
Matrix fullRot = xRot * yRot;
Vector3 lightPosition = new Vector3(0.0f, 1.5f, 0.0f) + 5.0f * Vector3.Transform(Vector3.Forward, yRot);
Vector3 lightDirection = Vector3.Transform(Vector3.Forward, fullRot);
Vector3 lightUp = Vector3.Transform(Vector3.Up, fullRot); ;
spotLights[i].Position = lightPosition;
spotLights[i].Strength = 0.4f;
spotLights[i].Direction = lightDirection;
spotLights[i].ConeAngle = (float)Math.Cos(coneAngle);
spotLights[i].ConeDecay = 1.5f;
spotLights[i].ViewMatrix = Matrix.CreateLookAt(lightPosition, lightPosition + lightDirection, lightUp);
float viewAngle = (float)Math.Acos(spotLights[i].ConeAngle);
spotLights[i].ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(coneAngle * 2.0f, 1.0f, 0.5f, 1000.0f);
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
//render color, normal and depth into 3 render targets
RenderSceneTo3RenderTargets();
//Add lighting contribution of each light onto shadingMap
shadingMap = GenerateShadingMap();
//Combine base color map and shading map
CombineColorAndShading();
base.Draw(gameTime);
}
private void RenderSceneTo3RenderTargets()
{
//bind render targets to outputs of pixel shaders
device.SetRenderTargets(colorTarget, normalTarget, depthTarget);
//clear all render targets
device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1, 0);
//render the scene using custom effect that writes to all render targets simultaneously
effect1Scene.CurrentTechnique = effect1Scene.Techniques["MultipleTargets"];
effect1Scene.Parameters["xView"].SetValue(fpsCam.ViewMatrix);
effect1Scene.Parameters["xProjection"].SetValue(fpsCam.ProjectionMatrix);
RenderScene(effect1Scene);
//de-activate render targets to resolve them
device.SetRenderTarget(null);
//copy contents of render targets into texture
colorMap = colorTarget;
normalMap = normalTarget;
depthMap = depthTarget;
}
//first pass - Create image maps
private void RenderScene(Effect effect)
{
//Render room
effect.Parameters["xWorld"].SetValue(Matrix.Identity);
effect.Parameters["xTexture"].SetValue(wallTexture);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleStrip, wallVertices, 0, 14);
}
//Render 9 towers
for (int i = 0; i < 9; i++)
{
Vector3 towerPosition = Vector3.Transform(20.0f * Vector3.Right, Matrix.CreateRotationY(MathHelper.Pi / 8.0f * (float)i));
RenderTower(effect, Matrix.CreateTranslation(towerPosition));
}
}
//second pass - Add lighting
BlendState newBlendState = new BlendState()
{
AlphaBlendFunction = BlendFunction.Add,
AlphaSourceBlend = Blend.One,
AlphaDestinationBlend = Blend.One,
ColorBlendFunction = BlendFunction.Add,
ColorSourceBlend = Blend.One,
ColorDestinationBlend = Blend.One
};
private Texture2D GenerateShadingMap()
{
shadingMap = blackImage;
for (int i = 0; i < NumberOfLights; i++)
{
RenderShadowMap(spotLights[i]);
AddLight(spotLights[i]);
}
//return shadingTarget;
if (currentShadingTarget == 0)
return shadingTarget2;
else
return shadingTarget;
}
private void RenderShadowMap(SpotLight spotLight)
{
device.SetRenderTarget(shadowTarget);
effectShadowMap.CurrentTechnique = effectShadowMap.Techniques["ShadowMap"];
effectShadowMap.Parameters["xView"].SetValue(spotLight.ViewMatrix);
effectShadowMap.Parameters["xProjection"].SetValue(spotLight.ProjectionMatrix);
RenderScene(effectShadowMap);
device.SetRenderTarget(null);
shadowMap = shadowTarget;
}
int currentShadingTarget = 0;
private void AddLight(SpotLight spotLight)
{
//device.SetRenderTarget(shadingTarget);
if (currentShadingTarget == 0)
{
device.SetRenderTarget(shadingTarget);
currentShadingTarget = 1;
}
else
{
device.SetRenderTarget(shadingTarget2);
currentShadingTarget = 0;
}
effect2Lights.CurrentTechnique = effect2Lights.Techniques["DeferredSpotLight"];
effect2Lights.Parameters["xPreviousShadingContents"].SetValue(shadingMap);
effect2Lights.Parameters["xNormalMap"].SetValue(normalMap);
effect2Lights.Parameters["xDepthMap"].SetValue(depthMap);
effect2Lights.Parameters["xShadowMap"].SetValue(shadowMap);
effect2Lights.Parameters["xLightPosition"].SetValue(spotLight.Position);
effect2Lights.Parameters["xLightStrength"].SetValue(spotLight.Strength);
effect2Lights.Parameters["xConeDirection"].SetValue(spotLight.Direction);
effect2Lights.Parameters["xConeAngle"].SetValue(spotLight.ConeAngle);
effect2Lights.Parameters["xConeDecay"].SetValue(spotLight.ConeDecay);
Matrix viewProjInv = Matrix.Invert(fpsCam.ViewMatrix * fpsCam.ProjectionMatrix);
effect2Lights.Parameters["xViewProjectionInv"].SetValue(viewProjInv);
effect2Lights.Parameters["xLightViewProjection"].SetValue(spotLight.ViewMatrix * spotLight.ProjectionMatrix);
foreach (EffectPass pass in effect2Lights.CurrentTechnique.Passes)
{
pass.Apply();
device.SamplerStates[1] = SamplerState.PointClamp; //depthtarget
device.SamplerStates[2] = SamplerState.PointClamp;
//device.SamplerStates[1] = SamplerState.PointWrap;
device.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleStrip, fsVertices, 0, 2);
}
device.SetRenderTarget(null);
if (currentShadingTarget == 0)
shadingMap = shadingTarget2;
else
shadingMap = shadingTarget;
}
//-- third pass - merge the scene
private void CombineColorAndShading()
{
effect3Final.CurrentTechnique = effect3Final.Techniques["CombineColorAndShading"];
effect3Final.Parameters["xColorMap"].SetValue(colorMap);
effect3Final.Parameters["xShadingMap"].SetValue(shadingMap);
effect3Final.Parameters["xAmbient"].SetValue(0.3f);
foreach (EffectPass pass in effect3Final.CurrentTechnique.Passes)
{
pass.Apply();
device.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleStrip, fsVertices, 0, 2);
}
}
private void RenderTower(Effect effect, Matrix worldMatrix)
{
effect.Parameters["xWorld"].SetValue(worldMatrix);
effect.Parameters["xTexture"].SetValue(wallTexture);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
device.DrawUserPrimitives<VertPosTexNormTan>(PrimitiveType.TriangleStrip, towerVertices, 0, towerVertices.Length - 2);
}
}
}
}
|
| |
|
| | | | | | Poster | : Anonymous | | Posts | : | | Country | : | | City | : |
| | | | Posted by Anonymous on 25/04/2012 at 11:47:03
| | Since those image links didn't work; here are the links...
Image1:
https://skydrive.live.com/redir.aspx?cid=373793b21a237ab3&resid=373793B21A237AB3!136&parid=root
Image2:
https://skydrive.live.com/redir.aspx?cid=373793b21a237ab3&resid=373793B21A237AB3!137&parid=root | |
|
|
 | | |  |
|
|
|
If you appreciate the amount of time I spend creating and updating these pages, feel free to donate -- any amount is welcome !
|
- Website design & DirectX code : Riemer Grootjans - ©2006 Riemer Grootjans
|
|