file Graphics - CPP /// /// Authors: Khan Sweetman
file Graphics - CPP /// /// Authors: Khan Sweetman
///
///
\file Graphics.cpp
///
///
Authors: Khan Sweetman
///
Copyright 2014, Digipen Institute of Technology
///
///////////////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
"Precompiled.h"
<algorithm>
"Factory.h"
"Graphics.h"
"GraphicsSpaceConfig.h"
"InputUpdate.h"
"ParticleEmitter.h"
"Sprite.h"
"SpriteText.h"
"WinCreate.h"
namespace Transmission
{
//////////////////////////
//////////////////////////
//////////////////////// Forward Declarations ////////////////////////
//////////////////////////
//////////////////////////
void OutputShaderErrorMessage(ID3D10Blob * errorMessage, HWND hWnd, LPCSTR
shaderFilename);
//////////////////////////////
//////////////////////////////
//////////////////////////// Global stuff /////////////////////////////
//////////////////////////////
//////////////////////////////
bool DebugDraw = false;
bool GlobalLightEnabled = false;
bool ZoomOverride = false;
Graphics * GRAPHICS = NULL;
std::vector<SpriteText*>gTextList;
float TARGET_WIDTH = 1600.0f;
float TARGET_HEIGHT = 900.0f;
float TARGET_ASPECT = TARGET_WIDTH / TARGET_HEIGHT;
bool IsWindowsAtLeast(DWORD major, DWORD minor, WORD spMajor, WORD spMinor)
{
DWORDLONG condition = 0;
OSVERSIONINFOEX info = { sizeof(info) };
info.dwMajorVersion = major;
info.dwMinorVersion = minor;
info.wServicePackMajor = spMajor;
info.wServicePackMinor = spMinor;
VER_SET_CONDITION(condition,
VER_SET_CONDITION(condition,
VER_SET_CONDITION(condition,
VER_SET_CONDITION(condition,
VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
Graphics::Graphics(void)
:
FullscreenOn(fullscreenboolean),
VSyncEnabled(VSYNC),
ScreenDepth(SCREEN_DEPTH),
ScreenNear(SCREEN_NEAR),
_camera(0),
_D3D(NULL),
_assetManager(NULL),
lightShader_(0),
m_fontShader(0),
pBlendState(0),
Initialized(false),
GlowOn(true),
ShadowsEnabled(false),
LoadingSprite(0)
{
GRAPHICS = this;
}
Graphics::~Graphics() { ShutdownGraphics(); }
// Getters //
std::string Graphics::GetName()
{ return "Graphics"; }
Vec2 Graphics::GetWorldCameraPosition()
{
return Vec2(_camera->GetPosition().x * WINDOWSSYSTEM->GetWindowWidth() / GRAPHICS>Zoom(),
_camera->GetPosition().y * WINDOWSSYSTEM->GetWindowHeight() / GRAPHICS>Zoom());
}
Vec2 Graphics::GetSpecialCameraPosition()
{
return Vec2(_camera->GetPosition().x * WINDOWSSYSTEM->GetWindowWidth(),
_camera->GetPosition().y * WINDOWSSYSTEM->GetWindowHeight());
}
// Setters //
void Graphics::SetScreenCameraPosition(float x, float y)
{ _camera->SetPosition(x, y,
-10.0f); }
void Graphics::SetScreenCameraPosition(Vec3 pos)
{ _camera->SetPosition(pos); }
void Graphics::SetWorldCameraPosition(float x, float y)
{
_camera->SetPosition(x * WINDOWSSYSTEM->GetInverseWidth() / GRAPHICS->Zoom(),
y * WINDOWSSYSTEM->GetInverseHeight() / GRAPHICS->Zoom(),
-10.0f);
}
void Graphics::SetWorldCameraPosition(Vec2 pos)
{
_camera->SetPosition(pos.x * WINDOWSSYSTEM->GetInverseWidth() / GRAPHICS->Zoom(),
pos.y * WINDOWSSYSTEM->GetInverseHeight() / GRAPHICS->Zoom(),
-10.0f);
}
void Graphics::SetSpecialCameraPosition(Vec2 pos)
{
_camera->SetPosition(pos.x * WINDOWSSYSTEM->GetInverseWidth(),
pos.y * WINDOWSSYSTEM->GetInverseHeight(),
-10.0f);
}
// Getter-Setters
LightShaderClass::LightBufferType& Graphics::AmbientLightInfo() { return lightShader_>m_lightInfo; }
float& Graphics::Zoom()
{ return _camera->Zoom(); }
void Graphics::Init()
{
// Inits early to clear the screen
// if check is to prevent redundant init
// TODO:
// Use to make a load screen in the opening
if (_D3D != NULL)
return;
_D3D = new D3DClass();
if(!_D3D->Init(VSyncEnabled, FullscreenOn, ScreenDepth, ScreenNear))
MessageBox(WINDOWSSYSTEM->GethWnd(), "D3D messed up.", "Error", MB_OK);
// Clear to black
_D3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);
_D3D->EndScene();
// Init member variables
_camera = new Camera();
_camera->SetPosition(0.0f, 0.0f, -10.0f);
_assetManager = new AssetManager();
_assetManager->Initialize();
LoadingSprite = new Sprite(std::string("Button_Credits"));
LoadingSprite->Init();
LoadBlendState();
// Register components with Introspection system
Sprite sprite;
sprite.RegisterInfo();
Camera camera;
camera.RegisterInfo();
SpriteText spriteText;
spriteText.RegisterInfo();
ParticleEmitter emitter;
emitter.RegisterInfo();
GraphicsSpaceConfig config;
config.RegisterInfo();
// Init shaders
lightShader_ = new LightShaderClass();
if(!lightShader_->Initialize(_D3D->GetDevice(), WINDOWSSYSTEM->GethWnd()))
MessageBox(WINDOWSSYSTEM->GethWnd(), "Light shader failed to initialize", "Error",
MB_OK);
// Update vertices
_assetManager->CollectVertices(&LoadingSprite);
_assetManager->SetVI();
// Draw the load sprite
lightShader_->Render(_D3D->GetDeviceContext(), _assetManager->GetIndexCount(),
world, view, proj, *LoadingSprite->GetTexture());
// Swap buffers
_D3D->EndScene();
}
void Graphics::Update(float dt, Space* currSpace)
{
// Debug keys
// L : Enable/Disable light
if (INPUT->CheckPressed(InputID::LCONTROL) && currSpace == ENGINE->GetActiveSpaces()
[0])
{
if (INPUT->CheckTriggered(InputID::L))
Transmission::GlobalLightEnabled = !Transmission::GlobalLightEnabled;
if (INPUT->CheckTriggered(InputID::K))
ZoomOverride = !ZoomOverride;
}
if (ZoomOverride)
Zoom() = 1.0f;
// Don't update while minimized
if (minimizedboolean || currSpace->GetDead())
return;
// Matrices
D3DXMATRIX worldMatrix, viewMatrix, orthoMatrix;
_camera->GetViewMatrix(viewMatrix);
_D3D->CalculateOrthoMatrix(_camera->Zoom());
_D3D->GetOrthoMatrix(orthoMatrix);
if (currSpace == ENGINE->GetActiveSpaces()[0])
{
// Clear the screen
_D3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);
_camera->Render();
}
//////////////////
// Light stuff
// Uses Jesse's raycasting thing to collect vertices
// Puts them together into a mesh
// - Currently just uses an arbitrary mesh
// - Uses an arbitrary index count
// Call SetStencilBufferFOV() to make draws modify the stencil buffer
// Draw the mesh
// Call SetStencilBufferNormal() to make draws happen relatively normally
// Draw everything with the stencil test on
//if (ShadowsEnabled)
//{
float sBottom;
// Draw the frustum outline for debugging
if (DebugDraw)
{
DrawLine(Vec2(fLeft + 10, fBottom + 10), Vec2(fRight - 10, fBottom + 10));
DrawLine(Vec2(fRight - 10, fBottom + 10), Vec2(fRight - 10, fTop - 10));
DrawLine(Vec2(fRight - 10, fTop - 10), Vec2(fLeft + 10, fTop - 10));
DrawLine(Vec2(fLeft + 10, fTop - 10),
Vec2(fLeft + 10, fBottom + 10));
}
//////////////////
// Draw all the sprites
for (std::list<BaseComponent*>::iterator it = sprites.begin(); it != sprites.end(); ++it)
{
sprite = static_cast<Sprite*>(*it);
transform = *static_cast<Transform*>(sprite->GetObject()->GetComponent(CT_Transform));
// Sprite location
sRight = transform.GetPosition().x + transform.GetScale().x * 0.5f;
sLeft = transform.GetPosition().x - transform.GetScale().x * 0.5f;
sTop = transform.GetPosition().y + transform.GetScale().y * 0.5f;
sBottom = transform.GetPosition().y - transform.GetScale().y * 0.5f;
// Debug drawing
if (DebugDraw)
{
DrawLine(Vec2(sLeft, sBottom), Vec2(sRight, sBottom));
DrawLine(Vec2(sRight, sBottom), Vec2(sRight, sTop));
DrawLine(Vec2(sRight, sTop), Vec2(sLeft, sTop));
DrawLine(Vec2(sLeft, sTop),
Vec2(sLeft, sBottom));
DrawLine(Vec2(sLeft, sBottom), Vec2(sRight, sTop));
}
// Frustum culling
if (sLeft > fRight
|| sRight < fLeft
|| sTop < fBottom
|| sBottom > fTop)
continue;
// Skip if this component got destroyed at some point
if (!sprite->Visible())
continue;
// Update the sprite's frame
sprite->Update(dt);
// Move onTop sprites to a separate list to draw after other sprites
if (sprite->m_onTop)
{
topSprites.push_back(sprite);
continue;
}
// Calculate the transform of the model being drawn
worldMatrix = transform.GetMatrix();
// Update vertices
_assetManager->CollectVertices(&sprite);
_assetManager->SetVI();
//Actually draw it
lightShader_->Render(_D3D->GetDeviceContext(), _assetManager->GetIndexCount(),
worldMatrix, viewMatrix, orthoMatrix, *sprite->GetTexture());
}
//////////////////
//////////////////
// Draw particles
std::list<BaseComponent*> particles = currSpace->GetComponentList(CT_ParticleEmitter);
for (auto it = particles.begin(); it != particles.end(); ++it)
static_cast<ParticleEmitter*>(*it)->Update(dt);
//////////////////
//////////////////
// Draw the onTop sprites
for (std::vector<Sprite*>::iterator it = topSprites.begin(); it != topSprites.end(); ++it)
{
sprite = static_cast<Sprite*>(*it);
transform = *static_cast<Transform*>(sprite->GetObject()->GetComponent(CT_Transform));
// Calculate the transform of the model being drawn
worldMatrix = transform.GetMatrix();
// Update vertices
_assetManager->CollectVertices(&sprite);
_assetManager->SetVI();
//Actually draw it
lightShader_->Render(_D3D->GetDeviceContext(), _assetManager->GetIndexCount(),
worldMatrix, viewMatrix, orthoMatrix, *sprite->GetTexture());
}
//////////////////
//////////////////
// Draw text
std::list<BaseComponent*> texts = currSpace->GetComponentList(CT_SpriteText);
for (auto it = texts.begin(); it != texts.end(); ++it)
static_cast<SpriteText*>(*it)->Draw(gDeviceContext, viewMatrix, orthoMatrix);
//////////////////
// Update the glow
if(GlowOn)
lightShader_->UpdateGlow(dt);
// Draw the tweak bar(s)
TwDraw();
// Swap buffers
if (currSpace == ENGINE->GetActiveSpaces().back())
_D3D->EndScene();
}
///////////////////
////////////////////
///////////////// Helper Functions //////////////////
///////////////////
////////////////////
vertices[0].position
vertices[1].position
vertices[2].position
vertices[3].position
vertices[4].position
vertices[5].position
=
=
=
=
=
=
vertices[0].texture
vertices[1].texture
vertices[2].texture
vertices[3].texture
vertices[4].texture
vertices[5].texture
=
=
=
=
=
=
// Color
vertices[0].color
vertices[1].color
vertices[2].color
vertices[3].color
vertices[4].color
vertices[5].color
D3DXVECTOR4(1.0f,
D3DXVECTOR4(1.0f,
D3DXVECTOR4(1.0f,
D3DXVECTOR4(1.0f,
D3DXVECTOR4(1.0f,
D3DXVECTOR4(1.0f,
=
=
=
=
=
=
D3DXVECTOR2(0.0f,
D3DXVECTOR2(0.0f,
D3DXVECTOR2(1.0f,
D3DXVECTOR2(0.0f,
D3DXVECTOR2(1.0f,
D3DXVECTOR2(1.0f,
// Bottom left
// Top left
// Top right
// Bottom left
// Top right
// Bottom right
1.0f);
0.0f);
0.0f);
1.0f);
0.0f);
1.0f);
1.0f,
1.0f,
1.0f,
1.0f,
1.0f,
1.0f,
1.0f,
1.0f,
1.0f,
1.0f,
1.0f,
1.0f,
1.0f);
1.0f);
1.0f);
1.0f);
1.0f);
1.0f);
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT r = D3DClass::GetDeviceContext()->Map(_assetManager->m_vertexBuffer, 0,
D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(r))
perror("Light buffer failed");
// Copy the calculated vertices into the vertex buffer
VERTEX* pVertices = (VERTEX*)mappedResource.pData;
memcpy(pVertices, vertices, sizeof(VERTEX) * 6);
gDeviceContext->Unmap(_assetManager->m_vertexBuffer, 0);
_assetManager->SetVI();
delete[] vertices;
}
void Graphics::ToggleAmbientLighting()
{
if (lightShader_->m_lightInfo.range < 5000)
lightShader_->m_lightInfo.range = 10000;
else
lightShader_->m_lightInfo.range = 375;
}
float Graphics::GetAmbientLightRange()
{
return lightShader_->m_lightInfo.range;
}
D3DXVECTOR4 Graphics::GetAmbientLightTint()
{
return lightShader_->m_lightInfo.tint;
}
void Graphics::SetAmbientLightRange(float range)
{
lightShader_->m_lightInfo.range = range;
}
void Graphics::SetAmbientLightTint(D3DXVECTOR4 tint)
{
lightShader_->m_lightInfo.tint = tint;
}
void Graphics::ToggleShadowcasting()
{
ShadowsEnabled = !ShadowsEnabled;
}
//////////////
//////////////
//////////// Debug Stuff ////////////
//////////////
//////////////
void Graphics::ToggleDebug()
{
if (DebugDraw == true)
GRAPHICS->TurnDebugOff();
else
GRAPHICS->TurnDebugOn();
}
// Sets the raster fillmode to wireframe
void Graphics::TurnDebugOn()
{
DebugDraw = true;
D3D11_RASTERIZER_DESC rasterizerDesc;
rasterizerDesc.AntialiasedLineEnable = false;
// Whether or not to use line antialiasing. Only applies if MultisampleEnable is false
rasterizerDesc.CullMode
= D3D11_CULL_BACK;
// Indicates what triangles not to
draw
rasterizerDesc.DepthBias
= 0;
// Depth value added to a given pixel
rasterizerDesc.DepthBiasClamp
= 0.f;
// Maximim depth bias of a pixel
rasterizerDesc.DepthClipEnable
= true;
// Enables distance-based clipping
rasterizerDesc.FillMode
= D3D11_FILL_WIREFRAME; // D3D11_FILL_WIREFRAME to
switch to wireframe mode. (D3D11_FILL_SOLID for normal)
rasterizerDesc.FrontCounterClockwise = false;
// Determines how DirectX determines
which triangles are facing forward
rasterizerDesc.MultisampleEnable
= false;
// Specifies whether we are using
quadrilateral or alpha line anti-aliasing
rasterizerDesc.ScissorEnable
= false;
// Enables scissor-rectangle culling. Pixels
outside an active scissor range are not drawn.
rasterizerDesc.SlopeScaledDepthBias = 0.0f;
// Scalar on a given pixel's slope
// Actually creating the rasterizer state
HRESULT result = gDevice->CreateRasterizerState(&rasterizerDesc, &_D3D>m_rasterizerState);
if (FAILED(result))
assert(0);
// Setting the rasterizer state
gDeviceContext->RSSetState(_D3D->m_rasterizerState);
}
// Sets the raster fillmode to solid
void Graphics::TurnDebugOff()
{
DebugDraw = false;
D3D11_RASTERIZER_DESC rasterizerDesc;
rasterizerDesc.AntialiasedLineEnable = false;
// Whether or not to use line anti-aliasing.
Only applies if MultisampleEnable is false
rasterizerDesc.CullMode
= D3D11_CULL_BACK; // Indicates what triangles not to draw
rasterizerDesc.DepthBias
= 0;
// Depth value added to a given pixel
rasterizerDesc.DepthBiasClamp
= 0.f;
// Maximim depth bias of a pixel
rasterizerDesc.DepthClipEnable
= true;
// Enables distance-based clipping
rasterizerDesc.FillMode
= D3D11_FILL_SOLID; // D3D11_FILL_WIREFRAME to switch to
wireframe mode. (D3D11_FILL_SOLID for normal)
rasterizerDesc.FrontCounterClockwise = false;
// Determines how DirectX determines
which triangles are facing forward
rasterizerDesc.MultisampleEnable
= false;
// Specifies whether we are using
quadrilateral or alpha line anti-aliasing
rasterizerDesc.ScissorEnable
= false;
// Enables scissor-rectangle culling. Pixels
outside an active scissor range are not drawn.
rasterizerDesc.SlopeScaledDepthBias = 0.0f;
// Scalar on a given pixel's slope
// Actually creating the rasterizer state
HRESULT result = gDevice->CreateRasterizerState(&rasterizerDesc, &_D3D>m_rasterizerState);
if (FAILED(result))
assert(0);
// Setting the rasterizer state
gDeviceContext->RSSetState(_D3D->m_rasterizerState);
}
// Pixel coordinates
void Graphics::DrawLine(Vec2 startPoint, Vec2 endPoint)
{
lightShader_->DisableLight(NULL);
VERTEX* vertices = new VERTEX[2];
vertices[0].position = D3DXVECTOR3(startPoint.x * WINDOWSSYSTEM->GetInverseWidth(),
startPoint.y * WINDOWSSYSTEM->GetInverseHeight(), 0.0f);
vertices[1].position = D3DXVECTOR3(endPoint.x * WINDOWSSYSTEM->GetInverseWidth(),
endPoint.y * WINDOWSSYSTEM->GetInverseHeight(), 0.0f);
vertices[0].texture = D3DXVECTOR2(0.5f, 0.5f);
vertices[1].texture = D3DXVECTOR2(0.5f, 0.5f);
vertices[0].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
vertices[1].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT r = D3DClass::GetDeviceContext()->Map(_assetManager->m_vertexBuffer, 0,
D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(r))
perror("Sprite buffer failed");
// Copy the vertices into the vertex buffer
VERTEX* pVertices = (VERTEX*)mappedResource.pData;
memcpy(pVertices, vertices, sizeof(VERTEX) * 2);
D3DClass::GetDeviceContext()->Unmap(_assetManager->m_vertexBuffer, 0);
delete[] vertices;
UINT stride[2] = { sizeof(VERTEX), sizeof(InstanceData) };
UINT offset[2] = { 0, 0 };
ID3D11Buffer* bufferPtrs[2] = { _assetManager->m_vertexBuffer, _assetManager>m_blankBuffer };
gDeviceContext->IASetVertexBuffers(0, 2, bufferPtrs, stride, offset);
gDeviceContext->IASetIndexBuffer(_assetManager->m_indexBuffer, DXGI_FORMAT_R32_UINT,
0);
// Matrices
D3DXMATRIX world, view, ortho;
D3DXMatrixIdentity(&world);
_camera->GetViewMatrix(view);
_D3D->CalculateOrthoMatrix(_camera->Zoom());
_D3D->GetOrthoMatrix(ortho);
// Draw
gDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
lightShader_->Render(gDeviceContext, 2, world, view, ortho, _textureList[0]->_texture);
}
void Graphics::ShutdownGraphics(void)
{
if(lightShader_)
{
lightShader_->Shutdown();
delete lightShader_;
lightShader_ = 0;
}
if(gSpriteList.size() != 0)
{
gSpriteList.clear();
}
if(_assetManager)
{
delete _assetManager;
_assetManager = 0;
}
if(_camera)
{
delete _camera;
_camera = 0;
}
if(_D3D)
{
_D3D->Shutdown();
delete _D3D;
_D3D = 0;
}
delete m_fontShader;
}
} // namespace : Transmission