ClassiCube/GraphicsAPI/ShadowMap.cs
2015-04-06 14:02:35 +10:00

113 lines
4.5 KiB
C#

using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace ClassicalSharp.GraphicsAPI {
public abstract class ShadowMap {
public Vector3 LightPosition = new Vector3( 256, 160, 256 );
public Vector3 LightTarget = new Vector3( 128, 128, 128 );
public Matrix4 ShadowMatrix;
public abstract void Create( int width, int height );
public abstract void BindForReading( IGraphicsApi graphics );
public abstract void BindForWriting( IGraphicsApi graphics );
public abstract void UnbindForWriting( IGraphicsApi graphics );
public abstract void SetupState( IGraphicsApi graphics, Game game );
public abstract void RestoreState( IGraphicsApi graphics, Game g );
public abstract void Dispose();
}
public sealed class OpenGLShadowMap : ShadowMap {
int depthTextureId, fboId;
int fboWidth, fboHeight;
public override void Create( int width, int height ) {
GL.GenTextures( 1, out depthTextureId );
GL.BindTexture( TextureTarget.Texture2D, depthTextureId );
//GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear );
//GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear );
GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Nearest );
GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest );
GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Clamp );
GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Clamp );
GL.TexImage2D( TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent,
width, height, 0, PixelFormat.DepthComponent,
PixelType.UnsignedByte, IntPtr.Zero );
GL.BindTexture( TextureTarget.Texture2D, 0 );
GL.Ext.GenFramebuffers( 1, out fboId );
GL.Ext.BindFramebuffer( FramebufferTarget.Framebuffer, fboId );
GL.DrawBuffer( DrawBufferMode.None );
GL.ReadBuffer( (ReadBufferMode)DrawBufferMode.None );
GL.Ext.FramebufferTexture2D( FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment,
TextureTarget.Texture2D, depthTextureId, 0 );
FramebufferErrorCode status = GL.Ext.CheckFramebufferStatus( FramebufferTarget.Framebuffer );
if( status != FramebufferErrorCode.FramebufferComplete ) Console.WriteLine( "ERROR FBO: " + status );
GL.Ext.BindFramebuffer( FramebufferTarget.Framebuffer, 0 );
fboWidth = width;
fboHeight = height;
}
public override void BindForReading( IGraphicsApi graphics ) {
GL.Arb.ActiveTexture( TextureUnit.Texture1 );
GL.BindTexture( TextureTarget.Texture2D, depthTextureId );
GL.Arb.ActiveTexture( TextureUnit.Texture0 );
}
public override void BindForWriting( IGraphicsApi graphics ) {
GL.Ext.BindFramebuffer( FramebufferTarget.Framebuffer, fboId );
}
public override void UnbindForWriting( IGraphicsApi graphics ) {
GL.Ext.BindFramebuffer( FramebufferTarget.Framebuffer, 0 );
}
public override void SetupState( IGraphicsApi graphics, Game game ) {
graphics.SetMatrixMode( MatrixType.Projection );
graphics.PushMatrix();
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(
(float)Math.PI / 4, game.Width / (float)game.Height, 1, 1000 );
graphics.LoadMatrix( ref projection );
graphics.SetMatrixMode( MatrixType.Modelview );
graphics.PushMatrix();
Matrix4 modelview = Matrix4.LookAt( LightPosition, LightTarget, Vector3.UnitY );
graphics.LoadMatrix( ref modelview );
ShadowMatrix = modelview * projection * bias;
graphics.ColourMask( false, false, false, false );
GL.Viewport( 0, 0, fboWidth, fboHeight );
GL.Clear( ClearBufferMask.DepthBufferBit );
}
public override void RestoreState( IGraphicsApi graphics, Game game ) {
graphics.SetMatrixMode( MatrixType.Projection );
graphics.PopMatrix();
graphics.SetMatrixMode( MatrixType.Modelview );
graphics.PopMatrix();
graphics.ColourMask( true, true, true, true );
GL.Viewport( 0, 0, game.Width, game.Height );
}
static Matrix4 bias = new Matrix4(
0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f
);
public override void Dispose() {
GL.DeleteTexture( depthTextureId );
GL.Ext.DeleteFramebuffers( 1, ref fboId );
}
}
}