Original Post
I started with C# and SlimDX (again) recently and use the dx11 tutorials at Rastertek as a guide for learning it.
Now that I am at tutorial 8 - loading an obj model - I have encountered my first serious problem. Everything looks fine when it is just a box, but anything more complex than that and parts of the model that should be obscured by parts that are in front of it a are shown. I have attached a screenshot where you can see this and a second one where you can see that a small part of the object (it's rotating) does not have that problem.
Below is my code, excluding the model loading. I do not think the problem is in there, but if anyone wants the full version let me know. I have googled around (mostly for depth problems and render problems in both SlimDX and DX11) and tried playing around with variables/parameters, but nothing so far. Also searched for depth buffer problems and what I could do about those, but creating one specifically either makes my object disappear (comparison.less) or I still have the same problem (comparison.all). Other options also did not seem to solve my problem.
[source lang="csharp"]namespace Dx11Playground
{
static class Program
{
static void Main()
{
var form = new RenderForm("Dx11 Playground");
var description = new SwapChainDescription()
{
BufferCount = 2, //BufferCount = 1,
Usage = Usage.RenderTargetOutput,
OutputHandle = form.Handle,
IsWindowed = true,
ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
SampleDescription = new SampleDescription(1, 0),
Flags = SwapChainFlags.AllowModeSwitch,
SwapEffect = SwapEffect.Discard
};
Device dx11Device;
SwapChain swapChain;
ShaderSignature shaderSignature;
VertexShader vertexShader;
PixelShader pixelShader;
Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, description, out dx11Device, out swapChain);
RenderTargetView renderTarget;
using (var resource = Resource.FromSwapChain(swapChain, 0))
renderTarget = new RenderTargetView(dx11Device, resource);
var context = dx11Device.ImmediateContext;
var viewport = new Viewport(0.0f, 0.0f, form.ClientSize.Width, form.ClientSize.Height);
context.OutputMerger.SetTargets(renderTarget);
context.Rasterizer.SetViewports(viewport);
ShaderBytecode effectByteCode = ShaderBytecode.CompileFromFile("../../render.fx", "fx_5_0");
Effect effect = new Effect(dx11Device, effectByteCode);
SamplerDescription sampleDesc = new SamplerDescription();
sampleDesc.AddressU = TextureAddressMode.Wrap;
sampleDesc.AddressV = TextureAddressMode.Wrap;
sampleDesc.AddressW = TextureAddressMode.Wrap;
sampleDesc.Filter = Filter.MinPointMagMipLinear;
SamplerState sampleState = SamplerState.FromDescription(dx11Device, sampleDesc);
Texture2D texture = Texture2D.FromFile(dx11Device, "../../testtex.jpg");
ShaderResourceView textureResource = new ShaderResourceView(dx11Device, texture);
context.PixelShader.SetShaderResource(textureResource, 0);
effect.GetVariableByName("DiffuseTex").AsResource().SetResource(textureResource);
effect.GetVariableByName("TextureSampler").AsSampler().SetSamplerState(0, sampleState);
float fieldOfView = (float)Math.PI / 4.0f;
float aspectRatio = (float)form.ClientSize.Width / form.ClientSize.Height;
Matrix view = Matrix.LookAtLH(new Vector3(0.0f, 15.0f, -40.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
Matrix projection = Matrix.PerspectiveFovLH(fieldOfView, aspectRatio, 1.0f, 250.0f);
Matrix world = Matrix.Identity;
matrixBuffer mBuf = new matrixBuffer();
mBuf.world = Matrix.Transpose(world);
mBuf.view = Matrix.Transpose(view);
mBuf.projection = Matrix.Transpose(projection);
var buf = new Buffer(dx11Device, new BufferDescription
{
Usage = ResourceUsage.Default,
SizeInBytes = Marshal.SizeOf(typeof(matrixBuffer)),
BindFlags = BindFlags.ConstantBuffer
});
var mBufData = new DataStream(Marshal.SizeOf(typeof(matrixBuffer)), true, true);
mBufData.Write(mBuf);
mBufData.Position = 0;
context.UpdateSubresource(new DataBox(0, 0, mBufData), buf, 0);
context.VertexShader.SetConstantBuffer(buf, 0);
using (var bytecode = ShaderBytecode.CompileFromFile("../../render.fx", "VShader", "vs_4_0", ShaderFlags.None, EffectFlags.None))
{
shaderSignature = ShaderSignature.GetInputSignature(bytecode);
vertexShader = new VertexShader(dx11Device, bytecode);
}
using (var bytecode = ShaderBytecode.CompileFromFile("../../render.fx", "PShader", "ps_4_0", ShaderFlags.None, EffectFlags.None))
pixelShader = new PixelShader(dx11Device, bytecode);
var elements = new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 12, 0),
new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0)};
var layout = new InputLayout(dx11Device, shaderSignature, elements);
var vertexBuffer = new Buffer(dx11Device, vertexStream,
Marshal.SizeOf(typeof(Vertex)) * vertexCount,
ResourceUsage.Default, BindFlags.VertexBuffer,
CpuAccessFlags.None, ResourceOptionFlags.None, 0);
context.InputAssembler.InputLayout = layout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, 32, 0));
context.VertexShader.Set(vertexShader);
context.PixelShader.Set(pixelShader);
float triangleRotation = 0.0f;
MessagePump.Run(form, () =>
{
context.ClearRenderTargetView(renderTarget, new Color4(0.2f, 0.4f, 0.8f));
mBuf.world = Matrix.RotationY(triangleRotation);
mBuf.world = Matrix.Transpose(mBuf.world);
triangleRotation += 0.0015f;
mBufData = new DataStream(Marshal.SizeOf(typeof(matrixBuffer)), true, true);
mBufData.Write(mBuf);
mBufData.Position = 0;
context.UpdateSubresource(new DataBox(0, 0, mBufData), buf, 0);
if (triangleRotation > 360.0f)
triangleRotation = 0.0f;
context.Draw(vertexCount, 0);
swapChain.Present(0, PresentFlags.None);
});
texture.Dispose();
vertexStream.Close();
vertexBuffer.Dispose();
layout.Dispose();
shaderSignature.Dispose();
vertexShader.Dispose();
pixelShader.Dispose();
renderTarget.Dispose();
swapChain.Dispose();
dx11Device.Dispose();
}
}
}
[/source]
[source lang="csharp"]Texture2D DiffuseTex;
sampler TextureSampler;
cbuffer matrixBuffer : register( b0 )
{
matrix world;
matrix view;
matrix projection;
}
struct VS_IN
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
float3 normal : NORMAL;
};
struct PS_IN
{
float4 position : SV_POSITION;
float2 texCoord : TEXCOORD;
float3 normal : NORMAL;
};
PS_IN VShader(VS_IN input)
{
PS_IN output = (PS_IN)0;
input.position.w = 1.0f;
output.position = mul(input.position, world);
output.position = mul(output.position, view);
output.position = mul(output.position, projection);
output.texCoord = input.texCoord;
output.normal = mul(input.normal, (float3x3)world);
output.normal = normalize(output.normal);
return output;
}
float4 PShader(PS_IN input) : SV_TARGET
{
float4 lightColour = float4(1.0f, 0.0f, 1.0f, 1.0f);
float3 lightDirection = float3(1.0f, -2.0f, 1.0f);
lightDirection = normalize(lightDirection);
lightDirection = -lightDirection;
float lightIntensity = saturate(dot(input.normal, lightDirection));
float4 colour = lightColour * lightIntensity;
return colour;
}[/source]
I hope I have given enough information, if more is required please let me know.
Now that I am at tutorial 8 - loading an obj model - I have encountered my first serious problem. Everything looks fine when it is just a box, but anything more complex than that and parts of the model that should be obscured by parts that are in front of it a are shown. I have attached a screenshot where you can see this and a second one where you can see that a small part of the object (it's rotating) does not have that problem.
Below is my code, excluding the model loading. I do not think the problem is in there, but if anyone wants the full version let me know. I have googled around (mostly for depth problems and render problems in both SlimDX and DX11) and tried playing around with variables/parameters, but nothing so far. Also searched for depth buffer problems and what I could do about those, but creating one specifically either makes my object disappear (comparison.less) or I still have the same problem (comparison.all). Other options also did not seem to solve my problem.
[source lang="csharp"]namespace Dx11Playground
{
static class Program
{
static void Main()
{
var form = new RenderForm("Dx11 Playground");
var description = new SwapChainDescription()
{
BufferCount = 2, //BufferCount = 1,
Usage = Usage.RenderTargetOutput,
OutputHandle = form.Handle,
IsWindowed = true,
ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
SampleDescription = new SampleDescription(1, 0),
Flags = SwapChainFlags.AllowModeSwitch,
SwapEffect = SwapEffect.Discard
};
Device dx11Device;
SwapChain swapChain;
ShaderSignature shaderSignature;
VertexShader vertexShader;
PixelShader pixelShader;
Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, description, out dx11Device, out swapChain);
RenderTargetView renderTarget;
using (var resource = Resource.FromSwapChain
renderTarget = new RenderTargetView(dx11Device, resource);
var context = dx11Device.ImmediateContext;
var viewport = new Viewport(0.0f, 0.0f, form.ClientSize.Width, form.ClientSize.Height);
context.OutputMerger.SetTargets(renderTarget);
context.Rasterizer.SetViewports(viewport);
ShaderBytecode effectByteCode = ShaderBytecode.CompileFromFile("../../render.fx", "fx_5_0");
Effect effect = new Effect(dx11Device, effectByteCode);
SamplerDescription sampleDesc = new SamplerDescription();
sampleDesc.AddressU = TextureAddressMode.Wrap;
sampleDesc.AddressV = TextureAddressMode.Wrap;
sampleDesc.AddressW = TextureAddressMode.Wrap;
sampleDesc.Filter = Filter.MinPointMagMipLinear;
SamplerState sampleState = SamplerState.FromDescription(dx11Device, sampleDesc);
Texture2D texture = Texture2D.FromFile(dx11Device, "../../testtex.jpg");
ShaderResourceView textureResource = new ShaderResourceView(dx11Device, texture);
context.PixelShader.SetShaderResource(textureResource, 0);
effect.GetVariableByName("DiffuseTex").AsResource().SetResource(textureResource);
effect.GetVariableByName("TextureSampler").AsSampler().SetSamplerState(0, sampleState);
float fieldOfView = (float)Math.PI / 4.0f;
float aspectRatio = (float)form.ClientSize.Width / form.ClientSize.Height;
Matrix view = Matrix.LookAtLH(new Vector3(0.0f, 15.0f, -40.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
Matrix projection = Matrix.PerspectiveFovLH(fieldOfView, aspectRatio, 1.0f, 250.0f);
Matrix world = Matrix.Identity;
matrixBuffer mBuf = new matrixBuffer();
mBuf.world = Matrix.Transpose(world);
mBuf.view = Matrix.Transpose(view);
mBuf.projection = Matrix.Transpose(projection);
var buf = new Buffer(dx11Device, new BufferDescription
{
Usage = ResourceUsage.Default,
SizeInBytes = Marshal.SizeOf(typeof(matrixBuffer)),
BindFlags = BindFlags.ConstantBuffer
});
var mBufData = new DataStream(Marshal.SizeOf(typeof(matrixBuffer)), true, true);
mBufData.Write(mBuf);
mBufData.Position = 0;
context.UpdateSubresource(new DataBox(0, 0, mBufData), buf, 0);
context.VertexShader.SetConstantBuffer(buf, 0);
using (var bytecode = ShaderBytecode.CompileFromFile("../../render.fx", "VShader", "vs_4_0", ShaderFlags.None, EffectFlags.None))
{
shaderSignature = ShaderSignature.GetInputSignature(bytecode);
vertexShader = new VertexShader(dx11Device, bytecode);
}
using (var bytecode = ShaderBytecode.CompileFromFile("../../render.fx", "PShader", "ps_4_0", ShaderFlags.None, EffectFlags.None))
pixelShader = new PixelShader(dx11Device, bytecode);
var elements = new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 12, 0),
new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0)};
var layout = new InputLayout(dx11Device, shaderSignature, elements);
var vertexBuffer = new Buffer(dx11Device, vertexStream,
Marshal.SizeOf(typeof(Vertex)) * vertexCount,
ResourceUsage.Default, BindFlags.VertexBuffer,
CpuAccessFlags.None, ResourceOptionFlags.None, 0);
context.InputAssembler.InputLayout = layout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, 32, 0));
context.VertexShader.Set(vertexShader);
context.PixelShader.Set(pixelShader);
float triangleRotation = 0.0f;
MessagePump.Run(form, () =>
{
context.ClearRenderTargetView(renderTarget, new Color4(0.2f, 0.4f, 0.8f));
mBuf.world = Matrix.RotationY(triangleRotation);
mBuf.world = Matrix.Transpose(mBuf.world);
triangleRotation += 0.0015f;
mBufData = new DataStream(Marshal.SizeOf(typeof(matrixBuffer)), true, true);
mBufData.Write(mBuf);
mBufData.Position = 0;
context.UpdateSubresource(new DataBox(0, 0, mBufData), buf, 0);
if (triangleRotation > 360.0f)
triangleRotation = 0.0f;
context.Draw(vertexCount, 0);
swapChain.Present(0, PresentFlags.None);
});
texture.Dispose();
vertexStream.Close();
vertexBuffer.Dispose();
layout.Dispose();
shaderSignature.Dispose();
vertexShader.Dispose();
pixelShader.Dispose();
renderTarget.Dispose();
swapChain.Dispose();
dx11Device.Dispose();
}
}
}
[/source]
[source lang="csharp"]Texture2D
sampler TextureSampler;
cbuffer matrixBuffer : register( b0 )
{
matrix world;
matrix view;
matrix projection;
}
struct VS_IN
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
float3 normal : NORMAL;
};
struct PS_IN
{
float4 position : SV_POSITION;
float2 texCoord : TEXCOORD;
float3 normal : NORMAL;
};
PS_IN VShader(VS_IN input)
{
PS_IN output = (PS_IN)0;
input.position.w = 1.0f;
output.position = mul(input.position, world);
output.position = mul(output.position, view);
output.position = mul(output.position, projection);
output.texCoord = input.texCoord;
output.normal = mul(input.normal, (float3x3)world);
output.normal = normalize(output.normal);
return output;
}
float4 PShader(PS_IN input) : SV_TARGET
{
float4 lightColour = float4(1.0f, 0.0f, 1.0f, 1.0f);
float3 lightDirection = float3(1.0f, -2.0f, 1.0f);
lightDirection = normalize(lightDirection);
lightDirection = -lightDirection;
float lightIntensity = saturate(dot(input.normal, lightDirection));
float4 colour = lightColour * lightIntensity;
return colour;
}[/source]
I hope I have given enough information, if more is required please let me know.