Implement sun & moon
This commit is contained in:
parent
528eb2c5f4
commit
e5aaf73d12
BIN
TrueCraft.Client/Content/moon.png
Normal file
BIN
TrueCraft.Client/Content/moon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
TrueCraft.Client/Content/sun.png
Normal file
BIN
TrueCraft.Client/Content/sun.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
@ -46,16 +46,17 @@ namespace TrueCraft.Client.Modules
|
||||
OpaqueEffect.TextureEnabled = true;
|
||||
OpaqueEffect.Texture = Game.TextureMapper.GetTexture("terrain.png");
|
||||
OpaqueEffect.FogEnabled = true;
|
||||
OpaqueEffect.FogStart = 512f;
|
||||
OpaqueEffect.FogEnd = 1000f;
|
||||
OpaqueEffect.FogColor = Color.CornflowerBlue.ToVector3();
|
||||
OpaqueEffect.FogStart = 0;
|
||||
OpaqueEffect.FogEnd = Game.Camera.Frustum.Far.D * 0.8f;
|
||||
OpaqueEffect.VertexColorEnabled = true;
|
||||
OpaqueEffect.LightingEnabled = true;
|
||||
|
||||
TransparentEffect = new AlphaTestEffect(Game.GraphicsDevice);
|
||||
TransparentEffect.AlphaFunction = CompareFunction.Greater;
|
||||
TransparentEffect.ReferenceAlpha = 127;
|
||||
TransparentEffect.Texture = Game.TextureMapper.GetTexture("terrain.png");
|
||||
TransparentEffect.VertexColorEnabled = true;
|
||||
OpaqueEffect.LightingEnabled = true;
|
||||
|
||||
ChunkMeshes = new List<ChunkMesh>();
|
||||
IncomingChunks = new ConcurrentBag<Mesh>();
|
||||
@ -164,8 +165,11 @@ namespace TrueCraft.Client.Modules
|
||||
|
||||
public void Draw(GameTime gameTime)
|
||||
{
|
||||
OpaqueEffect.FogColor = Game.SkyModule.WorldFogColor.ToVector3();
|
||||
Game.Camera.ApplyTo(OpaqueEffect);
|
||||
Game.Camera.ApplyTo(TransparentEffect);
|
||||
OpaqueEffect.AmbientLightColor = TransparentEffect.DiffuseColor = Color.White.ToVector3()
|
||||
* new Microsoft.Xna.Framework.Vector3(0.25f + Game.SkyModule.BrightnessModifier);
|
||||
|
||||
int chunks = 0;
|
||||
Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||
|
233
TrueCraft.Client/Modules/SkyModule.cs
Normal file
233
TrueCraft.Client/Modules/SkyModule.cs
Normal file
@ -0,0 +1,233 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace TrueCraft.Client.Modules
|
||||
{
|
||||
public class SkyModule : IGraphicalModule
|
||||
{
|
||||
// https://github.com/SirCmpwn/TrueCraft/wiki/Sky
|
||||
|
||||
private TrueCraftGame Game { get; set; }
|
||||
private BasicEffect SkyPlaneEffect { get; set; }
|
||||
private BasicEffect CelestialPlaneEffect { get; set; }
|
||||
private VertexBuffer SkyPlane { get; set; }
|
||||
private VertexBuffer CelestialPlane { get; set; }
|
||||
|
||||
public SkyModule(TrueCraftGame game)
|
||||
{
|
||||
Game = game;
|
||||
CelestialPlaneEffect = new BasicEffect(Game.GraphicsDevice);
|
||||
CelestialPlaneEffect.TextureEnabled = true;
|
||||
|
||||
SkyPlaneEffect = new BasicEffect(Game.GraphicsDevice);
|
||||
SkyPlaneEffect.VertexColorEnabled = false;
|
||||
SkyPlaneEffect.FogEnabled = true;
|
||||
SkyPlaneEffect.FogStart = 0;
|
||||
SkyPlaneEffect.FogEnd = 64 * 0.8f;
|
||||
SkyPlaneEffect.LightingEnabled = true;
|
||||
var plane = new[]
|
||||
{
|
||||
new VertexPositionColor(new Vector3(-64, 0, -64), Color.White),
|
||||
new VertexPositionColor(new Vector3(64, 0, -64), Color.White),
|
||||
new VertexPositionColor(new Vector3(-64, 0, 64), Color.White),
|
||||
|
||||
new VertexPositionColor(new Vector3(64, 0, -64), Color.White),
|
||||
new VertexPositionColor(new Vector3(64, 0, 64), Color.White),
|
||||
new VertexPositionColor(new Vector3(-64, 0, 64), Color.White)
|
||||
};
|
||||
SkyPlane = new VertexBuffer(Game.GraphicsDevice, VertexPositionColor.VertexDeclaration,
|
||||
plane.Length, BufferUsage.WriteOnly);
|
||||
SkyPlane.SetData<VertexPositionColor>(plane);
|
||||
var celestialPlane = new[]
|
||||
{
|
||||
new VertexPositionTexture(new Vector3(-60, 0, -60), new Vector2(0, 0)),
|
||||
new VertexPositionTexture(new Vector3(60, 0, -60), new Vector2(1, 0)),
|
||||
new VertexPositionTexture(new Vector3(-60, 0, 60), new Vector2(0, 1)),
|
||||
|
||||
new VertexPositionTexture(new Vector3(60, 0, -60), new Vector2(1, 0)),
|
||||
new VertexPositionTexture(new Vector3(60, 0, 60), new Vector2(1, 1)),
|
||||
new VertexPositionTexture(new Vector3(-60, 0, 60), new Vector2(0, 1))
|
||||
};
|
||||
CelestialPlane = new VertexBuffer(Game.GraphicsDevice, VertexPositionTexture.VertexDeclaration,
|
||||
celestialPlane.Length, BufferUsage.WriteOnly);
|
||||
CelestialPlane.SetData<VertexPositionTexture>(celestialPlane);
|
||||
}
|
||||
|
||||
private float CelestialAngle
|
||||
{
|
||||
get
|
||||
{
|
||||
float x = (Game.Client.World.Time % 24000f) / 24000f - 0.25f;
|
||||
if (x < 0) x = 0;
|
||||
if (x > 1) x = 1;
|
||||
return x + ((1 - ((float)Math.Cos(x * MathHelper.Pi) + 1) / 2) - x) / 3;
|
||||
}
|
||||
}
|
||||
|
||||
public static Color HSL2RGB(float h, float sl, float l)
|
||||
{
|
||||
// Thanks http://www.java2s.com/Code/CSharp/2D-Graphics/HSLtoRGBconversion.htm
|
||||
float v, r, g, b;
|
||||
r = g = b = l; // default to gray
|
||||
v = (l <= 0.5f) ? (l * (1.0f + sl)) : (l + sl - l * sl);
|
||||
if (v > 0)
|
||||
{
|
||||
int sextant;
|
||||
float m, sv, fract, vsf, mid1, mid2;
|
||||
m = l + l - v;
|
||||
sv = (v - m) / v;
|
||||
h *= 6.0f;
|
||||
sextant = (int)h;
|
||||
fract = h - sextant;
|
||||
vsf = v * sv * fract;
|
||||
mid1 = m + vsf;
|
||||
mid2 = v - vsf;
|
||||
switch (sextant)
|
||||
{
|
||||
case 0:
|
||||
r = v; g = mid1; b = m;
|
||||
break;
|
||||
case 1:
|
||||
r = mid2; g = v; b = m;
|
||||
break;
|
||||
case 2:
|
||||
r = m; g = v; b = mid1;
|
||||
break;
|
||||
case 3:
|
||||
r = m; g = mid2; b = v;
|
||||
break;
|
||||
case 4:
|
||||
r = mid1; g = m; b = v;
|
||||
break;
|
||||
case 5:
|
||||
r = v; g = m; b = mid2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Color(r, g, b);
|
||||
}
|
||||
|
||||
private Color BaseColor
|
||||
{
|
||||
get
|
||||
{
|
||||
// Note: temperature comes from the current biome, but we have to
|
||||
// do biomes differently than Minecraft so we'll un-hardcode this later.
|
||||
const float temp = 0.8f / 3;
|
||||
return HSL2RGB(0.6222222f - temp * 0.05f, 0.5f + temp * 0.1f, BrightnessModifier);
|
||||
}
|
||||
}
|
||||
|
||||
public float BrightnessModifier
|
||||
{
|
||||
get
|
||||
{
|
||||
var mod = (float)Math.Cos(CelestialAngle * MathHelper.TwoPi) * 2 + 0.5f;
|
||||
if (mod < 0) mod = 0;
|
||||
if (mod > 1) mod = 1;
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
|
||||
public Color WorldSkyColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return BaseColor;
|
||||
}
|
||||
}
|
||||
|
||||
public Color WorldFogColor
|
||||
{
|
||||
get
|
||||
{
|
||||
float y = (float)Math.Cos(CelestialAngle * MathHelper.TwoPi) * 2 + 0.5f;
|
||||
return new Color(0.7529412f * y * 0.94f + 0.06f,
|
||||
0.8470588f * y * 0.94f + 0.06f, 1.0f * y * 0.91f + 0.09f);
|
||||
}
|
||||
}
|
||||
|
||||
public Color AtmosphereColor
|
||||
{
|
||||
get
|
||||
{
|
||||
const float blendFactor = 0.29f; // TODO: Compute based on view distance
|
||||
Func<float, float, float> blend = (float source, float destination) =>
|
||||
destination + (source - destination) * blendFactor;
|
||||
var fog = WorldFogColor.ToVector3();
|
||||
var sky = WorldSkyColor.ToVector3();
|
||||
var color = new Vector3(blend(sky.X, fog.X), blend(sky.Y, fog.Y), blend(sky.Z, fog.Z));
|
||||
// TODO: more stuff
|
||||
return new Color(color);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(GameTime gameTime)
|
||||
{
|
||||
Game.GraphicsDevice.Clear(AtmosphereColor);
|
||||
Game.GraphicsDevice.SetVertexBuffer(SkyPlane);
|
||||
|
||||
var position = Game.Camera.Position;
|
||||
var yaw = Game.Camera.Yaw;
|
||||
Game.Camera.Position = TrueCraft.API.Vector3.Zero;
|
||||
Game.Camera.Yaw = 0;
|
||||
Game.Camera.ApplyTo(SkyPlaneEffect);
|
||||
Game.Camera.Yaw = yaw;
|
||||
Game.Camera.ApplyTo(CelestialPlaneEffect);
|
||||
Game.Camera.Position = position;
|
||||
// Sky
|
||||
SkyPlaneEffect.FogColor = AtmosphereColor.ToVector3();
|
||||
SkyPlaneEffect.World = Matrix.CreateRotationX(MathHelper.Pi)
|
||||
* Matrix.CreateTranslation(0, 100, 0)
|
||||
* Matrix.CreateRotationX(MathHelper.TwoPi * CelestialAngle);
|
||||
SkyPlaneEffect.AmbientLightColor = WorldSkyColor.ToVector3(); foreach (var pass in SkyPlaneEffect.CurrentTechnique.Passes)
|
||||
{
|
||||
pass.Apply();
|
||||
SkyPlaneEffect.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
|
||||
}
|
||||
|
||||
// Sun
|
||||
Game.GraphicsDevice.SetVertexBuffer(CelestialPlane);
|
||||
var backup = Game.GraphicsDevice.BlendState;
|
||||
Game.GraphicsDevice.BlendState = BlendState.Additive;
|
||||
Game.GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
|
||||
CelestialPlaneEffect.Texture = Game.TextureMapper.GetTexture("terrain/sun.png");
|
||||
CelestialPlaneEffect.World = Matrix.CreateRotationX(MathHelper.Pi)
|
||||
* Matrix.CreateTranslation(0, 100, 0)
|
||||
* Matrix.CreateRotationX(MathHelper.TwoPi * CelestialAngle);
|
||||
foreach (var pass in CelestialPlaneEffect.CurrentTechnique.Passes)
|
||||
{
|
||||
pass.Apply();
|
||||
CelestialPlaneEffect.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
|
||||
}
|
||||
// Moon
|
||||
CelestialPlaneEffect.Texture = Game.TextureMapper.GetTexture("terrain/moon.png");
|
||||
CelestialPlaneEffect.World = Matrix.CreateTranslation(0, -100, 0)
|
||||
* Matrix.CreateRotationX(MathHelper.TwoPi * CelestialAngle);
|
||||
foreach (var pass in CelestialPlaneEffect.CurrentTechnique.Passes)
|
||||
{
|
||||
pass.Apply();
|
||||
CelestialPlaneEffect.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
|
||||
}
|
||||
Game.GraphicsDevice.BlendState = backup;
|
||||
Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||
|
||||
// Void
|
||||
Game.GraphicsDevice.SetVertexBuffer(SkyPlane);
|
||||
SkyPlaneEffect.World = Matrix.CreateTranslation(0, -16, 0);
|
||||
SkyPlaneEffect.AmbientLightColor = WorldSkyColor.ToVector3()
|
||||
* new Vector3(0.2f, 0.2f, 0.6f)
|
||||
+ new Vector3(0.04f, 0.04f, 0.1f);
|
||||
foreach (var pass in SkyPlaneEffect.CurrentTechnique.Passes)
|
||||
{
|
||||
pass.Apply();
|
||||
SkyPlaneEffect.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(GameTime gameTime)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,8 @@ namespace TrueCraft.Client
|
||||
|
||||
internal World World { get; set; }
|
||||
|
||||
public long Time { get { return World.Time; } }
|
||||
|
||||
internal ReadOnlyWorld()
|
||||
{
|
||||
World = new World("default");
|
||||
|
@ -36,6 +36,8 @@ namespace TrueCraft.Client.Rendering
|
||||
Defaults.Add("gui/crafting.png", new PngReader().Read(File.OpenRead("Content/crafting.png"), graphicsDevice));
|
||||
Defaults.Add("gui/furnace.png", new PngReader().Read(File.OpenRead("Content/furnace.png"), graphicsDevice));
|
||||
Defaults.Add("gui/inventory.png", new PngReader().Read(File.OpenRead("Content/inventory.png"), graphicsDevice));
|
||||
Defaults.Add("terrain/moon.png", new PngReader().Read(File.OpenRead("Content/moon.png"), graphicsDevice));
|
||||
Defaults.Add("terrain/sun.png", new PngReader().Read(File.OpenRead("Content/sun.png"), graphicsDevice));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -151,6 +151,7 @@
|
||||
<Compile Include="AudioManager.cs" />
|
||||
<Compile Include="Modules\ChatModule.cs" />
|
||||
<Compile Include="Modules\WindowModule.cs" />
|
||||
<Compile Include="Modules\SkyModule.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
@ -379,6 +380,12 @@
|
||||
<Link>OpenTK.dll.config</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Content\moon.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Content\sun.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
</Project>
|
||||
|
@ -42,6 +42,7 @@ namespace TrueCraft.Client
|
||||
public AudioManager Audio { get; set; }
|
||||
public Texture2D White1x1 { get; set; }
|
||||
public PlayerControlModule ControlModule { get; set; }
|
||||
public SkyModule SkyModule { get; set; }
|
||||
|
||||
private List<IGameplayModule> InputModules { get; set; }
|
||||
private List<IGameplayModule> GraphicalModules { get; set; }
|
||||
@ -121,18 +122,23 @@ namespace TrueCraft.Client
|
||||
|
||||
base.Initialize(); // (calls LoadContent)
|
||||
|
||||
Camera = new Camera(GraphicsDevice.Viewport.AspectRatio, 70.0f, 0.1f, 1000.0f);
|
||||
UpdateCamera();
|
||||
|
||||
White1x1 = new Texture2D(GraphicsDevice, 1, 1);
|
||||
White1x1.SetData<Color>(new[] { Color.White });
|
||||
|
||||
Audio = new AudioManager();
|
||||
Audio.LoadDefaultPacks(Content);
|
||||
|
||||
SkyModule = new SkyModule(this);
|
||||
ChunkModule = new ChunkModule(this);
|
||||
DebugInfoModule = new DebugInfoModule(this, Pixel);
|
||||
ChatModule = new ChatModule(this, Pixel);
|
||||
var hud = new HUDModule(this, Pixel);
|
||||
var windowModule = new WindowModule(this, Pixel);
|
||||
|
||||
GraphicalModules.Add(SkyModule);
|
||||
GraphicalModules.Add(ChunkModule);
|
||||
GraphicalModules.Add(new HighlightModule(this));
|
||||
GraphicalModules.Add(hud);
|
||||
@ -161,9 +167,6 @@ namespace TrueCraft.Client
|
||||
var centerY = GraphicsDevice.Viewport.Height / 2;
|
||||
Mouse.SetPosition(centerX, centerY);
|
||||
|
||||
Camera = new Camera(GraphicsDevice.Viewport.AspectRatio, 70.0f, 0.1f, 1000.0f);
|
||||
UpdateCamera();
|
||||
|
||||
MouseComponent.Scroll += OnMouseComponentScroll;
|
||||
MouseComponent.Move += OnMouseComponentMove;
|
||||
MouseComponent.ButtonDown += OnMouseComponentButtonDown;
|
||||
@ -397,7 +400,6 @@ namespace TrueCraft.Client
|
||||
GraphicsDevice.SetRenderTarget(RenderTarget);
|
||||
GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
|
||||
|
||||
Graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||
GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
|
||||
GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp;
|
||||
|
||||
|
Reference in New Issue
Block a user