UltimateZoneBuilder/Source/Rendering/Graphics.cs
2007-06-15 22:38:42 +00:00

295 lines
8.4 KiB
C#

#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;
using Microsoft.DirectX.Direct3D;
using System.ComponentModel;
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
internal class Graphics : IDisposable
{
#region ================== Constants
// NVPerfHUD device name
public const string NVPERFHUD_ADAPTER = "NVPerfHUD";
#endregion
#region ================== Variables
// Settings
private int adapter;
// Main objects
private Control rendertarget;
private Caps devicecaps;
private Device d3dd;
private Renderer2D renderer2d;
private Renderer3D renderer3d;
// Disposing
private bool isdisposed = false;
#endregion
#region ================== Properties
public Device Device { get { return d3dd; } }
public bool IsDisposed { get { return isdisposed; } }
public Renderer2D Renderer2D { get { return renderer2d; } }
public Renderer3D Renderer3D { get { return renderer3d; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public Graphics(Control rendertarget)
{
// Set render target
this.rendertarget = rendertarget;
// We have no destructor
GC.SuppressFinalize(this);
}
// Diposer
public void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
renderer2d.Dispose();
renderer3d.Dispose();
d3dd.Dispose();
rendertarget = null;
// Done
isdisposed = true;
}
}
#endregion
#region ================== Renderstates
// This completes initialization after the device has started or has been reset
private void SetupSettings()
{
// Setup renderstates
d3dd.SetRenderState(RenderStates.AntialiasedLineEnable, true);
d3dd.SetRenderState(RenderStates.Ambient, Color.White.ToArgb());
d3dd.SetRenderState(RenderStates.AmbientMaterialSource, (int)ColorSource.Material);
d3dd.SetRenderState(RenderStates.ColorVertex, false);
d3dd.SetRenderState(RenderStates.DiffuseMaterialSource, (int)ColorSource.Color1);
d3dd.SetRenderState(RenderStates.FillMode, (int)FillMode.Solid);
d3dd.SetRenderState(RenderStates.FogEnable, false);
d3dd.SetRenderState(RenderStates.Lighting, false);
d3dd.SetRenderState(RenderStates.LocalViewer, false);
d3dd.SetRenderState(RenderStates.NormalizeNormals, false);
d3dd.SetRenderState(RenderStates.SpecularEnable, false);
d3dd.SetRenderState(RenderStates.StencilEnable, false);
d3dd.SetRenderState(RenderStates.PointSpriteEnable, false);
d3dd.SetRenderState(RenderStates.DitherEnable, true);
d3dd.SetRenderState(RenderStates.AlphaBlendEnable, false);
d3dd.SetRenderState(RenderStates.ZEnable, false);
d3dd.SetRenderState(RenderStates.ZBufferWriteEnable, false);
d3dd.SetRenderState(RenderStates.Clipping, true);
d3dd.SetRenderState(RenderStates.CullMode, (int)Cull.CounterClockwise);
d3dd.VertexFormat = PTVertex.Format;
// Sampler settings
d3dd.SamplerState[0].MagFilter = TextureFilter.Linear;
d3dd.SamplerState[0].MinFilter = TextureFilter.Linear;
d3dd.SamplerState[0].MipFilter = TextureFilter.Linear;
// Texture addressing
d3dd.SamplerState[0].AddressU = TextureAddress.Wrap;
d3dd.SamplerState[0].AddressV = TextureAddress.Wrap;
d3dd.SamplerState[0].AddressW = TextureAddress.Wrap;
// First texture stage
d3dd.TextureState[0].ColorOperation = TextureOperation.Modulate;
d3dd.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
d3dd.TextureState[0].ColorArgument2 = TextureArgument.TFactor;
d3dd.TextureState[0].ResultArgument = TextureArgument.Current;
d3dd.TextureState[0].TextureCoordinateIndex = 0;
// No more further stages
d3dd.TextureState[1].ColorOperation = TextureOperation.Disable;
// First alpha stage
d3dd.TextureState[0].AlphaOperation = TextureOperation.Modulate;
d3dd.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
d3dd.TextureState[0].AlphaArgument2 = TextureArgument.TFactor;
// No more further stages
d3dd.TextureState[1].AlphaOperation = TextureOperation.Disable;
// Setup material
Material material = new Material();
material.Ambient = Color.White;
material.Diffuse = Color.White;
material.Specular = Color.White;
d3dd.Material = material;
}
#endregion
#region ================== Initialization
// This initializes the graphics
public bool Initialize()
{
AdapterInformation adapterinfo;
PresentParameters displaypp;
DeviceType devtype;
// Use default adapter
this.adapter = Manager.Adapters.Default.Adapter;
// Make present parameters
displaypp = CreatePresentParameters(adapter);
// Determine device type for compatability with NVPerfHUD
if(Manager.Adapters[adapter].Information.Description.EndsWith(NVPERFHUD_ADAPTER))
devtype = DeviceType.Reference;
else
devtype = DeviceType.Hardware;
// Get the device capabilities
devicecaps = Manager.GetDeviceCaps(adapter, devtype);
try
{
// Check if this adapter supports TnL
if(devicecaps.DeviceCaps.SupportsHardwareTransformAndLight)
{
// Initialize with hardware TnL
d3dd = new Device(adapter, devtype, rendertarget,
CreateFlags.HardwareVertexProcessing, displaypp);
}
else
{
// Initialize with software TnL
d3dd = new Device(adapter, devtype, rendertarget,
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
d3dd.DeviceResizing += new CancelEventHandler(CancelResize);
// Initialize settings
SetupSettings();
// Create renderers
renderer2d = new Renderer2D(this);
renderer3d = new Renderer3D(this);
// 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
currentmode = Manager.Adapters[adapter].CurrentDisplayMode;
// 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;
displaypp.AutoDepthStencilFormat = DepthFormat.D16;
displaypp.MultiSample = MultiSampleType.None;
displaypp.PresentationInterval = PresentInterval.Immediate;
// Return result
return displaypp;
}
#endregion
#region ================== Resetting
// This resets the device and returns true on success
private bool Reset()
{
PresentParameters displaypp;
// TODO: Unload all Direct3D resources
// Make present parameters
displaypp = CreatePresentParameters(adapter);
try
{
// Reset the device
d3dd.Reset(displaypp);
}
catch(Exception)
{
// Failed to re-initialize
return false;
}
// Initialize settings
SetupSettings();
// TODO: Reload all Direct3D resources
// Success
return true;
}
#endregion
}
}