[PR]
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
プログラミング、3DCGとその他いろいろについて
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
float4x4 World;
float4x4 View;
float4x4 Projection;
struct VertexShaderInput
{
float4 Position : POSITION0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float DistanceFromCamera : TEXCOORD0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.DistanceFromCamera = output.Position.z;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
return input.DistanceFromCamera;
}
technique Technique1
{
pass Pass1
{
VertexShader = compile vs_1_1 VertexShaderFunction();
PixelShader = compile ps_1_1 PixelShaderFunction();
}
}
シャドウマップを作るシェーダーです。float4x4 World;
float4x4 View;
float4x4 Projection;
texture ShadowMap;
sampler ShadowMapSampler = sampler_state
{
Texture = (ShadowMap);
};
float4x4 LightView;
float4x4 LightProjection;
struct VertexShaderInput
{
float4 Position : POSITION0;
float4 Color : COLOR0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float4 PositionOnShadowMap : TEXCOORD0;
float4 Color : COLOR0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.Color = input.Color;
output.PositionOnShadowMap = mul(
worldPosition,
mul(LightView, LightProjection)
);
return output;
}
bool isLighted(float4 positionOnShadowMap)
{
float2 texCoord;
texCoord.x = (positionOnShadowMap.x / positionOnShadowMap.w + 1) / 2;
texCoord.y = (-positionOnShadowMap.y / positionOnShadowMap.w + 1) / 2;
//誤差があるはずなので、光が当たっているかどうかは
//ほんの少しだけ甘く判定します。
return positionOnShadowMap.z <= tex2D(ShadowMapSampler, texCoord).x + 0.001f;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
if(isLighted(input.PositionOnShadowMap))
return input.Color;
else
return input.Color / 3;
}
technique Technique1
{
pass Pass1
{
VertexShader = compile vs_1_1 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
public class MyGame : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
VertexPositionColor[] triangleVertices = {
new VertexPositionColor(new Vector3(0, 1, 0), Color.White),
new VertexPositionColor(new Vector3(1, 0, 0), Color.Red),
new VertexPositionColor(new Vector3(-1, 0, 0), Color.Blue)
};
Matrix[] triangles = { Matrix.Identity, Matrix.Identity };
Effect effect;
Effect shadowMapCreator;
RenderTarget2D shadowMap;
public MyGame()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
triangles[0] *= Matrix.CreateRotationX(MathHelper.ToRadians(-90));
triangles[0] *= Matrix.CreateTranslation(0, 0, 0.5f);
triangles[0] *= Matrix.CreateScale(3);
triangles[0] *= Matrix.CreateTranslation(0, -4, 0);
triangles[1] *= Matrix.CreateRotationX(MathHelper.ToRadians(-90));
triangles[1] *= Matrix.CreateTranslation(0, 0, 0.5f);
triangles[1] *= Matrix.CreateTranslation(0, -2, 0);
base.Initialize();
}
protected override void LoadContent()
{
GraphicsDevice.VertexDeclaration = new VertexDeclaration(
GraphicsDevice,
VertexPositionColor.VertexElements
);
Matrix lightView = Matrix.CreateLookAt(
new Vector3(0, 1, 0),
new Vector3(),
Vector3.Forward
);
Matrix lightProjection = Matrix.CreateOrthographic(
8, 8,
0.1f, 30
);
shadowMapCreator = Content.Load<Effect>("ShadowMapCreator");
shadowMapCreator.Parameters["View"].SetValue(lightView);
shadowMapCreator.Parameters["Projection"].SetValue(lightProjection);
effect = Content.Load<Effect>("DrawUsingShadowMap");
effect.Parameters["View"].SetValue(
Matrix.CreateLookAt(
new Vector3(0, 1, 8),
new Vector3(),
Vector3.Up
)
);
effect.Parameters["Projection"].SetValue(
Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(90),
GraphicsDevice.Viewport.AspectRatio,
0.1f, 100
)
);
effect.Parameters["LightView"].SetValue(lightView);
effect.Parameters["LightProjection"].SetValue(lightProjection);
shadowMap = new RenderTarget2D(
GraphicsDevice,
512, 512,
1,
SurfaceFormat.Single
);
}
protected override void UnloadContent()
{
shadowMap.Dispose();
}
protected override void Draw(GameTime gameTime)
{
initShadowMap();
GraphicsDevice.Clear(Color.CornflowerBlue);
effect.Parameters["ShadowMap"].SetValue(shadowMap.GetTexture());
foreach (Matrix triangleTransform in triangles)
{
effect.Parameters["World"].SetValue(triangleTransform);
effect.Begin();
effect.CurrentTechnique.Passes[0].Begin();
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
PrimitiveType.TriangleList,
triangleVertices,
0,
1
);
effect.CurrentTechnique.Passes[0].End();
effect.End();
}
base.Draw(gameTime);
}
private void initShadowMap()
{
GraphicsDevice.SetRenderTarget(0, shadowMap);
GraphicsDevice.Clear(Color.White);
foreach (Matrix triangleTransform in triangles)
{
shadowMapCreator.Parameters["World"].SetValue(triangleTransform);
shadowMapCreator.Begin();
shadowMapCreator.CurrentTechnique.Passes[0].Begin();
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
PrimitiveType.TriangleList,
triangleVertices,
0,
1
);
shadowMapCreator.CurrentTechnique.Passes[0].End();
shadowMapCreator.End();
}
GraphicsDevice.SetRenderTarget(0, null);
}
static void Main(string[] args)
{
using (MyGame game = new MyGame())
{
game.Run();
}
}
}