2007-06-15 18:30:55 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Text ;
using System.Windows.Forms ;
using System.IO ;
using System.Reflection ;
using System.Drawing ;
2007-07-07 09:40:34 +00:00
using SlimDX.Direct3D9 ;
2007-06-26 09:09:54 +00:00
using SlimDX.Direct3D ;
2007-06-15 18:30:55 +00:00
using System.ComponentModel ;
2007-06-24 18:56:43 +00:00
using CodeImp.DoomBuilder.Geometry ;
2007-06-26 09:09:54 +00:00
using SlimDX ;
2007-10-16 21:15:27 +00:00
using CodeImp.DoomBuilder.Interface ;
2007-06-15 18:30:55 +00:00
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
2007-09-17 21:22:46 +00:00
internal class D3DGraphics : IDisposable
2007-06-15 18:30:55 +00:00
{
#region = = = = = = = = = = = = = = = = = = Constants
// NVPerfHUD device name
public const string NVPERFHUD_ADAPTER = "NVPerfHUD" ;
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Settings
private int adapter ;
// Main objects
2007-10-16 21:15:27 +00:00
private RenderTargetControl rendertarget ;
2007-06-26 09:09:54 +00:00
private Capabilities devicecaps ;
2007-06-24 18:56:43 +00:00
private Device device ;
2007-06-15 22:38:42 +00:00
private Renderer2D renderer2d ;
private Renderer3D renderer3d ;
2007-07-07 09:40:34 +00:00
private Viewport viewport ;
2007-10-19 14:27:46 +00:00
private List < ID3DResource > resources ;
2007-10-19 17:05:21 +00:00
private ShaderManager shaders ;
2007-06-15 18:30:55 +00:00
// Disposing
private bool isdisposed = false ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
2007-06-24 18:56:43 +00:00
public Device Device { get { return device ; } }
2007-06-15 18:30:55 +00:00
public bool IsDisposed { get { return isdisposed ; } }
2007-06-15 22:38:42 +00:00
public Renderer2D Renderer2D { get { return renderer2d ; } }
public Renderer3D Renderer3D { get { return renderer3d ; } }
2007-10-16 21:15:27 +00:00
public RenderTargetControl RenderTarget { get { return rendertarget ; } }
2007-07-07 09:40:34 +00:00
public Viewport Viewport { get { return viewport ; } }
2007-10-19 17:05:21 +00:00
public ShaderManager Shaders { get { return shaders ; } }
2007-06-15 18:30:55 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
2007-10-16 21:15:27 +00:00
public D3DGraphics ( RenderTargetControl rendertarget )
2007-06-15 18:30:55 +00:00
{
// Set render target
this . rendertarget = rendertarget ;
2007-07-07 09:40:34 +00:00
2007-10-19 14:27:46 +00:00
// Create resources list
resources = new List < ID3DResource > ( ) ;
2007-06-15 18:30:55 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Diposer
public void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
// Clean up
2007-06-15 22:38:42 +00:00
renderer2d . Dispose ( ) ;
renderer3d . Dispose ( ) ;
2007-06-24 18:56:43 +00:00
device . Dispose ( ) ;
2007-06-15 18:30:55 +00:00
rendertarget = null ;
2007-07-07 09:40:34 +00:00
Direct3D . Terminate ( ) ;
2007-06-15 18:30:55 +00:00
// Done
isdisposed = true ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Renderstates
// This completes initialization after the device has started or has been reset
private void SetupSettings ( )
{
2007-10-21 04:07:36 +00:00
int intvalue ;
float floatvalue ;
2007-06-15 18:30:55 +00:00
// Setup renderstates
2007-06-26 09:09:54 +00:00
device . SetRenderState ( RenderState . AntialiasedLineEnable , false ) ;
device . SetRenderState ( RenderState . Ambient , Color . White . ToArgb ( ) ) ;
2007-07-07 09:40:34 +00:00
device . SetRenderState ( RenderState . AmbientMaterialSource , ColorSource . Material ) ;
2007-06-26 09:09:54 +00:00
device . SetRenderState ( RenderState . ColorVertex , false ) ;
2007-07-07 09:40:34 +00:00
device . SetRenderState ( RenderState . DiffuseMaterialSource , ColorSource . Color1 ) ;
device . SetRenderState ( RenderState . FillMode , FillMode . Solid ) ;
2007-06-26 09:09:54 +00:00
device . SetRenderState ( RenderState . FogEnable , false ) ;
device . SetRenderState ( RenderState . Lighting , false ) ;
device . SetRenderState ( RenderState . LocalViewer , false ) ;
device . SetRenderState ( RenderState . NormalizeNormals , false ) ;
device . SetRenderState ( RenderState . SpecularEnable , false ) ;
device . SetRenderState ( RenderState . StencilEnable , false ) ;
device . SetRenderState ( RenderState . PointSpriteEnable , false ) ;
device . SetRenderState ( RenderState . DitherEnable , true ) ;
device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
device . SetRenderState ( RenderState . ZEnable , false ) ;
device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
device . SetRenderState ( RenderState . Clipping , true ) ;
2007-07-07 09:40:34 +00:00
device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
2007-06-15 18:30:55 +00:00
2007-10-21 04:07:36 +00:00
// Make LOD bias hack until SlimDX has a SetSamplerState overload that accepts a float
floatvalue = - 0.99f ;
unsafe { General . CopyMemory ( & intvalue , & floatvalue , new UIntPtr ( 4 ) ) ; }
2007-06-15 18:30:55 +00:00
// Sampler settings
2007-07-07 09:40:34 +00:00
device . SetSamplerState ( 0 , SamplerState . MagFilter , TextureFilter . Linear ) ;
device . SetSamplerState ( 0 , SamplerState . MinFilter , TextureFilter . Linear ) ;
device . SetSamplerState ( 0 , SamplerState . MipFilter , TextureFilter . Linear ) ;
2007-10-21 04:07:36 +00:00
device . SetSamplerState ( 0 , SamplerState . MipMapLodBias , intvalue ) ;
2007-06-15 18:30:55 +00:00
// Texture addressing
2007-07-07 09:40:34 +00:00
device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Wrap ) ;
device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Wrap ) ;
device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Wrap ) ;
2007-06-15 18:30:55 +00:00
// First texture stage
2007-10-21 04:07:36 +00:00
device . SetTextureStageState ( 0 , TextureStage . ColorOperation , TextureOperation . Modulate ) ;
2007-10-19 14:27:46 +00:00
device . SetTextureStageState ( 0 , TextureStage . ColorArg1 , TextureArgument . Texture ) ;
2007-10-21 04:07:36 +00:00
device . SetTextureStageState ( 0 , TextureStage . ColorArg2 , TextureArgument . TFactor ) ;
2007-07-07 09:40:34 +00:00
device . SetTextureStageState ( 0 , TextureStage . ResultArg , TextureArgument . Current ) ;
2007-06-26 09:09:54 +00:00
device . SetTextureStageState ( 0 , TextureStage . TexCoordIndex , 0 ) ;
2007-06-15 18:30:55 +00:00
// No more further stages
2007-10-19 14:27:46 +00:00
device . SetTextureStageState ( 1 , TextureStage . ColorOperation , TextureOperation . Disable ) ;
2007-06-15 18:30:55 +00:00
// First alpha stage
2007-10-21 04:07:36 +00:00
device . SetTextureStageState ( 0 , TextureStage . AlphaOperation , TextureOperation . Modulate ) ;
2007-10-19 14:27:46 +00:00
device . SetTextureStageState ( 0 , TextureStage . AlphaArg1 , TextureArgument . Texture ) ;
2007-10-21 04:07:36 +00:00
device . SetTextureStageState ( 0 , TextureStage . AlphaArg2 , TextureArgument . TFactor ) ;
2007-06-15 18:30:55 +00:00
// No more further stages
2007-10-19 14:27:46 +00:00
device . SetTextureStageState ( 1 , TextureStage . AlphaOperation , TextureOperation . Disable ) ;
2007-06-15 18:30:55 +00:00
// Setup material
Material material = new Material ( ) ;
2007-06-26 09:09:54 +00:00
material . Ambient = ColorValue . FromColor ( Color . White ) ;
material . Diffuse = ColorValue . FromColor ( Color . White ) ;
material . Specular = ColorValue . FromColor ( Color . White ) ;
2007-06-24 18:56:43 +00:00
device . Material = material ;
2007-07-07 09:40:34 +00:00
// Get the viewport
viewport = device . Viewport ;
2007-10-19 17:05:21 +00:00
// Setup shaders
if ( shaders ! = null ) shaders . Dispose ( ) ;
shaders = new ShaderManager ( ) ;
2007-06-15 18:30:55 +00:00
}
#endregion
#region = = = = = = = = = = = = = = = = = = Initialization
// This initializes the graphics
public bool Initialize ( )
{
PresentParameters displaypp ;
DeviceType devtype ;
2007-07-07 09:40:34 +00:00
// Start DirectX
Direct3D . Initialize ( ) ;
2007-06-15 18:30:55 +00:00
// Use default adapter
2007-06-26 09:09:54 +00:00
this . adapter = 0 ; // Manager.Adapters.Default.Adapter;
2007-06-15 18:30:55 +00:00
// Make present parameters
displaypp = CreatePresentParameters ( adapter ) ;
// Determine device type for compatability with NVPerfHUD
2007-06-26 09:09:54 +00:00
if ( Direct3D . Adapters [ adapter ] . Details . Description . EndsWith ( NVPERFHUD_ADAPTER ) )
2007-06-15 18:30:55 +00:00
devtype = DeviceType . Reference ;
else
devtype = DeviceType . Hardware ;
// Get the device capabilities
2007-06-26 09:09:54 +00:00
devicecaps = Direct3D . GetDeviceCaps ( adapter , devtype ) ;
2007-06-15 18:30:55 +00:00
try
{
// Check if this adapter supports TnL
2007-06-26 09:09:54 +00:00
if ( ( devicecaps . DeviceCaps & DeviceCaps . HWTransformAndLight ) ! = 0 )
2007-06-15 18:30:55 +00:00
{
// Initialize with hardware TnL
2007-06-26 09:09:54 +00:00
device = new Device ( adapter , devtype , rendertarget . Handle ,
2007-06-15 18:30:55 +00:00
CreateFlags . HardwareVertexProcessing , displaypp ) ;
}
else
{
// Initialize with software TnL
2007-06-26 09:09:54 +00:00
device = new Device ( adapter , devtype , rendertarget . Handle ,
2007-06-15 18:30:55 +00:00
CreateFlags . SoftwareVertexProcessing , displaypp ) ;
}
}
catch ( Exception )
{
// Failed
MessageBox . Show ( General . MainWindow , "Unable to initialize the Direct3D video device. Another application may have taken exclusive mode on this video device." , Application . ProductName , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return false ;
}
// Add event to cancel resize event
2007-06-26 09:09:54 +00:00
//device.DeviceResizing += new CancelEventHandler(CancelResize);
2007-10-21 04:07:36 +00:00
// Create renderers
renderer2d = new Renderer2D ( this ) ;
renderer3d = new Renderer3D ( this ) ;
2007-10-19 14:27:46 +00:00
2007-06-15 18:30:55 +00:00
// Initialize settings
SetupSettings ( ) ;
// Done
return true ;
}
// This is to disable the automatic resize reset
private static void CancelResize ( object sender , CancelEventArgs e )
{
// Cancel resize event
e . Cancel = true ;
}
// This creates present parameters
private PresentParameters CreatePresentParameters ( int adapter )
{
PresentParameters displaypp = new PresentParameters ( ) ;
DisplayMode currentmode ;
// Get current display mode
2007-06-26 09:09:54 +00:00
currentmode = Direct3D . Adapters [ adapter ] . CurrentDisplayMode ;
2007-06-15 18:30:55 +00:00
// Make present parameters
displaypp . Windowed = true ;
displaypp . SwapEffect = SwapEffect . Discard ;
displaypp . BackBufferCount = 1 ;
displaypp . BackBufferFormat = currentmode . Format ;
displaypp . BackBufferWidth = rendertarget . ClientSize . Width ;
displaypp . BackBufferHeight = rendertarget . ClientSize . Height ;
displaypp . EnableAutoDepthStencil = true ;
2007-07-07 09:40:34 +00:00
displaypp . AutoDepthStencilFormat = Format . D16 ;
2007-10-19 14:27:46 +00:00
displaypp . Multisample = MultisampleType . None ;
2007-06-15 18:30:55 +00:00
displaypp . PresentationInterval = PresentInterval . Immediate ;
// Return result
return displaypp ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Resetting
2007-10-19 14:27:46 +00:00
// This registers a resource
public void RegisterResource ( ID3DResource res )
{
// Add resource
resources . Add ( res ) ;
}
// This unregisters a resource
public void UnregisterResource ( ID3DResource res )
{
// Remove resource
resources . Remove ( res ) ;
}
2007-06-15 18:30:55 +00:00
// This resets the device and returns true on success
2007-06-16 19:53:51 +00:00
public bool Reset ( )
2007-06-15 18:30:55 +00:00
{
PresentParameters displaypp ;
2007-10-19 14:27:46 +00:00
// Unload all Direct3D resources
foreach ( ID3DResource res in resources ) res . UnloadResource ( ) ;
2007-10-20 12:34:27 +00:00
if ( shaders ! = null ) shaders . Dispose ( ) ;
2007-10-19 17:05:21 +00:00
2007-06-15 18:30:55 +00:00
// Make present parameters
displaypp = CreatePresentParameters ( adapter ) ;
try
{
// Reset the device
2007-06-24 18:56:43 +00:00
device . Reset ( displaypp ) ;
2007-06-15 18:30:55 +00:00
}
catch ( Exception )
{
// Failed to re-initialize
return false ;
}
// Initialize settings
SetupSettings ( ) ;
2007-10-19 14:27:46 +00:00
// Reload all Direct3D resources
foreach ( ID3DResource res in resources ) res . ReloadResource ( ) ;
2007-06-15 18:30:55 +00:00
// Success
return true ;
}
#endregion
2007-06-24 18:56:43 +00:00
#region = = = = = = = = = = = = = = = = = = Rendering
// This begins a drawing session
2007-10-20 13:06:05 +00:00
public bool StartRendering ( int backcolor )
2007-06-24 18:56:43 +00:00
{
2007-06-26 09:09:54 +00:00
CooperativeLevel coopresult ;
2007-06-24 18:56:43 +00:00
// When minimized, do not render anything
if ( General . MainWindow . WindowState ! = FormWindowState . Minimized )
{
// Test the cooperative level
2007-06-26 09:09:54 +00:00
coopresult = device . CheckCooperativeLevel ( ) ;
2007-06-24 18:56:43 +00:00
// Check if device must be reset
2007-06-26 09:09:54 +00:00
if ( coopresult = = CooperativeLevel . DeviceNotReset )
2007-06-24 18:56:43 +00:00
{
// Device is lost and must be reset now
return Reset ( ) ;
}
// Check if device is lost
2007-06-26 09:09:54 +00:00
else if ( coopresult = = CooperativeLevel . DeviceLost )
2007-06-24 18:56:43 +00:00
{
// Device is lost and cannot be reset now
return false ;
}
// Clear the screen
2007-10-20 13:06:05 +00:00
device . Clear ( ClearFlags . Target | ClearFlags . ZBuffer , backcolor , 1f , 0 ) ;
2007-06-24 18:56:43 +00:00
// Ready to render
device . BeginScene ( ) ;
return true ;
}
else
{
// Minimized, you cannot see anything
return false ;
}
}
// This ends a drawing session
public void FinishRendering ( )
{
try
{
// Done
device . EndScene ( ) ;
// Display the scene
device . Present ( ) ;
}
// Errors are not a problem here
catch ( Exception ) { }
}
#endregion
#region = = = = = = = = = = = = = = = = = = Tools
// Make a color from ARGB
public static int ARGB ( float a , float r , float g , float b )
{
return Color . FromArgb ( ( int ) ( a * 255f ) , ( int ) ( r * 255f ) , ( int ) ( g * 255f ) , ( int ) ( b * 255f ) ) . ToArgb ( ) ;
}
// Make a color from RGB
public static int RGB ( int r , int g , int b )
{
return Color . FromArgb ( 255 , r , g , b ) . ToArgb ( ) ;
}
// This makes a Vector3 from Vector3D
public static Vector3 V3 ( Vector3D v3d )
{
return new Vector3 ( v3d . x , v3d . y , v3d . z ) ;
}
// This makes a Vector3D from Vector3
public static Vector3D V3D ( Vector3 v3 )
{
return new Vector3D ( v3 . X , v3 . Y , v3 . Z ) ;
}
#endregion
2007-06-15 18:30:55 +00:00
}
}