Toon Shading + Point Shadows #1

Merged
cosmonaut merged 9 commits from point_shadow into main 2020-10-19 22:17:48 +00:00
18 changed files with 284 additions and 28 deletions

2
Kav

@ -1 +1 @@
Subproject commit 66d4e5bf6e78949f6e5b2fc9eb1983d438047f0b
Subproject commit cb0baf0bf0b2c8c830c239c1566ca7a2fcacced9

View File

@ -0,0 +1,15 @@
using Encompass;
using Microsoft.Xna.Framework;
namespace KavTest.Components
{
public struct AmbientLightComponent : IComponent
{
public Color Color { get; }
public AmbientLightComponent(Color color)
{
Color = color;
}
}
}

View File

@ -0,0 +1,15 @@
using Encompass;
using Microsoft.Xna.Framework;
namespace KavTest
{
public struct ContinuousRotationComponent : IComponent
{
public Quaternion Quaternion { get; }
public ContinuousRotationComponent(Vector3 axis, float angle)
{
Quaternion = Quaternion.CreateFromAxisAngle(axis, angle);
}
}
}

View File

@ -0,0 +1,15 @@
using Encompass;
using Microsoft.Xna.Framework.Graphics;
namespace KavTest.Components
{
public struct SkyboxComponent : IComponent
{
public TextureCube Skybox { get; }
public SkyboxComponent(TextureCube skybox)
{
Skybox = skybox;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

BIN
KavTest/Content/ToonShadeRuins.glb (Stored with Git LFS) Normal file

Binary file not shown.

BIN
KavTest/Content/bluetorus.glb (Stored with Git LFS) Normal file

Binary file not shown.

BIN
KavTest/Content/pinkcone.glb (Stored with Git LFS) Normal file

Binary file not shown.

BIN
KavTest/Content/redcylinder.glb (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -5,7 +5,7 @@ using Microsoft.Xna.Framework;
namespace KavTest.Engines
{
[Reads(typeof(AngularVelocityComponent))]
[Reads(typeof(AngularVelocityComponent), typeof(ContinuousRotationComponent))]
[Sends(typeof(LocalRotationMessage))]
public class AngularVelocityEngine : Engine
{
@ -18,6 +18,12 @@ namespace KavTest.Engines
SendMessage(new LocalRotationMessage(entity, Quaternion.CreateFromYawPitchRoll(angularVelocity.X, angularVelocity.Y, angularVelocity.Z)));
}
foreach (var entity in ReadEntities<ContinuousRotationComponent>())
{
ref readonly var rotationComponent = ref GetComponent<ContinuousRotationComponent>(entity);
SendMessage(new LocalRotationMessage(entity, rotationComponent.Quaternion));
}
}
}
}

View File

@ -13,6 +13,8 @@ namespace KavTest.Spawners
AddComponent(entity, new Transform3DComponent(new Transform3D(Vector3.Zero, message.Orientation)));
AddComponent(entity, new DirectionalLightComponent(message.Color, message.Intensity));
var forward = Matrix.CreateFromQuaternion(message.Orientation).Forward;
AddComponent(entity, new ContinuousRotationComponent(forward, 0.01f));
}
}
}

View File

