This is a continuation of a solved post here [Solved]How would one render the screen to just a portion of a rendertarget ?
It was sort of off topic in the other thread.
I still have some questions on how to render this rendercube to a actual quad cube.
Do i set the light position to be the center of a quad cube and then get the rendered scene texels to do reflection mapping onto a cube ? Id like to also be able to colorize the depth and display it in that way onto a cube for visualization and to make sure it looks proper.
Anyways i got it running i have no idea how bugged up this really is till i get a better scene in there im tired so itll have to wait. But it appears to be doing some shadowing.
Gray is the shadow color in the below picture. So it’s at least partialy working.
Here’s my code so far minus the helper class with the grid.
Game1 and Shader
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace TestTextureCube
{
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
// whats the difference here what does the textureCube do exactly
TextureCube textureCube;
// i get the rendertargetCube
RenderTargetCube renderTargetCube;
//
Effect effect;
//
float near = 1.0f;
float far = 1000f;
Matrix world, view, projection;
Matrix worldGrid, worldCamera, worldLight, worldObj1, worldObj2;
Vector3 worldGridPosition, worldCameraPosition, worldLightPosition, worldObj1Position, worldObj2Position;
// something to draw
Grid3dOrientation grid = new Grid3dOrientation(30, 30, .001f);
// 2.0 is screen scale with a wvp identity matrix.
Quad quad = new Quad(1.7f);
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = this.LoadBasics("Shadow Cube test");
effect = Content.Load<Effect>("EffectCubeMap");
textureCube = new TextureCube(GraphicsDevice, 6, false, SurfaceFormat.Single);
renderTargetCube = new RenderTargetCube(GraphicsDevice, 256, false, SurfaceFormat.Single, DepthFormat.Depth24);
effect.Parameters["farPlane"].SetValue(far);
world = Matrix.Identity;
SetView(world);
projection = Matrix.CreatePerspectiveFieldOfView((float)MathHelper.Pi * .5f, GraphicsDevice.Viewport.Width / GraphicsDevice.Viewport.Height, near, far);
worldLightPosition = new Vector3(3f, .1f, -.5f);
worldLight = CreateWorldToTarget(worldLightPosition, Vector3.Zero, Vector3.Up);
worldGridPosition = Vector3.Zero;
worldGrid = Matrix.CreateScale(30f) * Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up);
worldCameraPosition = new Vector3(.5f, -.5f, 2f);
worldCamera = CreateWorldToTarget(worldCameraPosition, Vector3.Zero, Vector3.Up);
}
protected override void UnloadContent()
{
this.UnloadBasics();
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
//BasicStuff.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
GraphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, 1, 0);
GraphicsDevice.RasterizerState = new RasterizerState() { FillMode = FillMode.Solid, CullMode = CullMode.None };
GraphicsDevice.DepthStencilState = new DepthStencilState() { DepthBufferEnable = true, DepthBufferFunction = CompareFunction.LessEqual };
// ok so lets take a look
effect.CurrentTechnique = effect.Techniques["CreateLightShadowCubeDepth"];
// well set a rendertarget to prepare for drawing
// we set our own view matrix to match at the light shadow location.
// we draw some stuff to a depth buffer.
GraphicsDevice.SetRenderTarget(renderTargetCube, CubeMapFace.NegativeX);
SetViewToLight(worldLightPosition, Vector3.Left);
DrawGridToDepth();
GraphicsDevice.SetRenderTarget(renderTargetCube, CubeMapFace.NegativeY);
SetViewToLight(worldLightPosition, Vector3.Down);
DrawGridToDepth();
GraphicsDevice.SetRenderTarget(renderTargetCube, CubeMapFace.NegativeZ);
SetViewToLight(worldLightPosition, Vector3.Forward);
DrawGridToDepth();
GraphicsDevice.SetRenderTarget(renderTargetCube, CubeMapFace.PositiveX);
SetViewToLight(worldLightPosition, Vector3.Right);
DrawGridToDepth();
GraphicsDevice.SetRenderTarget(renderTargetCube, CubeMapFace.PositiveY);
SetViewToLight(worldLightPosition, Vector3.Up);
DrawGridToDepth();
GraphicsDevice.SetRenderTarget(renderTargetCube, CubeMapFace.PositiveZ);
SetViewToLight(worldLightPosition, Vector3.Backward);
DrawGridToDepth();
// definately going to need a octree too.
// Ok so we have our depths in this rendertarget cube.
// I want to draw with the shadowing.
// So on this calculation side, im guessing it just does the math and thats the attraction.
// i suppose i can get data on this thing if i want to see it flattened out.
// switch to backbuffer
GraphicsDevice.SetRenderTarget(null);
// we switch our view now to our actual camera and draw our scene with shadow.... but...
effect.CurrentTechnique = effect.Techniques["LightShadowCubeBasicShader"];
effect.Parameters["worldLightPosition"].SetValue(worldLightPosition);
SetView(worldCamera);
effect.Parameters["WorldViewProjection"].SetValue(GetWvp());
DrawGridWithShadow();
BasicStuff.Draw();
base.Draw(gameTime);
}
// yes its wasteful i just want a working test for now.
void DrawGridToDepth()
{
SetWorld(worldGrid);
effect.Parameters["lightsPovWorldViewProjection"].SetValue(GetWvp());
grid.Draw(GraphicsDevice, effect, 0);
grid.Draw(GraphicsDevice, effect, 1);
grid.Draw(GraphicsDevice, effect, 2);
}
void DrawGridWithShadow()
{
SetWorld(worldGrid);
effect.Parameters["lightsPovWorldViewProjection"].SetValue(GetWvp());
effect.Parameters["TextureB"].SetValue(renderTargetCube);
effect.Parameters["TextureA"].SetValue(BasicTextures.red);
grid.Draw(GraphicsDevice, effect, 0);
effect.Parameters["TextureA"].SetValue(BasicTextures.green);
grid.Draw(GraphicsDevice, effect, 1);
effect.Parameters["TextureA"].SetValue(BasicTextures.blue);
grid.Draw(GraphicsDevice, effect, 2);
}
void SetWorld(Matrix world)
{
this.world = world;
}
void SetView(Matrix worldForCamera)
{
var m = worldForCamera;
view = Matrix.CreateLookAt(m.Translation, m.Forward + m.Translation, m.Up);
}
Matrix GetWvp()
{
return world * view * projection;
}
void SetViewToLight(Vector3 shadowCubePosition, Vector3 direction)
{
Matrix m = Matrix.CreateWorld(shadowCubePosition, direction, Vector3.Up);
view = Matrix.CreateLookAt(m.Translation, 10f * m.Forward + m.Translation, m.Up);
}
Matrix CreateWorldToTarget(Vector3 position, Vector3 targetPosition, Vector3 up)
{
return Matrix.CreateWorld(position, targetPosition - position, up);
}
}
}
Shader.
//
//EffectCubeMap.fx
//
#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
//_______________________
// Common Functions
// Calculate depth
float CalculateLightDepth(float pz, float farPlaneValue)
{
float result = farPlaneValue - pz;
return result;
}
// encode 3
float3 EncodeFloatRGB(float f)
{
float3 color;
f *= 256;
color.x = floor(f);
f = (f - color.x) * 256;
color.y = floor(f);
color.z = f - color.y;
color.xy *= 0.00390625; // *= 1.0/256
return color;
}
// decode 3
float DecodeFloatRGB(float3 color)
{
const float3 byte_to_float = float3(1.0, 1.0 / 256, 1.0 / (256 * 256));
return dot(color, byte_to_float);
}
// _______________________
// texture samplers.
Texture TextureA;
Texture TextureB;
sampler TextureSamplerA = sampler_state
{
texture = <TextureA>;
//magfilter = LINEAR; //minfilter = LINEAR; //mipfilter = LINEAR; //AddressU = mirror; //AddressV = mirror;
};
sampler TextureSamplerB = sampler_state
{
texture = <TextureB>;
//magfilter = LINEAR; //minfilter = LINEAR; //mipfilter = LINEAR; //AddressU = mirror; //AddressV = mirror;
};
//_______________________
// specifics
matrix World;
matrix View;
matrix Projection;
matrix WorldViewProjection;
matrix lightsPovWorldViewProjection;
float3 worldLightPosition;
float farPlane;
//__________________
// Shaders begin now _
// _________________
//
//_______________________________________________________________
// techniques Create depth texture
//_______________________________________________________________
//
struct VsInputCalcSceneDepth
{
float4 Position : POSITION0;
float2 TexCoords : TEXCOORD0;
};
struct VsOutputCalcSceneDepth
{
float4 Position : SV_Position;
float4 Position2D : TEXCOORD0;
};
struct PsOutputCalcSceneDepth
{
float4 Color : COLOR0;
};
// ______
// Shader.
//
VsOutputCalcSceneDepth CreateDepthMapVertexShader(VsInputCalcSceneDepth input)//(float4 inPos : POSITION)
{
VsOutputCalcSceneDepth Output;
Output.Position = mul(input.Position, lightsPovWorldViewProjection);
// might need to get changed
Output.Position2D = Output.Position;
return Output;
}
//
// I guess we set the render cube side in code so.
// Ok so were going to use the old calculation i guess.
// How does the perspective matrix align with this.
//
PsOutputCalcSceneDepth CreateDepthMapPixelShader(VsOutputCalcSceneDepth input)
{
PsOutputCalcSceneDepth Output;
// ABS ?
float lightDepth = CalculateLightDepth(input.Position2D.z, farPlane);
float3 temp = EncodeFloatRGB(lightDepth); // 24 bit depth
float4 result = float4(temp.r, temp.g, temp.b, 1.0f);
Output.Color = result;
return Output;
}
//_________
// techniques
technique CreateLightShadowCubeDepth
{
pass Pass0
{
VertexShader = compile VS_SHADERMODEL CreateDepthMapVertexShader();
PixelShader = compile PS_SHADERMODEL CreateDepthMapPixelShader();
}
}
//_______________________________________________________________
// techniques DrawLightOrShadow
//_______________________________________________________________
struct VsInLightShadow
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float2 TexureCoordinateA : TEXCOORD0;
};
struct VsOutLightShadow
{
float4 Position : SV_Position;
float2 TexureCoordinateA : TEXCOORD0;
float4 Position2D : TEXCOORD1;
};
struct PsOutLightShadow
{
float4 Color : COLOR0;
};
//_______
// shaders
//
VsOutLightShadow VsLightShadow(VsInLightShadow input)
{
VsOutLightShadow output;
output.Position = mul(input.Position, WorldViewProjection); // basically matrix identity
output.TexureCoordinateA = input.TexureCoordinateA;
output.Position2D = output.Position;
return output;
}
PsOutLightShadow PsLightShadow(VsOutLightShadow input)
{
PsOutLightShadow output;
output.Color = tex2D(TextureSamplerA, input.TexureCoordinateA); // *input.Color;
// ok i think i need to mult the worldLightPosition its really in world space atm.
float3 lightpos = mul(worldLightPosition, WorldViewProjection);
float3 dir = input.Position2D - lightpos; //worldLightPosition
// promlem is i dunno what texcobe does under the hood.
float shadowDepth = DecodeFloatRGB(texCUBE(TextureSamplerB, dir).xyz);
// texCUBE(TextureSamplerB, float4(dir, 0)).x;
if (shadowDepth > input.Position2D.z)
output.Color = float4(0.7f, 0.7f, 0.7f, 1.0f); // light gray
return output;
}
//_________
// techniques
technique LightShadowCubeBasicShader
{
pass
{
VertexShader = compile VS_SHADERMODEL VsLightShadow();
PixelShader = compile PS_SHADERMODEL PsLightShadow();
}
}