I am experiencing an issue with wireframe within my 3D scene. For some strange reason, the wireframe is showing as incomplete in certain places. Moving the camera around makes some of the lines appear, and others disappear, instead of just being one complete wireframe. Here are a few pictures and some code. I am using SharpDX. Does anyone know what's going on?
(The following code has been trimmed down signifincantly to show only what I believe to be the relevant bits to this question)
using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DirectInput;
using SharpDX.DXGI;
using SharpDX.Windows;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Windows.Forms;
using VoidwalkerEngine.Framework.DirectX;
using VoidwalkerEngine.Framework.DirectX.Rendering;
using VoidwalkerEngine.Framework.DirectX.Shaders;
using VoidwalkerEngine.Framework.Logic;
using VoidwalkerEngine.Framework.Maths;
namespace GrimoireTacticsGame.Client
{
public class GameWindow : RenderForm
{
/**
* Client Variables
*/
public Camera Camera { get; set; }
public Keyboard Keyboard { get; set; }
public Mouse Mouse { get; set; }
public bool IsMouseLookEnabled { get; private set; }
public Point CurrentMouseLocation { get; set; }
public Stopwatch ClientTimer { get; set; }
public int RenderFrequency { get; private set; }
public VsyncLevel Vsync { get; set; }
private bool _isResizeNeeded { get; set; } = true;
private Point _mouseLockLocation { get; set; }
private float _previousFrameDeltaTime { get; set; }
private int _frameCounter;
private System.DateTime _previousDateTime;
/**
* DirectX Variables
*/
private Texture2D _depthBuffer;
private SwapChain _swapChain;
private SwapChainDescription _swapChainDescription;
private Texture2D _backBuffer = null;
private RenderTargetView _renderView = null;
private DepthStencilView _depthView = null;
private SharpDX.Direct3D11.Device _device;
private DeviceContext _graphicsCardContext;
private Factory _factory;
public PointLightShaderArgs _pointLightArgs;
private BlendState BlendState { get; set; }
private RasterizerStateDescription RasterizerState { get; set; }
public List<StaticGeometry> StaticGeometry { get; set; }
/**
* Shaders
*/
public WorldShader WorldShader;
public GameWindow()
: base("Grimoire Tactics")
{
Initialize();
}
public void InitializeDirectX()
{
// SwapChain description
_swapChainDescription = new SwapChainDescription()
{
BufferCount = 1,
ModeDescription = new ModeDescription(
this.ClientSize.Width,
this.ClientSize.Height,
new Rational(60, 1),
Format.R8G8B8A8_UNorm),
IsWindowed = true,
OutputHandle = this.Handle,
SampleDescription = new SampleDescription(1, 0),
SwapEffect = SwapEffect.Discard,
Usage = Usage.RenderTargetOutput
};
SharpDX.Direct3D11.Device.CreateWithSwapChain(
DriverType.Hardware,
DeviceCreationFlags.None,
_swapChainDescription,
out _device,
out _swapChain);
_graphicsCardContext = _device.ImmediateContext;
_factory = _swapChain.GetParent<Factory>();
_factory.MakeWindowAssociation(this.Handle, WindowAssociationFlags.IgnoreAll);
/**
* Create RasterizerState
*/
RasterizerState = new RasterizerStateDescription
{
CullMode = CullMode.None,
DepthBias = 0,
DepthBiasClamp = 0,
FillMode = FillMode.Solid,
IsAntialiasedLineEnabled = false,
IsDepthClipEnabled = false,
IsFrontCounterClockwise = false,
IsMultisampleEnabled = false,
IsScissorEnabled = false,
SlopeScaledDepthBias = 0
};
_graphicsCardContext.Rasterizer.State = new RasterizerState(_device, RasterizerState);
/**
* Create BlendState
*/
BlendStateDescription blendStateDescription = new BlendStateDescription
{
AlphaToCoverageEnable = false,
};
blendStateDescription.RenderTarget[0].IsBlendEnabled = true;
blendStateDescription.RenderTarget[0].SourceBlend = BlendOption.SourceAlpha;
blendStateDescription.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha;
blendStateDescription.RenderTarget[0].BlendOperation = BlendOperation.Add;
blendStateDescription.RenderTarget[0].SourceAlphaBlend = BlendOption.Zero;
blendStateDescription.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero;
blendStateDescription.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add;
blendStateDescription.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;
this.BlendState = new BlendState(_device, blendStateDescription);
this._graphicsCardContext.OutputMerger.BlendState = this.BlendState;
}
private void InitializeShaders()
{
WorldShader = new WorldShader(_device);
}
private void Initialize()
{
this.StaticGeometry = new List<StaticGeometry>();
this.StartPosition = FormStartPosition.CenterScreen;
this.Camera = new Camera
{
MoveSpeed = 128f,
LookSpeed = 0.50f, // 0 ~ 1 (0.50 = 50%)
Location = new Vector3(0, 0, 0),
FieldOfView = 1.0f, // 0.7 ~ 1.20
NearZ = 1f,
FarZ = 8000f,
AccelerationMultiplier = 2.5f
};
InitializeDirectX();
InitializeShaders();
InitializeGeometry();
/**
* Initialize Clock
* Probably use a DateTime instead.
*/
ClientTimer = new Stopwatch();
/**
* Setup Handlers
*/
this.KeyDown += OnKeyDown;
this.KeyUp += OnKeyUp;
this.UserResized += OnResize;
this.MouseUp += OnMouseUp;
this.MouseMove += OnMouseMove;
this.MouseDown += OnMouseDown;
this.FormClosing += OnFormClosing;
/**
* Setup User Input
*/
DirectInput input = new DirectInput();
this.Keyboard = new Keyboard(input);
this.Keyboard.Properties.BufferSize = 128;
this.Keyboard.Acquire();
this.Mouse = new Mouse(input);
this.Mouse.Properties.BufferSize = 8;
this.Mouse.Acquire();
}
private void DrawScene(float deltaTime)
{
this.Text = this.Camera.Location.ToString();
float elapsedClientTime = ClientTimer.ElapsedMilliseconds / 1000.0f;
Matrix modelViewMatrix = Camera.ModelViewMatrix;
Matrix projectionMatrix = Camera.ProjectionMatrix;
Matrix modelViewProjectionMatrix = Camera.ModelViewProjectionMatrix;
if (!WorldShader.IsBound)
{
WorldShader.Bind(_graphicsCardContext);
}
this._pointLightArgs = new PointLightShaderArgs(
new Vector3(16, 32, 16),
1024,
new Vector3(0, 0.06f, 0),
new Vector4(0.5f, 0.5f, 0.5f, 1.0f),
new Vector4(1, 1, 1, 1));
_graphicsCardContext.UpdateSubresource(ref _pointLightArgs, WorldShader.PointLightShaderArgsBuffer);
foreach (StaticGeometry geometry in this.StaticGeometry)
{
if (geometry.IsVisible)
{
Matrix worldPositionMatrix = VoidwalkerMath.CreateRotationMatrix(geometry.Rotation) * Matrix.Translation(geometry.Location);
Matrix localMatrix = worldPositionMatrix * modelViewProjectionMatrix;
worldPositionMatrix.Transpose();
localMatrix.Transpose();
_graphicsCardContext.UpdateSubresource(ref localMatrix, WorldShader.LocalMatrixBuffer);
_graphicsCardContext.UpdateSubresource(ref worldPositionMatrix, WorldShader.WorldPositionBuffer);
Vector2 textureResolution = geometry.Mesh.DiffuseMaterial.Resolution;
_graphicsCardContext.UpdateSubresource(ref textureResolution, WorldShader.TextureResolutionBuffer);
geometry.Draw(_graphicsCardContext);
}
}
}
private void OnRenderFrame()
{
if (_isResizeNeeded)
{
ResizeFrameBuffers();
}
float elapsedClientTime = ClientTimer.ElapsedMilliseconds / 1000.0f;
float currentFrameDeltaTime = elapsedClientTime - _previousFrameDeltaTime;
_previousFrameDeltaTime = elapsedClientTime;
System.DateTime dateTimeNow = System.DateTime.Now;
System.TimeSpan subtractedTime = dateTimeNow.Subtract(_previousDateTime);
if (subtractedTime.TotalSeconds >= 1)
{
this.RenderFrequency = _frameCounter;
_frameCounter = 0;
this._previousDateTime = dateTimeNow;
}
_graphicsCardContext.ClearDepthStencilView(_depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
_graphicsCardContext.ClearRenderTargetView(_renderView, Color.CornflowerBlue);
CheckKeyboardInput(currentFrameDeltaTime);
DrawScene(elapsedClientTime);
_swapChain.Present((int)this.Vsync, PresentFlags.None);
_frameCounter++;
}
private void OnKeyUp(object sender, KeyEventArgs args)
{
switch (args.KeyCode)
{
case Keys.F2:
RasterizerStateDescription previousDescription = _graphicsCardContext.Rasterizer.State.Description;
FillMode mode;
mode = previousDescription.FillMode == FillMode.Solid
? FillMode.Wireframe
: FillMode.Solid;
_graphicsCardContext.Rasterizer.State = new RasterizerState(_device, new RasterizerStateDescription
{
CullMode = previousDescription.CullMode,
DepthBias = previousDescription.DepthBias,
DepthBiasClamp = previousDescription.DepthBiasClamp,
FillMode = mode,
IsAntialiasedLineEnabled = previousDescription.IsAntialiasedLineEnabled,
IsDepthClipEnabled = previousDescription.IsDepthClipEnabled,
IsFrontCounterClockwise = previousDescription.IsFrontCounterClockwise,
IsMultisampleEnabled = previousDescription.IsMultisampleEnabled,
IsScissorEnabled = previousDescription.IsScissorEnabled,
SlopeScaledDepthBias = previousDescription.SlopeScaledDepthBias
});
break;
}
}
private void ResizeFrameBuffers()
{
Utilities.Dispose(ref _backBuffer);
Utilities.Dispose(ref _renderView);
Utilities.Dispose(ref _depthBuffer);
Utilities.Dispose(ref _depthView);
_swapChain.ResizeBuffers(_swapChainDescription.BufferCount, this.ClientSize.Width, this.ClientSize.Height, Format.Unknown, SwapChainFlags.None);
_backBuffer = Texture2D.FromSwapChain<Texture2D>(_swapChain, 0);
_renderView = new RenderTargetView(_device, _backBuffer);
_depthBuffer = new Texture2D(_device, new Texture2DDescription()
{
Format = Format.D32_Float_S8X24_UInt,
ArraySize = 1,
MipLevels = 1,
Width = this.ClientSize.Width,
Height = this.ClientSize.Height,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Default,
BindFlags = BindFlags.DepthStencil,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None
});
_depthView = new DepthStencilView(_device, _depthBuffer);
_graphicsCardContext.Rasterizer.SetViewport(new Viewport(0, 0, this.ClientSize.Width, this.ClientSize.Height, 0.0f, 1.0f));
_graphicsCardContext.OutputMerger.SetTargets(_depthView, _renderView);
Camera.AspectRatio = this.ClientSize.Width / (float)this.ClientSize.Height;
_isResizeNeeded = false;
}
}
}
Nevermind, I figured it out. I have to disable alpha blending. Should have guessed that.
blendStateDescription.RenderTarget[0].IsBlendEnabled = false;