I'm having a great deal of difficulty with my camera. I have a test triangle on the screen that I've been using to troubleshoot my camera. But I'm clearly doing something incorrect in generating my camera matrix. When I turn even slightly away from head on towards the triangle, the triangle distorts wildly. I've included two screenshots, the first shows the triangle head on, and it looks correct. All three vertices appear correct and are colored correctly. But when I turn slightly away, everything distorts. You can see it in the second screenshot.
Triangle head on http://i.imgur.com/11XvT.jpg
Turned slightly left http://i.imgur.com/2cBkC.jpg
Does anyone have any advice for me?
Let me give you a peek at the code that generates this utter failure:
Camera class definition:
class Camera
{
public:
Camera(ID3D11Device*);
~Camera();
void Update();
void Draw( ID3D11DeviceContext* );
void move ( float x );
void Yaw ( float x );
void Pitch ( float x );
void Roll ( float x );
void Slew ( float x );
void Elevate ( float x );
void Accelerate( float x );
void Stop();
void ResetToStartPosition();
D3DXVECTOR3* GetPosition();
D3DXVECTOR3* GetLook();
float GetNearClippingPlane();
float GetFarClippingPlane();
void SetNearClippingPlane( float );
void SetFarClippingPlane( float );
void SetPerspectiveAngle( float );
float GetPerspectiveAngle();
float GetYaw(){ return m_yaw; }
float GetPitch(){ return m_pitch; }
float GetRoll(){ return m_roll; }
private:
HRESULT SendCameraDataToGraphicsCard( ID3D11DeviceContext* pDeviceContext );
D3DXMATRIX m_view;
D3DXMATRIX m_perspective;
D3DXMATRIX m_world;
D3DXVECTOR3 m_pos;
D3DXVECTOR3 m_look;
D3DXVECTOR3 m_up;
D3DXVECTOR3 m_right;
float m_fov;
float m_yaw;
float m_pitch;
float m_roll;
float m_vel;
float m_acc;
float m_nearClippingPlane;
float m_farClippingPlane;
ID3D11Buffer* m_ConstantBuffer;
VS_CONSTANT_BUFFER m_ConstantBufferContents;
};
Camera constructor:
Camera::Camera( ID3D11Device* pDevice )
{
m_pos = D3DXVECTOR3 (0.0f, 0.0f, -10.0f);
m_look = D3DXVECTOR3 (0.0f, 0.0f, 1.0f);
m_right = D3DXVECTOR3 (1.0f, 0.0f, 0.0f);
m_up = D3DXVECTOR3 (0.0f, 1.0f, 0.0f);
m_vel = 0.0f;
m_acc = 0.0f;
m_fov = D3DX_PI / 4.0f;
m_yaw = 0.0f;
m_pitch = 0.0f;
m_roll = 0.0f;
m_farClippingPlane = 1000.0f;
m_nearClippingPlane = 0.01f;
// Supply the vertex shader constant data.
D3DXMATRIX identity;
D3DXMatrixIdentity( &identity );
m_view = identity;
m_perspective = identity;
m_world = identity;
m_ConstantBufferContents.m_WorldViewProj = identity;
m_ConstantBufferContents.m_World = identity;
// Fill in a buffer description.
D3D11_BUFFER_DESC cbDesc;
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.ByteWidth = sizeof( VS_CONSTANT_BUFFER );
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbDesc.MiscFlags = 0;
cbDesc.StructureByteStride = 0;
// Create the buffer.
HRESULT hr = pDevice->CreateBuffer( &cbDesc, nullptr, &m_ConstantBuffer );
D3DXMatrixPerspectiveFovLH( &m_perspective, m_fov, 1.f, m_nearClippingPlane, m_farClippingPlane );
}
Camera draw function:
void Camera::Draw( ID3D11DeviceContext* pDeviceContext )
{
float yaw = D3DXToRadian( m_yaw ); // rotation around the y axis
float pitch = D3DXToRadian( m_pitch ); // rotation around the x axis
float roll = D3DXToRadian( m_roll ); // rotation around the z axis
D3DXVECTOR3 position = m_pos; // camera position
D3DXVECTOR3 up = m_up;
D3DXVECTOR3 look = m_look;
D3DXVECTOR3 right = m_right;
D3DXMATRIX rotation;
D3DXMatrixRotationYawPitchRoll(&rotation, m_yaw, m_pitch, m_roll);
D3DXVec3TransformCoord(&look, &look, &rotation);
D3DXVec3TransformCoord(&up, &up, &rotation);
D3DXVec3TransformCoord(&right, &right, &rotation);
D3DXMATRIX viewMatrix;
D3DXMatrixIdentity(&viewMatrix);
viewMatrix._11 = right.x; viewMatrix._12 = up.x; viewMatrix._13 = look.x;
viewMatrix._21 = right.y; viewMatrix._22 = up.y; viewMatrix._23 = look.y;
viewMatrix._31 = right.z; viewMatrix._32 = up.z; viewMatrix._33 = look.z;
viewMatrix._41 = - D3DXVec3Dot( &position, &right );
viewMatrix._42 = - D3DXVec3Dot( &position, &up );
viewMatrix._43 = - D3DXVec3Dot( &position, &look );
m_view = viewMatrix;
SendCameraDataToGraphicsCard( pDeviceContext );
}
Function to transfer the view projection matrix to the shader:
HRESULT Camera::SendCameraDataToGraphicsCard( ID3D11DeviceContext* pDeviceContext )
{
D3DXMATRIX worldViewProjection = m_view * m_perspective;
D3D11_MAPPED_SUBRESOURCE mappedResource;
pDeviceContext->Map( m_ConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );
VS_CONSTANT_BUFFER* dataPtr = (VS_CONSTANT_BUFFER*)mappedResource.pData;
dataPtr->m_WorldViewProj = worldViewProjection;
dataPtr->m_World = m_world;
pDeviceContext->Unmap( m_ConstantBuffer, 0 );
// Set the buffer.
pDeviceContext->VSSetConstantBuffers( 0, 1, &m_ConstantBuffer );
return S_OK; //You might want to have something real returned, dork
}
And finally, the shader:
//--------------------------------------------------------------------------------------
// Constant Buffers
//--------------------------------------------------------------------------------------
cbuffer cbPerObject //: register( b0 )
{
matrix g_mWorldViewProjection : packoffset( c0 );
matrix g_mWorld : packoffset( c4 );
}
cbuffer cbPerFrame //: register( b1 )
{
float3 g_vLightDir : packoffset( c0 );
float g_fTime : packoffset( c0.w );
float4 g_LightDiffuse : packoffset( c1 );
};
//-----------------------------------------------------------------------------------------
// Textures and Samplers
//-----------------------------------------------------------------------------------------
Texture2D g_txDiffuse : register( t0 );
SamplerState g_samLinear : register( s0 );
//--------------------------------------------------------------------------------------
// shader input/output structure
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
float4 Position : POSITION; // vertex position
float4 Color0 : COLOR0; // vertex color
};
struct VS_OUTPUT
{
float4 Position : SV_POSITION; // vertex position
float4 Diffuse : COLOR0; // vertex diffuse color (note that COLOR0 is clamped from 0..1)
};
//--------------------------------------------------------------------------------------
// This shader computes standard transform and lighting
//--------------------------------------------------------------------------------------
VS_OUTPUT RenderSceneVS( VS_INPUT input )
{
VS_OUTPUT Output;
float3 vNormalWorldSpace;
// Transform the position from object space to homogeneous projection space
Output.Position = mul( input.Position, g_mWorldViewProjection );
// Calc diffuse color
Output.Diffuse = input.Color0;
return Output;
}
//--------------------------------------------------------------------------------------
// This shader outputs the pixel's color by modulating the texture's
// color with diffuse material color
//--------------------------------------------------------------------------------------
float4 RenderScenePS( VS_OUTPUT In ) : SV_TARGET
{
return In.Diffuse;
}
Well, that ended up being quite the code dump, and I apologize for that. I just feel at my wits end as I've been struggling and googling and trying a billion different things to make it work. But at least I've gotten this far!
Thanks to everyone who takes a look, and even if you don't have anything to offer, I hope you all have a great weekend!