point light sphere optimization

mesh_sprite_draw
cosmonaut 2020-12-09 16:10:53 -08:00
parent 2c113ed642
commit 0060c22d72
9 changed files with 119 additions and 13 deletions

View File

@ -18,6 +18,8 @@ namespace Kav
EffectParameter farPlaneParam; EffectParameter farPlaneParam;
EffectParameter worldViewProjectionParam;
public Texture2D GPosition { get; set; } public Texture2D GPosition { get; set; }
public Texture2D GAlbedo { get; set; } public Texture2D GAlbedo { get; set; }
public Texture2D GNormal { get; set; } public Texture2D GNormal { get; set; }
@ -31,6 +33,42 @@ namespace Kav
public float FarPlane { get; set; } public float FarPlane { get; set; }
Matrix world = Matrix.Identity;
Matrix view = Matrix.Identity;
Matrix projection = Matrix.Identity;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
public Matrix World
{
get { return world; }
set
{
world = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
}
}
public Matrix View
{
get { return view; }
set
{
view = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
}
}
public Matrix Projection
{
get { return projection; }
set
{
projection = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
}
}
public DeferredPBR_PointLightEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_PointLightEffect) public DeferredPBR_PointLightEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_PointLightEffect)
{ {
CacheEffectParameters(); CacheEffectParameters();
@ -73,6 +111,13 @@ namespace Kav
pointLightColorParam.SetValue(PointLightColor); pointLightColorParam.SetValue(PointLightColor);
farPlaneParam.SetValue(FarPlane); farPlaneParam.SetValue(FarPlane);
if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
{
worldViewProjectionParam.SetValue(world * view * projection);
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
}
} }
void CacheEffectParameters() void CacheEffectParameters()
@ -89,6 +134,8 @@ namespace Kav
pointLightColorParam = Parameters["PointLightColor"]; pointLightColorParam = Parameters["PointLightColor"];
farPlaneParam = Parameters["FarPlane"]; farPlaneParam = Parameters["FarPlane"];
worldViewProjectionParam = Parameters["WorldViewProjection"];
} }
} }
} }

Binary file not shown.

View File