@ -23,8 +23,8 @@ namespace KavTest
public KavTestGame()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = 1280;
graphics.PreferredBackBufferHeight = 720;
graphics.PreferredBackBufferWidth = 1600;
graphics.PreferredBackBufferHeight = 900;
graphics.PreferMultiSampling = false;
Content.RootDirectory = "Content";
@ -50,8 +50,17 @@ namespace KavTest
var rustyBallModel = Kav.ModelLoader.Load(
GraphicsDevice,
Smuggler.Importer.ImportGLB(GraphicsDevice, File.OpenRead("Content/rustysphere.glb"))
Smuggler.Importer.ImportGLB(
GraphicsDevice,
File.OpenRead("Content/rustysphere.glb")
)
);
rustyBallModel.DisableNormalMaps();
rustyBallModel.DisableAlbedoMaps();
rustyBallModel.DisableMetallicRoughnessMaps();
rustyBallModel.Albedo = Color.DeepSkyBlue;
rustyBallModel.Metallic = 0.5f;
rustyBallModel.Roughness = 0.284f;
var lightBulbModel = Kav.ModelLoader.Load(
GraphicsDevice,
@ -62,12 +71,104 @@ namespace KavTest
GraphicsDevice,
Smuggler.Importer.ImportGLB(GraphicsDevice, File.OpenRead("Content/floor.glb"))
);
floorModel.Metallic = 0f;
floorModel.Roughness = 0f;
var avocadoModel = Kav.ModelLoader.Load(
GraphicsDevice,
Smuggler.Importer.ImportGLB(GraphicsDevice, File.OpenRead("Content/avocado.glb"))
);
var redCylinderModel = Kav.ModelLoader.Load(
GraphicsDevice,
Smuggler.Importer.ImportGLB(
GraphicsDevice,
File.OpenRead("Content/redcylinder.glb")
)
);
var pinkConeModel = Kav.ModelLoader.Load(
GraphicsDevice,
Smuggler.Importer.ImportGLB(
GraphicsDevice,
File.OpenRead("Content/pinkcone.glb")
)
);
var blueTorusModel = Kav.ModelLoader.Load(
GraphicsDevice,
Smuggler.Importer.ImportGLB(
GraphicsDevice,
File.OpenRead("Content/bluetorus.glb")
)
);
var cubeModel = Kav.ModelLoader.Load(
GraphicsDevice,
Smuggler.Importer.ImportGLB(
GraphicsDevice,
File.OpenRead("Content/cube.glb")
)
);
var toonShadeRuinsModel = Kav.ModelLoader.Load(
GraphicsDevice,
Smuggler.Importer.ImportGLB(
GraphicsDevice,
File.OpenRead("Content/ToonShadeRuins.glb")
)
);
Texture2D.TextureDataFromStreamEXT(
File.OpenRead("Content/Skybox/front.jpg"),
out var skyboxSize,
out _,
out byte[] frontPixels
);
Texture2D.TextureDataFromStreamEXT(
File.OpenRead("Content/Skybox/back.jpg"),
out _,
out _,
out byte[] backPixels
);
Texture2D.TextureDataFromStreamEXT(
File.OpenRead("Content/Skybox/right.jpg"),
out _,
out _,
out byte[] rightPixels
);
Texture2D.TextureDataFromStreamEXT(
File.OpenRead("Content/Skybox/left.jpg"),
out _,
out _,
out byte[] leftPixels
);
Texture2D.TextureDataFromStreamEXT(
File.OpenRead("Content/Skybox/top.jpg"),
out _,
out _,
out byte[] topPixels
);
Texture2D.TextureDataFromStreamEXT(
File.OpenRead("Content/Skybox/bottom.jpg"),
out _,
out _,
out byte[] bottomPixels
);
var skybox = new TextureCube(GraphicsDevice, skyboxSize, false, SurfaceFormat.Color);
skybox.SetData(CubeMapFace.PositiveZ, frontPixels);
skybox.SetData(CubeMapFace.NegativeZ, backPixels);
skybox.SetData(CubeMapFace.PositiveX, rightPixels);
skybox.SetData(CubeMapFace.NegativeX, leftPixels);
skybox.SetData(CubeMapFace.PositiveY, topPixels);
skybox.SetData(CubeMapFace.NegativeY, bottomPixels);
WorldBuilder.AddEngine(new InputEngine(this));
WorldBuilder.AddEngine(new AngularVelocityEngine());
WorldBuilder.AddEngine(new MoveAlongCurve3DEngine());
@ -94,35 +195,97 @@ namespace KavTest
// new Vector3(-1, 1, 1)
// ));
// WorldBuilder.SendMessage(new StaticModelSpawnMessage(
// new Transform3D(new Vector3(0, 1, 0), Quaternion.Identity, new Vector3(1f, 1f, 1f)),
// rustyBallModel
// ));
WorldBuilder.SendMessage(new StaticModelSpawnMessage(
new Transform3D(new Vector3(0, -3, 0), Quaternion.Identity, new Vector3(10f, 1f, 10f)),
floorModel
));
var entity = WorldBuilder.CreateEntity();
WorldBuilder.SetComponent(entity, new Transform3DComponent(
WorldBuilder.SendMessage(new StaticModelSpawnMessage(
new Transform3D(
new Vector3(0, 1, 0),
Quaternion.CreateFromAxisAngle(Vector3.Right, -Microsoft.Xna.Framework.MathHelper.PiOver2),
new Vector3(30, 30, 30))
Quaternion.CreateFromAxisAngle(
Vector3.Right,
-Microsoft.Xna.Framework.MathHelper.PiOver2
),
new Vector3(1f, 1f, 1f)
),
redCylinderModel
));
WorldBuilder.SendMessage(new StaticModelSpawnMessage(
new Transform3D(
new Vector3(-3, 1, 0),
Quaternion.CreateFromAxisAngle(
Vector3.Right,
-Microsoft.Xna.Framework.MathHelper.PiOver2
),
new Vector3(1f, 1f, 1f)
),
blueTorusModel
));
WorldBuilder.SendMessage(new StaticModelSpawnMessage(
new Transform3D(
new Vector3(3, 1, 0),
Quaternion.CreateFromAxisAngle(
Vector3.Right,
-Microsoft.Xna.Framework.MathHelper.PiOver2
),
new Vector3(1f, 1f, 1f)
),
cubeModel
));
// WorldBuilder.SendMessage(new StaticModelSpawnMessage(
// Transform3D.Identity,
// toonShadeRuinsModel
// ));
var lightEntity = WorldBuilder.CreateEntity();
WorldBuilder.SetComponent(
lightEntity,
new Transform3DComponent(
new Transform3D(
new Vector3(0, 3, 3),
Quaternion.Identity,
new Vector3(0.1f, 0.1f, 0.1f)
)
)
);
WorldBuilder.SetComponent(entity, new ModelComponent(avocadoModel));
WorldBuilder.SetComponent(
lightEntity,
new PointLightComponent(Color.Blue, 1000f)
);
WorldBuilder.SetComponent(
lightEntity,
new ModelComponent(cubeModel)
);
for (var i = 0; i < 1; i++)
{
var start = RandomHelper.RandomVector3(-5, 5);
// for (var i = 0; i < 1; i++)
// {
// var start = RandomHelper.RandomVector3(2, 5);
WorldBuilder.SendMessage(new LightBulbSpawnMessage(
new Transform3D(start.ToXNAVector(), Quaternion.Identity, new Vector3(0.1f, 0.1f, 0.1f)),
RandomHelper.RandomColor(),
1f,
RandomHelper.RandomLoop(start, -15, 15, 3, 10)
));
}
// WorldBuilder.SendMessage(new LightBulbSpawnMessage(
// new Transform3D(start.ToXNAVector(), Quaternion.Identity, new Vector3(0.1f, 0.1f, 0.1f)),
// RandomHelper.RandomColor(),
// 5f,
// RandomHelper.RandomLoop(start, 2, 5, 3, 10)
// ));
// }
var ambientLightEntity = WorldBuilder.CreateEntity();
WorldBuilder.SetComponent(ambientLightEntity, new AmbientLightComponent(
new Color(0.4f, 0.4f, 0.4f)
));
WorldBuilder.SendMessage(new DirectionalLightSpawnMessage(
//Quaternion.CreateFromAxisAngle(Vector3.Right, Microsoft.Xna.Framework.MathHelper.Pi / 3f),
Quaternion.CreateFromAxisAngle(Vector3.Right, Microsoft.Xna.Framework.MathHelper.PiOver4),
Color.LightGoldenrodYellow,
0.7f
@ -155,6 +318,11 @@ namespace KavTest
100f
));
var skyboxEntity = WorldBuilder.CreateEntity();
WorldBuilder.SetComponent(skyboxEntity, new SkyboxComponent(
skybox
));
World = WorldBuilder.Build();
}

