SuperNoob needs help: advanced lighting in xna

deeFive

Newcomer
so i'm still working on my xna project and i have run in to problem when drawing a directional light in xna using deffered rendering, here is the code from the directionalLight.fx:

i'm still wroking with deffered rendering

float4x4 World;
float4x4 View;
float4x4 Projection;
//direction of the light
float3 lightDirection;
//color of the light
float3 Color;
//position of the camera, for specular light
float3 cameraPosition;
//this is used to compute the world-position
float4x4 InvertViewProjection;

//diffuse color, and specularIntensity in the alpha channel
texture colorMap;
//normals, and specularPower in the alpha channel
texture normalMap;
//depth
texture depthMap;

sampler colorSampler = sampler_state
{
Texture = (colorMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = POINT;
MinFilter = POINT;
MipFilter = POINT;
};

sampler depthSampler = sampler_state
{
Texture = (depthMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = POINT;
MinFilter = POINT;
MipFilter = POINT;
};

sampler normalSampler = sampler_state
{
Texture = (normalMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = POINT;
MinFilter = POINT;
Mipfilter = POINT;
};

struct VertexShaderInput
{
float3 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};

float2 halfPixel;

VertexShaderOutput VertexShaderFuction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position = float4(input.Position,1);
//align texture coordinates
output.TexCoord = input.TexCoord - halfPixel;
return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
//get the normal data from the normalMap
float4 normalData = tex2D(normalSampler,input.TexCoord);
//tranForm the normals back into [-1,1} range
float3 normal = 2.0f * normalData.xyz - 1.0f;
//get specular power, and get it into [0,255] range
float specularPower = normalData.a * 255;
//get specular intensity from the colorMap
float specularIntensity = tex2D(colorSampler,input.TexCoord).a;

//read depth
float depthVal = tex2D(depthSampler,input.TexCoord).r;

//compute screen-space position
float4 position;
position.x = input.TexCoord.x * 2.0f - 1.0f;
position.y = -(input.TexCoord.x * 2.0f - 1.0f);
position.z = depthVal;
position.w = 1.0f;

//transform to world space
position = mul(position, InvertViewProjection);
position /= position.w;

//surface-to-light vector
float3 lightVector = -normalize(lightDirection);

//compute diffuse light
float NdL = max(0,dot(normal,lightVector));
float3 diffuseLight = NdL * Color.rgb;

//reflexion vector
float3 reflectionVector = normalize(reflect(lightVector, normal));

//camera-to-surface vector
float3 directionToCamera = normalize(cameraPosition - position);

//compute specular light
float specularLight = specularIntensity * pow( saturate(dot(reflectionVector, directionToCamera)), specularPower);

//output the two lights
return float4(diffuseLight.rgb, specularLight);
}

technique Technique0
{
pass Pass0
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}

the plan is to slowly evole my on renderer over the next 2t o 6 months then start working on gameplay or scene management not sure which yet.

another quick question does anyone know how to import and compile .fx file into GPU-ShaderAnalyser ver1.42 or does anybody know any noob friendly shader compilers


thanks in advance



d'
 
You haven't said what exactly you need help with:

What are you seeing onscreen if anything?

Do you have any other lighting modes working?

Have you tried rendering your g-buffers directly to check they contain what you expect?

I notice you're outputing the specular to alpha, do you have another render pass that actually uses it?

Have you set 'halfpixel' in your code?

More info required...
 
sorry i posted as i was leaving for work, the error that i'm getting is

error X3004: undeclared identifier 'VertexShaderFunction'

and yes halfpixel is in the main code

again thanks in advance



d'
 
More issues.......

So, i continued to code and have got 3 directional lights to work but when i try to blend them with the color data, via a pixel shader i only get a white screen:

defferred render code

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;
using DeferredShadingTutorial;

namespace DCP_Step_0
{
/// <summary>
/// This is a game component that implements IUpdateable.
/// </summary>
public class DeferredRenderer : Microsoft.Xna.Framework.DrawableGameComponent
{
//code to load the camera component
private Camera camera;
//code to load the quadRenderer component
private QuadRenderComponent quadRenderer;
//code to load the Scene component
private Scene scene;
//this Render Target (RT) will hold the color (albdeo, diffuse responce) and the Specular Intensity data
private RenderTarget2D colorRT;
//this RT will hold the normal data and the Specular Power data
private RenderTarget2D normalRT;
//this RT will hold the depth data
private RenderTarget2D depthRT;
//this RT will hold the light data
private RenderTarget2D lightRT;
//code to load the ClearGBuffer component
private Effect clearBufferEffect;
//code to load the SpriteBatch component
private SpriteBatch spriteBatch;
//code to load the half pixel componet
private Vector2 halfPixel;
//code to load the directionalLight component
private Effect directionalLightEffect;
//code to load the CombineFinal component
private Effect finalCombineEffect;


public DeferredRenderer(Game game)
: base(game)
{
// TODO: Construct any child components here

scene = new Scene(game);
}

/// <summary>
/// Allows the game component to perform any initialization it needs to before starting
/// to run. This is where it can query for any required services and load content.
/// </summary>
public override void Initialize()
{
// TODO: Add your initialization code here

base.Initialize();
camera = new Camera(Game);
quadRenderer = new QuadRenderComponent(Game);

Game.Components.Add(camera);

Game.Components.Add(quadRenderer);
}

protected override void LoadContent()
{
halfPixel.X = 0.5f / (float)GraphicsDevice.PresentationParameters.BackBufferWidth;
halfPixel.Y = 0.5f / (float)GraphicsDevice.PresentationParameters.BackBufferHeight;
scene.InitializeScene();

//retrive the sizes of the backbuffer, in order to have matching render targets
int backBufferWidth = GraphicsDevice.PresentationParameters.BackBufferWidth;
int backBufferHeight = GraphicsDevice.PresentationParameters.BackBufferHeight;

colorRT = new RenderTarget2D(GraphicsDevice, backBufferWidth, backBufferHeight, 1, SurfaceFormat.Color);
normalRT = new RenderTarget2D(GraphicsDevice, backBufferWidth, backBufferHeight, 1, SurfaceFormat.Color);
depthRT = new RenderTarget2D(GraphicsDevice, backBufferWidth, backBufferHeight, 1, SurfaceFormat.Single);
lightRT = new RenderTarget2D(GraphicsDevice, backBufferWidth, backBufferHeight, 1, SurfaceFormat.Color);


clearBufferEffect = Game.Content.Load<Effect>("ClearGBuffer");
directionalLightEffect = Game.Content.Load<Effect>("DirectionalLight");
finalCombineEffect = Game.Content.Load<Effect>("CombineFinal");
spriteBatch = new SpriteBatch(Game.GraphicsDevice);
base.LoadContent();
}

private void SetGBuffer()
{
GraphicsDevice.SetRenderTarget(0, colorRT);
GraphicsDevice.SetRenderTarget(1, normalRT);
GraphicsDevice.SetRenderTarget(2, depthRT);
}

private void ResolveGBuffer()
{
//we first have to set all rendertargets to null. in XNA 2.0, switching RT
//causes the resolving of the previous RT, in XNA 1.1, we needed th call
//GraphicsDevice.ResolveRenderTarget(i);
GraphicsDevice.SetRenderTarget(0, null);
GraphicsDevice.SetRenderTarget(1, null);
GraphicsDevice.SetRenderTarget(2, null);
}

private void ClearGBuffer()
{
clearBufferEffect.Begin();
clearBufferEffect.Techniques[0].Passes[0].Begin();
quadRenderer.Render(Vector2.One * -1, Vector2.One);
clearBufferEffect.Techniques[0].Passes[0].End();
clearBufferEffect.End();
}

private void DrawDirectionalLight(Vector3 lightDirection, Color color)
{
//set all parameters
directionalLightEffect.Parameters["colorMap"].SetValue(colorRT.GetTexture());
directionalLightEffect.Parameters["normalMap"].SetValue(normalRT.GetTexture());
directionalLightEffect.Parameters["depthMap"].SetValue(depthRT.GetTexture());
directionalLightEffect.Parameters["lightDirection"].SetValue(lightDirection);
directionalLightEffect.Parameters["Color"].SetValue(color.ToVector3());
directionalLightEffect.Parameters["InvertViewProjection"].SetValue(Matrix.Invert(camera.View * camera.Projection));
directionalLightEffect.Parameters["halfPixel"].SetValue(halfPixel);

directionalLightEffect.Begin();
directionalLightEffect.Techniques[0].Passes[0].Begin();
//draw a full-screen quad
quadRenderer.Render(Vector2.One * -1, Vector2.One);
directionalLightEffect.Techniques[0].Passes[0].End();
directionalLightEffect.End();
}

private void DrawLights(GameTime gameTime)
{
GraphicsDevice.SetRenderTarget(0, lightRT);

//clear all components to 0
GraphicsDevice.Clear(Color.TransparentBlack);
GraphicsDevice.RenderState.AlphaBlendEnable = true;
//use additive blending, and make sure the blending factors are as we need them to be set
GraphicsDevice.RenderState.AlphaBlendOperation = BlendFunction.Add;
GraphicsDevice.RenderState.SourceBlend = Blend.One;
GraphicsDevice.RenderState.DestinationBlend = Blend.One;
//use the same operation on the alpha channel
GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = false;

//draw a few lights
DrawDirectionalLight(new Vector3(0, -1, 0), Color.White);
DrawDirectionalLight(new Vector3(-1, 0, 0), Color.Crimson);
DrawDirectionalLight(new Vector3(1, 0, 0), Color.SkyBlue);

GraphicsDevice.RenderState.AlphaBlendEnable = false;

GraphicsDevice.SetRenderTarget(0, null);

//set the effect parameters
finalCombineEffect.Parameters["colorMap"].SetValue(colorRT.GetTexture());
finalCombineEffect.Parameters["lightMap"].SetValue(lightRT.GetTexture());
finalCombineEffect.Parameters["halfPixel"].SetValue(halfPixel);

finalCombineEffect.Begin();
finalCombineEffect.Techniques[0].Passes[0].Begin();

//render a full-screen quad
quadRenderer.Render(Vector2.One * -1, Vector2.One);

finalCombineEffect.Techniques[0].Passes[0].End();
finalCombineEffect.End();


}


public override void Draw(GameTime gameTime)
{
SetGBuffer();
GraphicsDevice.Clear(Color.Gray);
scene.DrawScene(camera, gameTime);
ResolveGBuffer();
DrawLights(gameTime);
base.Draw(gameTime);
}
/// <summary>
/// Allows the game component to update itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public override void Update(GameTime gameTime)
{
// TODO: Add your update code here

base.Update(gameTime);
}
}
}

and the final combine code

texture colorMap;
texture lightMap;

sampler colorSampler = sampler_state
{
Texture = (colorMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = LINEAR;
MinFilter = LINEAR;
MipFilter = LINEAR;
};

sampler lightSampler = sampler_state
{
Texture = (lightMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = LINEAR;
MinFilter = LINEAR;
MipFilter = LINEAR;
};


struct VertexShaderInput
{
float3 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};

float2 halfPixel;

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position = float4(input.Position,1);
output.TexCoord = input.TexCoord - halfPixel;
return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float3 diffuseColor = tex2D(colorSampler,input.TexCoord).rgb;
float4 light = tex2D(lightSampler,input.TexCoord);
float3 diffuseLight = light.rgb;
float specularLight = light.a;
return float4((diffuseColor * diffuseLight + specularLight),1);
}

technique Technique1
{
pass Pass1
{
// TODO: set renderstates here.

VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}

again when i debug i only get a white screen, but i dont get any errors

thanks in adavnce



d'
 
Last edited by a moderator:
Back
Top