@ -1,3 +1,5 @@
// Assumes you are drawing a sphere!!
#include "Macros.fxh" //from FNA #include "Macros.fxh" //from FNA
#include "Lighting.fxh" #include "Lighting.fxh"
#include "Shadow.fxh" #include "Shadow.fxh"
@ -19,26 +21,27 @@ BEGIN_CONSTANTS
MATRIX_CONSTANTS MATRIX_CONSTANTS
float4x4 WorldViewProjection _vs(c0) _cb(c4);
END_CONSTANTS END_CONSTANTS
struct VertexInput struct VertexInput
{ {
float4 Position : POSITION; float4 Position : POSITION;
float2 TexCoord : TEXCOORD;
}; };
struct PixelInput struct PixelInput
{ {
float4 Position : SV_POSITION; float4 Position : SV_POSITION;
float2 TexCoord : TEXCOORD0; float4 ScreenPosition : TEXCOORD0;
}; };
PixelInput main_vs(VertexInput input) PixelInput main_vs(VertexInput input)
{ {
PixelInput output; PixelInput output;
output.Position = input.Position; output.Position = mul(input.Position, WorldViewProjection);
output.TexCoord = input.TexCoord; output.ScreenPosition = output.Position;
return output; return output;
} }
@ -73,10 +76,13 @@ float4 ComputeColor(
float4 main_ps(PixelInput input) : SV_TARGET0 float4 main_ps(PixelInput input) : SV_TARGET0
{ {
float3 worldPosition = SAMPLE_TEXTURE(gPosition, input.TexCoord).rgb; input.ScreenPosition.xy /= input.ScreenPosition.w;
float3 normal = SAMPLE_TEXTURE(gNormal, input.TexCoord).xyz; float2 texCoord = 0.5f * float2(input.ScreenPosition.x,-input.ScreenPosition.y) + 0.5f;
float3 albedo = SAMPLE_TEXTURE(gAlbedo, input.TexCoord).rgb;
float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, input.TexCoord).rg; float3 worldPosition = SAMPLE_TEXTURE(gPosition, texCoord).rgb;
float3 normal = SAMPLE_TEXTURE(gNormal, texCoord).xyz;
float3 albedo = SAMPLE_TEXTURE(gAlbedo, texCoord).rgb;
float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, texCoord).rg;
return ComputeColor( return ComputeColor(
worldPosition, worldPosition,

View File

@ -64,6 +64,9 @@
<EmbeddedResource Include="Models\UnitCube.glb"> <EmbeddedResource Include="Models\UnitCube.glb">
<LogicalName>Kav.Resources.UnitCube.glb</LogicalName> <LogicalName>Kav.Resources.UnitCube.glb</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Models\UnitSphere.glb">
<LogicalName>Kav.Resources.UnitSphere.glb</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -64,6 +64,9 @@
<EmbeddedResource Include="Models\UnitCube.glb"> <EmbeddedResource Include="Models\UnitCube.glb">
<LogicalName>Kav.Resources.UnitCube.glb</LogicalName> <LogicalName>Kav.Resources.UnitCube.glb</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Models\UnitSphere.glb">
<LogicalName>Kav.Resources.UnitSphere.glb</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -4,15 +4,23 @@ namespace Kav
{ {
public struct PointLight public struct PointLight
{ {
public static double ATTENUATION_EPSILON = 0.1;
public Vector3 Position { get; } public Vector3 Position { get; }
public Color Color { get; } public Color Color { get; }
public float Intensity { get; } public float Intensity { get; }
public float EffectiveRadius { get; }
public BoundingSphere BoundingSphere { get; }
public PointLight(Vector3 position, Color color, float intensity = 1f) public PointLight(Vector3 position, Color color, float intensity = 1f)
{ {
Position = position; Position = position;
Color = color; Color = color;
Intensity = intensity; Intensity = intensity;
EffectiveRadius = (float) System.Math.Sqrt(Intensity);
BoundingSphere = new BoundingSphere(position, EffectiveRadius);
} }
} }
} }

BIN
Models/UnitSphere.glb Normal file

Binary file not shown.

View File

@ -28,6 +28,7 @@ namespace Kav
private DiffuseLitSpriteEffect DiffuseLitSpriteEffect { get; } private DiffuseLitSpriteEffect DiffuseLitSpriteEffect { get; }
private Kav.Model UnitCube { get; } private Kav.Model UnitCube { get; }
private Kav.Model UnitSphere { get; }
public Renderer( public Renderer(
GraphicsDevice graphicsDevice GraphicsDevice graphicsDevice
@ -61,6 +62,11 @@ namespace Kav
GraphicsDevice, GraphicsDevice,
Smuggler.Importer.ImportGLB(GraphicsDevice, new MemoryStream(Resources.UnitCubeModel)) Smuggler.Importer.ImportGLB(GraphicsDevice, new MemoryStream(Resources.UnitCubeModel))
); );
UnitSphere = Kav.ModelLoader.Load(
graphicsDevice,
Smuggler.Importer.ImportGLB(graphicsDevice, new MemoryStream(Resources.UnitSphereModel))
);
} }
public static (T[], DynamicVertexBuffer) CreateInstanceVertexBuffer<T>( public static (T[], DynamicVertexBuffer) CreateInstanceVertexBuffer<T>(
@ -461,7 +467,16 @@ namespace Kav
PointLight pointLight PointLight pointLight
) { ) {
GraphicsDevice.SetRenderTarget(renderTarget); GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead; if (Vector3.Distance(camera.Position, pointLight.Position) < pointLight.EffectiveRadius)
{
GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
}
else
{
GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
}
GraphicsDevice.DepthStencilState = DepthStencilState.None;
GraphicsDevice.BlendState = BlendState.Additive; GraphicsDevice.BlendState = BlendState.Additive;
DeferredPointLightEffect.GPosition = gPosition; DeferredPointLightEffect.GPosition = gPosition;
@ -478,7 +493,17 @@ namespace Kav
DeferredPointLightEffect.FarPlane = 25f; // FIXME: magic value DeferredPointLightEffect.FarPlane = 25f; // FIXME: magic value
RenderFullscreenEffect(DeferredPointLightEffect); DeferredPointLightEffect.World =
Matrix.CreateScale(pointLight.EffectiveRadius) *
Matrix.CreateTranslation(pointLight.Position);
DeferredPointLightEffect.View = camera.View;
DeferredPointLightEffect.Projection = camera.Projection;
RenderIndexed(
GraphicsDevice,
UnitSphere.Meshes[0].MeshParts[0],
DeferredPointLightEffect
);
} }
public void RenderDirectionalLight( public void RenderDirectionalLight(
@ -492,6 +517,7 @@ namespace Kav
DirectionalLight directionalLight DirectionalLight directionalLight
) { ) {
GraphicsDevice.SetRenderTarget(renderTarget); GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead; GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
GraphicsDevice.BlendState = BlendState.Additive; GraphicsDevice.BlendState = BlendState.Additive;

View File

@ -195,6 +195,18 @@ namespace Kav
} }
} }
public static byte[] UnitSphereModel
{
get
{
if (unitSphereModel == null)
{
unitSphereModel = GetResource("UnitSphere.glb");
}
return unitSphereModel;
}
}
private static byte[] ambientLightEffect; private static byte[] ambientLightEffect;
private static byte[] pointLightEffect; private static byte[] pointLightEffect;
private static byte[] directionalLightEffect; private static byte[] directionalLightEffect;
@ -212,6 +224,7 @@ namespace Kav
private static byte[] paletteCrushEffect; private static byte[] paletteCrushEffect;
private static byte[] unitCubeModel; private static byte[] unitCubeModel;
private static byte[] unitSphereModel;
private static byte[] GetResource(string name) private static byte[] GetResource(string name)
{ {