View File

@ -19,6 +19,7 @@ namespace KavTest.Renderers
{
foreach (var entity in ReadEntitiesAsEnumerable<ModelComponent>())
{
/* FIXME: this transformation should definitely not go here */
var transformComponent = GetComponent<Transform3DComponent>(entity);
var modelComponent = GetComponent<ModelComponent>(entity);
if (HasComponent<OverrideAlbedoComponent>(entity))
@ -29,11 +30,8 @@ namespace KavTest.Renderers
{
foreach (var meshPart in mesh.MeshParts)
{
if (meshPart.Effect is DeferredPBR_GBufferEffect gBufferEffect)
{
gBufferEffect.AlbedoTexture = null;
gBufferEffect.Albedo = overrideAlbedoComponent.Color;
}
meshPart.DisableAlbedoMap = true;
meshPart.Albedo = overrideAlbedoComponent.Color;
}
}
}
@ -42,6 +40,21 @@ namespace KavTest.Renderers
}
}
private AmbientLight AmbientLight
{
get
{
if (SomeComponent<AmbientLightComponent>())
{
return new AmbientLight(ReadComponent<AmbientLightComponent>().Color);
}
else
{
return new AmbientLight(Color.Black);
}
}
}
private IEnumerable<PointLight> PointLights
{
get
@ -118,11 +131,21 @@ namespace KavTest.Renderers
// );
// }
Renderer.DeferredRender(
// Renderer.DeferredRender(
// camera,
// ModelTransforms,
// AmbientLight,
// PointLights,
// DirectionalLight()
// );
Renderer.DeferredToonRender(
camera,
ModelTransforms,
AmbientLight,
PointLights,
DirectionalLight()
DirectionalLight(),
ReadComponent<SkyboxComponent>().Skybox
);
// foreach (var directionalLight in DirectionalLights)