Related
I am trying to make a simple d3d11 program to rotate a cube.
But ultimately the cube doesnt seem to appear.
Only the screen is being cleared to blue but the cube doesnot show up.
I have been using this as my source: https://learn.microsoft.com/en-us/windows/win32/direct3dgetstarted/getting-started-with-a-directx-game
The structure of my project is a
MainClass.cpp, MainClass.h (Handles window initializtion)
DeviceResources.cpp, DeviceResources.h (The Device Resources include device, context, etc.)
Renderer.cpp, Renderer.h (The renderer loads geometry and shaders. Most probably this is where i am going wrong)
Here is my Renderer.h :
#pragma once
#include <memory>
#include <Windows.h>
#include <DirectXMath.h>
#include "DeviceResources.h"
class Renderer
{
public:
Renderer(std::shared_ptr<DeviceResources> deviceResources);
~Renderer();
void CreateDeviceDependentResources();
void CreateWindowSizeDependentResources();
void Update();
void Render();
private:
HRESULT CreateShaders();
HRESULT CreateCube();
void CreateViewAndPerspective();
bool m_done = false;
std::shared_ptr<DeviceResources> m_deviceResources;
typedef struct _constantBufferStruct {
DirectX::XMFLOAT4X4 world;
DirectX::XMFLOAT4X4 view;
DirectX::XMFLOAT4X4 projection;
} ConstantBufferStruct;
static_assert((sizeof(ConstantBufferStruct) % 16) == 0, "Constant Buffer size must be 16-byte aligned");
typedef struct _vertexPositionColor {
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT3 color;
} VertexPositionColor;
typedef struct _vertexPositionColorTangent {
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT3 color;
DirectX::XMFLOAT3 tangent;
} VertexPositionColorTangent;
ConstantBufferStruct m_constantBufferData;
unsigned int m_indexCount;
unsigned int m_frameCount;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pVertexBuffer;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pIndexBuffer;
Microsoft::WRL::ComPtr<ID3D11VertexShader> m_pVertexShader;
Microsoft::WRL::ComPtr<ID3D11PixelShader> m_pPixelShader;
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_pInputLayout;
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_pInputLayoutExtended;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pConstantBuffer;
};
And here is my Renderer.cpp code :
#include "Renderer.h"
#include <fstream>
#include <ppltasks.h>
#include <stdexcept>
Renderer::Renderer(std::shared_ptr<DeviceResources> deviceResources) :
m_deviceResources(deviceResources),
m_frameCount(0)
{
m_frameCount = 0;
}
Renderer::~Renderer() {}
void Renderer::CreateDeviceDependentResources() {
auto CreateShaderTask = Concurrency::create_task([this]() {CreateShaders();
m_done = true;
});
auto CreateCubeTask = CreateShaderTask.then([this]() {CreateCube(); });
}
void Renderer::CreateWindowSizeDependentResources() {
CreateViewAndPerspective();
}
HRESULT Renderer::CreateShaders() {
HRESULT hr = S_OK;
ID3D11Device* device = m_deviceResources->GetDevice();
FILE* vShader, * pShader;
BYTE* bytes;
size_t destSize = 4096;
size_t bytesRead = 0;
bytes = new BYTE[destSize];
fopen_s(&vShader, "cubeVertexShader.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, vShader);
hr = device->CreateVertexShader(
bytes,
bytesRead,
nullptr,
&m_pVertexShader
);
D3D11_INPUT_ELEMENT_DESC iaDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
hr = device->CreateInputLayout(iaDesc,ARRAYSIZE(iaDesc), bytes, bytesRead, &m_pInputLayout);
delete bytes;
bytes = new BYTE[destSize];
bytesRead = 0;
fopen_s(&pShader, "cubePixelShader.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, pShader);
hr = device->CreatePixelShader(bytes, bytesRead, nullptr, &m_pPixelShader);
CD3D11_BUFFER_DESC cbDesc(sizeof(ConstantBufferStruct), D3D11_BIND_CONSTANT_BUFFER );
hr = device->CreateBuffer(&cbDesc, nullptr, &m_pConstantBuffer);
if (FAILED(hr))
throw std::exception("Failed to Create Constant Buffer");
fclose(vShader);
fclose(pShader);
return hr;
}
HRESULT Renderer::CreateCube() {
HRESULT hr = S_OK;
ID3D11Device* device = m_deviceResources->GetDevice();
VertexPositionColor CubeVertices[] =
{
{DirectX::XMFLOAT3(-0.5f,-0.5f,-0.5f), DirectX::XMFLOAT3(0, 0, 0),},
{DirectX::XMFLOAT3(-0.5f,-0.5f, 0.5f), DirectX::XMFLOAT3(0, 0, 1),},
{DirectX::XMFLOAT3(-0.5f, 0.5f,-0.5f), DirectX::XMFLOAT3(0, 1, 0),},
{DirectX::XMFLOAT3(-0.5f, 0.5f, 0.5f), DirectX::XMFLOAT3(0, 1, 1),},
{DirectX::XMFLOAT3(0.5f,-0.5f,-0.5f), DirectX::XMFLOAT3(1, 0, 0),},
{DirectX::XMFLOAT3(0.5f,-0.5f, 0.5f), DirectX::XMFLOAT3(1, 0, 1),},
{DirectX::XMFLOAT3(0.5f, 0.5f,-0.5f), DirectX::XMFLOAT3(1, 1, 0),},
{DirectX::XMFLOAT3(0.5f, 0.5f, 0.5f), DirectX::XMFLOAT3(1, 1, 1),},
};
unsigned short CubeIndices[] =
{
0,2,1, // -x
1,2,3,
4,5,6, // +x
5,7,6,
0,1,5, // -y
0,5,4,
2,6,7, // +y
2,7,3,
0,4,6, // -z
0,6,2,
1,3,7, // +z
1,7,5,
};
m_indexCount = ARRAYSIZE(CubeIndices);
CD3D11_BUFFER_DESC vbDesc(sizeof(CubeVertices), D3D11_BIND_VERTEX_BUFFER);
D3D11_SUBRESOURCE_DATA vData;
ZeroMemory(&vData, sizeof(D3D11_SUBRESOURCE_DATA));
vData.pSysMem = CubeVertices;
vData.SysMemPitch = 0;
vData.SysMemSlicePitch = 0;
hr = device->CreateBuffer(&vbDesc, &vData, &m_pVertexBuffer);
CD3D11_BUFFER_DESC ibDesc(sizeof(CubeIndices), D3D11_BIND_INDEX_BUFFER);
D3D11_SUBRESOURCE_DATA iData;
ZeroMemory(&iData, sizeof(D3D11_SUBRESOURCE_DATA));
iData.pSysMem = CubeIndices;
iData.SysMemPitch = 0;
iData.SysMemSlicePitch = 0;
hr = device->CreateBuffer(&ibDesc, &iData, &m_pIndexBuffer);
return hr;
}
void Renderer::CreateViewAndPerspective() {
// Use DirectXMath to create view and perspective matrices.
DirectX::XMVECTOR eye = DirectX::XMVectorSet(0.0f, 0.7f, 1.5f, 0.f);
DirectX::XMVECTOR at = DirectX::XMVectorSet(0.0f, -0.1f, 0.0f, 0.f);
DirectX::XMVECTOR up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.f);
DirectX::XMStoreFloat4x4(
&m_constantBufferData.view,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixLookAtRH(
eye,
at,
up
)
)
);
float aspectRatio = m_deviceResources->GetAspectRatio();
DirectX::XMStoreFloat4x4(
&m_constantBufferData.projection,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixPerspectiveFovRH(
DirectX::XMConvertToRadians(70),
aspectRatio,
0.01f,
100.0f
)
)
);
}
void Renderer::Update() {
DirectX::XMStoreFloat4x4(
&m_constantBufferData.world,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixRotationY(
DirectX::XMConvertToRadians(
(float)m_frameCount++
)
)
)
);
if (m_frameCount == MAXUINT) m_frameCount = 0;
}
void Renderer::Render() {
while (!m_done) {
}
ID3D11DeviceContext* context = m_deviceResources->GetDeviceContext();
ID3D11RenderTargetView* renderTarget = m_deviceResources->GetRenderTarget();
ID3D11DepthStencilView* depthStencil = m_deviceResources->GetDepthStencil();
context->UpdateSubresource(m_pConstantBuffer.Get(), 0, nullptr, &m_constantBufferData, 0, 0);
const float blue[4] = { 0.2f, 0.3f, 0.8f, 1.0f};
context->ClearRenderTargetView(renderTarget, blue);
context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
context->OMSetRenderTargets(1, &renderTarget, depthStencil);
UINT stride = sizeof(VertexPositionColor);
UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_pVertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(m_pIndexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_pInputLayout.Get());
context->VSSetShader(m_pVertexShader.Get(), nullptr, 0);
context->VSSetConstantBuffers(0, 1, m_pConstantBuffer.GetAddressOf());
context->PSSetShader(m_pPixelShader.Get(), nullptr, 0);
//context->DrawIndexed(m_indexCount, 0, 0);
context->Draw(3, 0);
}
For more reference here are the shaders:-
Vertex Shader
cbuffer ModelViewProjectionBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
float4 main(float3 Position:POSITION, float3 Color:COLOR) : SV_POSITION// main is the default function name
{
float4 pos = float4(Position, 1.0f);
// Transform the position from object space to homogeneous projection space
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
return pos;
}
Pixel Shader:
float4 main(float4 position:SV_POSITION) : SV_TARGET
{
return float4(0.9f, 0.4f, 0.2f, 1.0f);
}
Image of the output
Please help me analyze where i am going wrong.
Moreover, i am using visual studio 2019.
Edit: Some were asking a for a complete reproduction so here is the visual studio solution
https://drive.google.com/file/d/1jt6fQgbRElpc9AYpbhYOyp-HCQL3WmEF/view?usp=sharing
You're doing invalid memory accesses when reading the vertex and pixel buffers.
Also, on my computer, both shaders have a dozen of kbytes whilst the memory buffer you're reading them to has only 4096 bytes.
To fix your problem, increase the size of the memory buffer you're using to read the shader bytecode from disk and don't forget to update the elementcount in fread_s().
e.g.,
Renderer.cpp # 35
size_t destSize = 1024 * 1024; // CHANGE THE SIZE OF YOUR MEMORY BUFFER HERE
size_t bytesRead = 0;
bytes = new BYTE[destSize];
fopen_s(&vShader, "cubeVertexShader.cso", "rb");
bytesRead = fread_s(bytes, destSize * sizeof(BYTE), sizeof(BYTE), destSize, vShader);
hr = device->CreateVertexShader(
bytes,
bytesRead,
nullptr,
&m_pVertexShader
);
Do the same where you're reading the pixel shader.
PRO TIP: Pay attention to the debug output and you'll see important messages from d3d debug layer, like the one telling you that both shaders failed to be created :)
This is a question for anybody experienced with the Oculus Rift C++ SDK.
SDK Version: ovr_sdk_win_1.20.0_public
IDE: VS2013
I am trying to resolve a depth buffer problem in my code for a simplified 3D engine for the Oculus Rift DK2.
The OculusRoomTiny example supplied with the SDK is very complex as it is designed with versatility in mind. So, I've taken the SuperMinimal Sample code and used that as a basis for my engine. The SuperMinimal Sample did did not support multi-colour vertexes or depth buffers. So my code includes both.
I've had no problem creating depth buffers using Microsoft DirectX-11 libraries on PC apps so think it's an Oculus specific challenge. Note: the OculusRoomTiny example depth buffer works fine but is encapsulated in classes too complex for my code.
In my code, the Cube rendered as would be expected but inclusion of the Depth buffer only renders the world background colour.
I ripped the depth buffer code from the OculusRoomTiny_Advanced demo and am sure I have integrated it religiously.
I've posted my code for comment. Please note, it is super minimal and does not clean up the COM objects.
Any advice would be welcome as I've been playing with the code now for 6 weeks!
main.cpp
#include "d3d11.h"
#include "d3dcompiler.h"
#include "OVR_CAPI_D3D.h"
#include "DirectXMath.h"
#include "models.h"
using namespace DirectX;
#pragma comment(lib, "d3dcompiler.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
void CreateSampleModel(ID3D11Device * Device, ID3D11DeviceContext *
Context);
void RenderSampleModel(XMMATRIX * viewProj, ID3D11Device * Device, ID3D11DeviceContext * Context);
ID3D11Buffer * IndexBuffer;
ID3D11RenderTargetView * eyeRenderTexRtv[2][3];
ID3D11DepthStencilView *zbuffer[2]; // containing one for each eye
ovrLayerEyeFov ld = { { ovrLayerType_EyeFov } }; //Only using one layer Update this to an array if using several
ovrSession session;
ID3D11Device * Device;
ID3D11DeviceContext * Context;
void CreateDepthBufferForBothEyes(int eye)
{
// Create the Depth Buffer Texture
D3D11_TEXTURE2D_DESC texd;
ZeroMemory(&texd, sizeof(texd));
texd.Width = ld.Viewport[eye].Size.w;
texd.Height = ld.Viewport[eye].Size.h;
texd.ArraySize = 1;
texd.MipLevels = 1;
texd.SampleDesc.Count = 1; // This matches the RTV
texd.Format = DXGI_FORMAT_D32_FLOAT;
texd.BindFlags = D3D11_BIND_DEPTH_STENCIL;
ID3D11Texture2D *pDepthBuffer;
Device->CreateTexture2D(&texd, NULL, &pDepthBuffer);
// Describe specific properties of the Depth Stencil Buffer
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
ZeroMemory(&dsvd, sizeof(dsvd));
dsvd.Format = DXGI_FORMAT_D32_FLOAT; // Make the same as the texture format
dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
Device->CreateDepthStencilView(pDepthBuffer, &dsvd, &zbuffer[eye]);
pDepthBuffer->Release();
}
//-------------------------------------------------------------------------------------------------
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int)
{
// Init Rift and device
ovr_Initialize(0);
ovrGraphicsLuid luid;
ovr_Create(&session, &luid);
IDXGIFactory * DXGIFactory; CreateDXGIFactory1(__uuidof(IDXGIFactory), (void**)(&DXGIFactory));
IDXGIAdapter * DXGIAdapter; DXGIFactory->EnumAdapters(0, &DXGIAdapter);
D3D11CreateDevice(DXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN, 0, 0, 0, 0, D3D11_SDK_VERSION, &Device, 0, &Context);
// Create eye render buffers
for (int eye = 0; eye < 2; eye++)
{
ld.Fov[eye] = ovr_GetHmdDesc(session).DefaultEyeFov[eye];
ld.Viewport[eye].Size = ovr_GetFovTextureSize(session, (ovrEyeType)eye, ld.Fov[eye], 1.0f);
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
desc.ArraySize = 1;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
desc.Width = ld.Viewport[eye].Size.w;
desc.Height = ld.Viewport[eye].Size.h;
desc.MipLevels = 1;
desc.SampleCount = 1;
desc.StaticImage = ovrFalse;
desc.MiscFlags = ovrTextureMisc_DX_Typeless;
desc.BindFlags = ovrTextureBind_DX_RenderTarget;
ovr_CreateTextureSwapChainDX(session, Device, &desc, &ld.ColorTexture[eye]);
int textureCount = 0; ovr_GetTextureSwapChainLength(session, ld.ColorTexture[eye], &textureCount);
for (int j = 0; j < textureCount; j++) // Creates 3 backbuffers for each eye
{
ID3D11Texture2D* tex; ovr_GetTextureSwapChainBufferDX(session, ld.ColorTexture[eye], j, IID_PPV_ARGS(&tex));
D3D11_RENDER_TARGET_VIEW_DESC rtvd = { DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_RTV_DIMENSION_TEXTURE2D };
Device->CreateRenderTargetView(tex, &rtvd, &eyeRenderTexRtv[eye][j]);
}
CreateDepthBufferForBothEyes(eye);
}
// Create sample model to be rendered in VR
CreateSampleModel(Device,Context);
// Loop for some frames, then terminate
float camX = 0.0f;
float camY = 0.0f;
float camZ = 0.0f;
for (long long frameIndex = 0; frameIndex < 1000;)
{
if (GetKeyState(VK_LEFT) & 0x8000)
camX -= 0.001f;
if (GetKeyState(VK_RIGHT) & 0x8000)
camX += 0.001f;
if (GetKeyState(VK_UP) & 0x8000)
camY += 0.001f;
if (GetKeyState(VK_DOWN) & 0x8000)
camY -= 0.001f;
if (GetKeyState(VK_NEXT) & 0x8000)
camZ += 0.001f;
if (GetKeyState(VK_PRIOR) & 0x8000)
camZ -= 0.001f;
// Get pose using a default IPD
ovrPosef HmdToEyePose[2] = {{{0,0,0,1}, {-0.032f, 0, 0}},
{{0,0,0,1}, {+0.032f, 0, 0}}};
ovrPosef pose[2]; ovr_GetEyePoses(session, 0, ovrTrue, HmdToEyePose, pose, &ld.SensorSampleTime);
//for (int eye = 0; eye < 2; eye++)
// ld.RenderPose[eye] = pose[eye]; // Update the Layer description with the new head position for each eye
// Render to each eye
for (int eye = 0; eye < 2; eye++)
{
ld.RenderPose[eye] = pose[eye]; // Update the Layer description with the new head position for each eye
// Set and clear current render target, and set viewport
int index = 0; ovr_GetTextureSwapChainCurrentIndex(session, ld.ColorTexture[eye], &index);
Context->OMSetRenderTargets(1, &eyeRenderTexRtv[eye][index], zbuffer[eye]); // zbuffer[eye]
Context->ClearRenderTargetView(eyeRenderTexRtv[eye][index], new float[]{ 0.1f, 0.0f, 0.0f, 0.0f });
Context->ClearDepthStencilView(zbuffer[eye], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0);
D3D11_VIEWPORT D3Dvp; // = { 0, 0, (float)ld.Viewport[eye].Size.w, (float)ld.Viewport[eye].Size.h };
D3Dvp.TopLeftX = 0.0f;
D3Dvp.TopLeftY = 0.0f;
D3Dvp.Width = (float)ld.Viewport[eye].Size.w;
D3Dvp.Height = (float)ld.Viewport[eye].Size.h;
D3Dvp.MinDepth = 0;
D3Dvp.MaxDepth = 1;
Context->RSSetViewports(1, &D3Dvp);
pose[eye].Position.z = 2.0f + camZ; // Move camera 2m from cube
pose[eye].Position.x = camX;
pose[eye].Position.y = camY;
// Calculate view and projection matrices using pose and SDK
XMVECTOR rot = XMLoadFloat4((XMFLOAT4 *)&pose[eye].Orientation);
XMVECTOR pos = XMLoadFloat3((XMFLOAT3 *)&pose[eye].Position);
XMVECTOR up = XMVector3Rotate(XMVectorSet(0, 1, 0, 0), rot);
XMVECTOR forward = XMVector3Rotate(XMVectorSet(0, 0, 1, 0), rot);
XMMATRIX view = XMMatrixLookAtLH(pos, XMVectorAdd(pos, forward), up);
ovrMatrix4f p = ovrMatrix4f_Projection(ld.Fov[eye], 0, 1, ovrProjection_None);
XMMATRIX proj = XMMatrixTranspose(XMLoadFloat4x4((XMFLOAT4X4 *)&p));
// Render model and commit frame
RenderSampleModel(&XMMatrixMultiply(view, proj), Device, Context);
ovr_CommitTextureSwapChain(session, ld.ColorTexture[eye]);
}
// Send rendered eye buffers to HMD, and increment the frame if we're visible
ovrLayerHeader* layers[1] = { &ld.Header };
if (ovrSuccess == ovr_SubmitFrame(session, 0, nullptr, layers, 1))
frameIndex; // was frameIndex++; but changed to loop forever
}
ovr_Shutdown();
}
//---------------------------------------------------------------------------------------
// THIS CODE IS NOT SPECIFIC TO VR OR THE SDK, JUST USED TO DRAW SOMETHING IN VR
//---------------------------------------------------------------------------------------
void CreateSampleModel(ID3D11Device * Device, ID3D11DeviceContext * Context)
{
// Create Vertex Buffer
//#define V(n) (n&1?+1.0f:-1.0f), (n&2?-1.0f:+1.0f), (n&4?+1.0f:-1.0f)
//float vertices[] = { V(0), V(3), V(2), V(6), V(3), V(7), V(4), V(2), V(6), V(1), V(5), V(3), V(4), V(1), V(0), V(5), V(4), V(7) };
D3D11_BUFFER_DESC vbDesc = { sizeof(VERTEX) * NUM_OF_VERTICES, D3D11_USAGE_DEFAULT, D3D11_BIND_VERTEX_BUFFER };
D3D11_SUBRESOURCE_DATA initData = { tList };
ID3D11Buffer* VertexBuffer;
Device->CreateBuffer(&vbDesc, &initData, &VertexBuffer);
//create the index buffer
D3D11_BUFFER_DESC bd;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(short) * NUM_OF_INDICES; // 3 per triangle, 12 triangles
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
Device->CreateBuffer(&bd, NULL, &IndexBuffer);
D3D11_MAPPED_SUBRESOURCE ms;
Context->Map(IndexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, indexes, NUM_OF_INDICES * sizeof(short)); // copy the data
Context->Unmap(IndexBuffer, NULL);
// Create Vertex Shader
char* vShader = "float4x4 m;"
"struct VOut { "
" float4 position : SV_POSITION;"
" float4 color : COLOR;"
"}; "
"VOut VS(float4 p1 : POSITION, float4 colour: COLOR)"
"{"
" VOut output;"
" output.position = mul(m, p1);"
" output.color = colour;"
" return output;"
"}";
ID3D10Blob * pBlob; D3DCompile(vShader, strlen(vShader), "VS", 0, 0, "VS", "vs_4_0", 0, 0, &pBlob, 0);
ID3D11VertexShader * VertexShader;
Device->CreateVertexShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), 0, &VertexShader);
// Create Input Layout
D3D11_INPUT_ELEMENT_DESC elements[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
ID3D11InputLayout * InputLayout;
Device->CreateInputLayout(elements, 2, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), &InputLayout);
// Create Pixel Shader
char* pShader = "float4 PS(float4 position : POSITION, float4 colour : COLOR) : SV_Target { return colour; }";
D3DCompile(pShader, strlen(pShader), "PS", 0, 0, "PS", "ps_4_0", 0, 0, &pBlob, 0);
ID3D11PixelShader * PixelShader;
Device->CreatePixelShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), 0, &PixelShader);
Context->IASetInputLayout(InputLayout);
Context->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R16_UINT, 0);
UINT stride = sizeof(float) * 4U; // 7U
UINT offset = 0;
Context->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
Context->VSSetShader(VertexShader, 0, 0);
Context->PSSetShader(PixelShader, 0, 0);
}
//------------------------------------------------------
void RenderSampleModel(XMMATRIX * viewProj, ID3D11Device * Device, ID3D11DeviceContext * Context)
{
D3D11_BUFFER_DESC desc = { sizeof(XMMATRIX), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE };
D3D11_SUBRESOURCE_DATA initData = { viewProj };
ID3D11Buffer * ConstantBuffer; Device->CreateBuffer(&desc, &initData, &ConstantBuffer);
Context->VSSetConstantBuffers(0, 1, &ConstantBuffer);
Context->DrawIndexed(NUM_OF_INDICES, 0, 0);
}
models.h
#ifndef MODELS_H
#define MODELS_H
#include "DirectXMath.h"
using namespace DirectX;
#define NUM_OF_MODELS 1
struct VERTEX{
float x;
float y;
float z;
uint32_t C; // Colour
};
#define NUM_OF_VERTICES 24
#define NUM_OF_INDICES 36
extern VERTEX tList[];
extern short indexes[];
#endif
models.cpp
#include "models.h"
VERTEX tList[] = {
{ -0.1f, 0.1f, 0.2f, 0xFF0000FF }, // Cube Vertex Index 0
{ 0.1f, 0.1f, 0.2f, 0xFF0000FF }, // 1
{ -0.1f, -0.1f, 0.2f, 0xFF0000FF }, // 2
{ 0.1f, -0.1f, 0.2f, 0xFF0000FF }, // 3
{ -0.1f, 0.1f, -0.0f, 0x00FF00FF }, // 4
{ 0.1f, 0.1f, -0.0f, 0x00FF00FF }, // 5
{ -0.1f, -0.1f, -0.0f, 0x00FF00FF }, // 6
{ 0.1f, -0.1f, -0.0f, 0x00FF00FF }, // 7
{ 0.1f, 0.1f, 0.2f, 0x0000FFFF }, // 8
{ 0.1f, 0.1f, -0.0f, 0x0000FFFF }, // 9
{ 0.08f, -0.1f, 0.2f, 0x0000FFFF }, // 10 Distorted in prep to test Depth
{ 0.08f, -0.1f, -0.0f, 0x0000FFFF }, // 11 Distorted in prep to test Depth
{ -0.1f, 0.1f, 0.2f, 0xFF0000FF }, // 12
{ -0.1f, 0.1f, -0.0f, 0xFF0000FF }, // 13
{ -0.1f, -0.1f, 0.2f, 0xFF0000FF }, // 14
{ -0.1f, -0.1f, -0.0f, 0xFF0000FF }, // 15
{ -0.1f, 0.1f, -0.0f, 0x00FF00FF }, // 16
{ 0.1f, 0.1f, -0.0f, 0x00FF00FF }, // 17
{ -0.1f, 0.1f, 0.2f, 0x00FF00FF }, // 18
{ 0.1f, 0.1f, 0.2f, 0x00FF00FF }, // 19
{ -0.1f, -0.1f, -0.0f, 0x00FFFFFF }, // 20
{ 0.1f, -0.1f, -0.0f, 0x00FFFFFF }, // 21
{ -0.1f, -0.1f, 0.2f, 0x00FFFFFF }, // 22
{ 0.1f, -0.1f, 0.2f, 0x00FFFFFF }, // 23
};
short indexes[] = {
0, 1, 2, // FRONT QUAD
2, 1, 3,
5, 4, 6, // BACK QUAD
5, 6, 7,
8, 9, 11, // RIGHT QUAD
8, 11, 10,
13, 12,14, // LEFT QUAD
13, 14, 15,
18,16, 17, // TOP QUAD
18, 17, 19,
22, 23, 21, // BOTTOM QUAD
22, 21, 20
};
After much research I've found my own solution:
The line
ovrMatrix4f p = ovrMatrix4f_Projection(ld.Fov[eye], 0, 1, ovrProjection_None);
Creates the projection Matrix.
A was simply a case of setting the projection depth correctly
float zNear = 0.1f;
float zFar = 1000.0f;
ovrMatrix4f p = ovrMatrix4f_Projection(ld.Fov[eye], zNear, zFar, ovrProjection_None);
Amazing how, now 7 weeks of investigating, revealed the flaw as a simple ommission!
I am currently working on an project but my problem is that my Vertex shader gets the wrong data, so my position values aren't any longer the same as i set them at the beginning.
So this is where I define the position/anchor of my Sprite
struct SpriteVertex
{
DirectX::XMFLOAT3 position;
float radius;
int textureIndex;
};
//Sprite renderer
vector<SpriteVertex> sprite_vertices;
SpriteVertex current;
current.position.x = 0;
current.position.y = 0;
current.position.z = 0;
current.radius = 100;
current.textureIndex = 0;
sprite_vertices.push_back(current);
g_SpriteRenderer->renderSprites(pd3dImmediateContext, sprite_vertices, g_camera);
So in my SpriteRenderer Class I have the create method where I set up the Input layout and create an empty vertex buffer.
HRESULT SpriteRenderer::create(ID3D11Device* pDevice)
{
cout << "Spriterender Create has been called" << endl;
HRESULT hr;
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = 1024 * sizeof(SpriteVertex);
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
V(pDevice->CreateBuffer(&bd , nullptr, &m_pVertexBuffer));
const D3D11_INPUT_ELEMENT_DESC layout[] ={
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "RADIUS", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXTUREINDEX",0,DXGI_FORMAT_R32_SINT,0,D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
UINT numEements = sizeof(layout) / sizeof(layout[0]);
D3DX11_PASS_DESC pd;
V_RETURN(m_pEffect->GetTechniqueByName("Render")->GetPassByName("SpritePass")->GetDesc(&pd));
V_RETURN(pDevice->CreateInputLayout(layout, numEements, pd.pIAInputSignature, pd.IAInputSignatureSize, &m_pInputLayout));
return S_OK;
}
And I have the render method which fills the buffer and is supposed to render it with the shader I coded:
void SpriteRenderer::renderSprites(ID3D11DeviceContext* context, const std::vector<SpriteVertex>& sprites, const CFirstPersonCamera& camera)
{
//cout << "SpriterenderrenderSprites has been called" << endl;
D3D11_BOX box;
box.left = 0; box.right = sprites.size()*sizeof(SpriteVertex);
box.top = 0; box.bottom = 1;
box.front = 0; box.back = 1;
context->UpdateSubresource(m_pVertexBuffer,0,&box,&sprites[0],0,0);
const UINT size = sizeof(SpriteVertex);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
context->IASetInputLayout(m_pInputLayout);
context->IASetVertexBuffers(0, 0, &m_pVertexBuffer, &size, nullptr);
//setting shader resouirces
DirectX::XMMATRIX worldviewProj =camera.GetViewMatrix()*camera.GetProjMatrix();
m_pEffect->GetVariableByName("g_ViewProjection")->AsMatrix()->SetMatrix(( float* ) &worldviewProj);
m_pEffect->GetVariableByName("g_cameraRight")->AsVector()->SetFloatVector((float*) &camera.GetWorldRight());
m_pEffect->GetVariableByName("g_cameraUP")->AsVector()->SetFloatVector((float*)&camera.GetWorldUp());
m_pEffect->GetTechniqueByName("Render")->GetPassByName("SpritePass")->Apply( 0,context);
context->Draw(size,0);
}
So my big problem is that when I debug the Shaders that my inital Position radius and so on aren't even close to what I want:
Debug VS
I'm trying to fix this now for ever any help would be really appreciated.
EDIT: HLSL Code might help ;=)
//--------------------------------------------------------------------------------------
// Shader resources
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Constant buffers
//--------------------------------------------------------------------------------------
cbuffer cbCOnstant
{
matrix g_ViewProjection;
float4 g_cameraRight;
float4 g_cameraUP;
};
//--------------------------------------------------------------------------------------
// Structs
//--------------------------------------------------------------------------------------
struct SpriteVertex
{
float3 POSITION : POSITION;
float RADIUS: RADIUS;
int TEXIN : TEXTUREINDEX;
};
struct PSVertex
{
float4 POSITION : SV_Position;
int TEXIN : TEXTUREINDEX;
};
//--------------------------------------------------------------------------------------
// Rasterizer states
//--------------------------------------------------------------------------------------
RasterizerState rsCullNone
{
CullMode = None;
};
//--------------------------------------------------------------------------------------
// DepthStates
//--------------------------------------------------------------------------------------
DepthStencilState EnableDepth
{
DepthEnable = TRUE;
DepthWriteMask = ALL;
DepthFunc = LESS_EQUAL;
};
BlendState NoBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = FALSE;
};
//--------------------------------------------------------------------------------------
// Shaders
//--------------------------------------------------------------------------------------
SpriteVertex DummyVS(SpriteVertex Input)
{
return Input;
}
[maxvertexcount(4)]
void SpriteGS(point SpriteVertex vertex[1], inout TriangleStream<PSVertex> stream){
PSVertex input;
input.TEXIN = vertex[0].TEXIN;
//bottom left
input.POSITION = mul(float4(vertex[0].POSITION,1) - vertex[0].RADIUS * g_cameraRight - vertex[0].RADIUS * g_cameraUP, g_ViewProjection);
stream.Append(input);
//top left
input.POSITION = mul(float4(vertex[0].POSITION,1) - vertex[0].RADIUS * g_cameraRight + vertex[0].RADIUS * g_cameraUP, g_ViewProjection);
stream.Append(input);
//top right
input.POSITION = mul(float4(vertex[0].POSITION,1) + vertex[0].RADIUS * g_cameraRight + vertex[0].RADIUS * g_cameraUP, g_ViewProjection);
stream.Append(input);
//bot right
input.POSITION = mul(float4(vertex[0].POSITION,1) + vertex[0].RADIUS * g_cameraRight - vertex[0].RADIUS * g_cameraUP, g_ViewProjection);
stream.Append(input);
}
float4 DummyPS(PSVertex input) : SV_Target0
{
return float4(1, 1, 0, 1);
}
//--------------------------------------------------------------------------------------
// Techniques
//--------------------------------------------------------------------------------------
technique11 Render
{
pass SpritePass
{
SetVertexShader(CompileShader(vs_5_0, DummyVS()));
SetGeometryShader(CompileShader(gs_5_0, SpriteGS()));
SetPixelShader(CompileShader(ps_5_0, DummyPS()));
SetRasterizerState(rsCullNone);
SetDepthStencilState(EnableDepth,0);
SetBlendState(NoBlending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
}
}
Your binding of the vertex buffer below is wrong :
context->IASetVertexBuffers(0, 0, &m_pVertexBuffer, &size, nullptr);
The seconde arguments of ID3D11DeviceContext::IASetVertexBuffers is the number of buffer to bind, it has to be one here, and offsets has to be valid :
UINT offset = 0;
context->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &size, &offset);
As a general advice, you should turn on the debug device at creation with the flag D3D11_CREATE_DEVICE_DEBUG and look for any message in the output. On windows 10, you may have to install it first following Microsoft instructions installing the debug device
Hi I just got Introduction to 3D Game Programming with DirectX 11 and am trying to get the BoxDemo code working, however I am having troubles with the effect.
Basically the compiled shader part works, and even the creation of the effect works but when it comes to getting the description from the effect pass, I get a Access Violation error, I have tried, and researched online but can't find any help for this matter.
Please note I have the latest version of effects11.
Here is the fx:
//***************************************************************************** **********
// color.fx by Frank Luna (C) 2011 All Rights Reserved.
//
// Transforms and colors geometry.
//***************************************************************************************
cbuffer cbPerObject
{
float4x4 gWorldViewProj;
};
struct VertexIn
{
float3 PosL : POSITION;
float4 Color : COLOR;
};
struct VertexOut
{
float4 PosH : SV_POSITION;
float4 Color : COLOR;
};
VertexOut VS(VertexIn vin)
{
VertexOut vout;
// Transform to homogeneous clip space.
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
// Just pass vertex color into the pixel shader.
vout.Color = vin.Color;
return vout;
}
float4 PS(VertexOut pin) : SV_Target
{
return pin.Color;
}
technique11 ColorTech
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS()));
}
}
here is the cpp file:
#include "BoxApp.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
BoxApp theApp(hInstance);
if (!theApp.Init())
return 0;
return theApp.Run();
}
BoxApp::BoxApp(HINSTANCE hInstance)
: D3DApp(hInstance), mBoxVB(0), mBoxIB(0), mFX(0), mTech(0),
mfxWorldViewProj(0), mInputLayout(0),
mTheta(1.5f*MathHelper::Pi), mPhi(0.25f*MathHelper::Pi), mRadius(5.0f)
{
mMainWndCaption = L"Box Demo";
mLastMousePos.x = 0;
mLastMousePos.y = 0;
XMMATRIX I = XMMatrixIdentity();
XMStoreFloat4x4(&mWorld, I);
XMStoreFloat4x4(&mView, I);
XMStoreFloat4x4(&mProj, I);
}
BoxApp::~BoxApp()
{
ReleaseCOM(mBoxVB);
ReleaseCOM(mBoxIB);
ReleaseCOM(mFX);
ReleaseCOM(mInputLayout);
}
bool BoxApp::Init()
{
if (!D3DApp::Init())
return false;
BuildGeometryBuffers();
BuildFX();
BuildVertexLayout();
return true;
}
void BoxApp::OnResize()
{
D3DApp::OnResize();
// The window resized, so update the aspect ratio and recompute the projection matrix.
XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
XMStoreFloat4x4(&mProj, P);
}
void BoxApp::UpdateScene(float dt)
{
// Convert Spherical to Cartesian coordinates.
float x = mRadius*sinf(mPhi)*cosf(mTheta);
float z = mRadius*sinf(mPhi)*sinf(mTheta);
float y = mRadius*cosf(mPhi);
// Build the view matrix.
XMVECTOR pos = XMVectorSet(x, y, z, 1.0f);
XMVECTOR target = XMVectorZero();
XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
XMMATRIX V = XMMatrixLookAtLH(pos, target, up);
XMStoreFloat4x4(&mView, V);
}
void BoxApp::DrawScene()
{
md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::LightSteelBlue));
md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
md3dImmediateContext->IASetInputLayout(mInputLayout);
md3dImmediateContext- >IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
UINT stride = sizeof(Vertex);
UINT offset = 0;
md3dImmediateContext->IASetVertexBuffers(0, 1, &mBoxVB, &stride, &offset);
md3dImmediateContext->IASetIndexBuffer(mBoxIB, DXGI_FORMAT_R32_UINT, 0);
// Set constants
XMMATRIX world = XMLoadFloat4x4(&mWorld);
XMMATRIX view = XMLoadFloat4x4(&mView);
XMMATRIX proj = XMLoadFloat4x4(&mProj);
XMMATRIX worldViewProj = world*view*proj;
mfxWorldViewProj->SetMatrix(reinterpret_cast<float*>(&worldViewProj));
D3DX11_TECHNIQUE_DESC techDesc;
mTech->GetDesc(&techDesc);
for (UINT p = 0; p < techDesc.Passes; ++p)
{
mTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
// 36 indices for the box.
md3dImmediateContext->DrawIndexed(36, 0, 0);
}
HRESULT hr = (mSwapChain->Present(0, 0));
}
void BoxApp::OnMouseDown(WPARAM btnState, int x, int y)
{
mLastMousePos.x = x;
mLastMousePos.y = y;
SetCapture(mhMainWnd);
}
void BoxApp::OnMouseUp(WPARAM btnState, int x, int y)
{
ReleaseCapture();
}
void BoxApp::OnMouseMove(WPARAM btnState, int x, int y)
{
if ((btnState & MK_LBUTTON) != 0)
{
// Make each pixel correspond to a quarter of a degree.
float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
// Update angles based on input to orbit camera around box.
mTheta += dx;
mPhi += dy;
// Restrict the angle mPhi.
mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi - 0.1f);
}
else if ((btnState & MK_RBUTTON) != 0)
{
// Make each pixel correspond to 0.005 unit in the scene.
float dx = 0.005f*static_cast<float>(x - mLastMousePos.x);
float dy = 0.005f*static_cast<float>(y - mLastMousePos.y);
// Update the camera radius based on input.
mRadius += dx - dy;
// Restrict the radius.
mRadius = MathHelper::Clamp(mRadius, 3.0f, 15.0f);
}
mLastMousePos.x = x;
mLastMousePos.y = y;
}
void BoxApp::BuildGeometryBuffers()
{
// Create vertex buffer
Vertex vertices[] =
{
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::White },
{ XMFLOAT3(-1.0f, +1.0f, -1.0f), (const float*)&Colors::Black },
{ XMFLOAT3(+1.0f, +1.0f, -1.0f), (const float*)&Colors::Red },
{ XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Green },
{ XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Blue },
{ XMFLOAT3(-1.0f, +1.0f, +1.0f), (const float*)&Colors::Yellow },
{ XMFLOAT3(+1.0f, +1.0f, +1.0f), (const float*)&Colors::Cyan },
{ XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Magenta }
};
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex) * 8;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = vertices;
HRESULT hr1 = (md3dDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB));
// Create the index buffer
UINT indices[] = {
// front face
0, 1, 2,
0, 2, 3,
// back face
4, 6, 5,
4, 7, 6,
// left face
4, 5, 1,
4, 1, 0,
// right face
3, 2, 6,
3, 6, 7,
// top face
1, 5, 6,
1, 6, 2,
// bottom face
4, 0, 3,
4, 3, 7
};
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * 36;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
ibd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = indices;
HRESULT hr2 = (md3dDevice->CreateBuffer(&ibd, &iinitData, &mBoxIB));
}
void BoxApp::BuildFX()
{
DWORD shaderFlags = 0;
//#if defined( DEBUG ) || defined( _DEBUG )
// shaderFlags |= D3D10_SHADER_DEBUG;
// shaderFlags |= D3D10_SHADER_SKIP_OPTIMIZATION;
//#endif
ID3D10Blob* compiledShader = 0;
ID3D10Blob* compilationMsgs = 0;
HRESULT hr;
hr = D3DX11CompileFromFile(L"color.fx", NULL, NULL, "ColorTech", "fx_5_0"
, shaderFlags, 0, 0, &compiledShader, &compilationMsgs, &hr);
// compilationMsgs can store errors or warnings.
if (compilationMsgs != 0)
{
MessageBoxA(0, (char*)compilationMsgs->GetBufferPointer(), 0, 0);
ReleaseCOM(compilationMsgs);
}
// Even if there are no compilationMsgs, check to make sure there were no other errors.
if (FAILED(hr))
{
//DXTrace(__FILE__, (DWORD)__LINE__, hr, L"D3DX11CompileFromFile", true);
}
ID3D10Blob* pErrorBlob = 0;
//ID3DInclude* include = D3D_COMPILE_STANDARD_FILE_INCLUDE;
HRESULT hr3 = (D3DX11CreateEffectFromMemory(compiledShader->GetBufferPointer(), compiledShader->GetBufferSize(),
0, md3dDevice, &mFX));
//HRESULT hr3 = (D3DX11CreateEffectFromFile(L"color.fx", shaderFlags, md3dDevice, &mFX));
// Done with compiled shader.
ReleaseCOM(compiledShader);
mTech = mFX->GetTechniqueByName("ColorTech");
mfxWorldViewProj = mFX->GetVariableByName("gWorldViewProj")->AsMatrix();
}
void BoxApp::BuildVertexLayout()
{
// Create the vertex input layout.
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
// Create the input layout
D3DX11_PASS_DESC passDesc;
ID3DX11EffectPass* pass = mTech->GetPassByIndex(0);
if (pass != nullptr)
{
HRESULT hr5 = pass->GetDesc(&passDesc);
HRESULT hr4 = (md3dDevice->CreateInputLayout(vertexDesc, 2, passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize, &mInputLayout));
}
}
You've commented out all the error checks, so it's probably that D3DX11CreateEffectFromMemory returned a failure. If a function returns an HRESULT, you must check it at runtime or you will miss potential errors. That means using the FAILED macro, the SUCCEEDED macro, or the ThrowIfFailed helper on every function that returns an HRESULT. See MSDN.
Since you are making use of the Effects for Direct3D 11 library, you should pick up the latest version from GitHub. If you are using VS 2013 or VS 2015 for a Windows desktop app, you can also get it from NuGet.
You should also read this post which has some additional notes about the Introduction to 3D Game Programming with DirectX 11 book. It's a good book, but unfortunately it was published just before the DirectX development story was changed rather radically with the deprecation of the DirectX SDK. See MSDN.
You should also take a look at the DirectX Tool Kit tutorials, particularly the material on ComPtr.
Ok finally here is the final code
BoxDemoApp.h:
#pragma once
//#pragma comment(lib, "Effects11.lib")
#pragma comment(lib, "d3d11.lib")
//#pragma comment(lib, "d3dx11.lib")
//#pragma comment(lib, "DxErr.lib")
//#pragma comment(lib, "D3DCompiler.lib")
//#pragma comment(lib, "dxguid.lib")
#include <windows.h>
#include <d3d11_1.h>
#include "d3dApp.h"
#include "d3dx11effect.h"
#include "MathHelper.h"
#include "StaticCamera.h"
#include "Conversion.h"
#include "DefinedModel.h"
#include <iostream>
using namespace std;
class BoxDemoApp : public D3DApp
{
public:
BoxDemoApp(HINSTANCE hInstance);
~BoxDemoApp();
bool Init();
bool InitScene();
void OnResize();
void UpdateScene(float dt);
void DrawScene();
private:
DefinedModel* m_Model;
bool m_bLoaded;
bool m_bInitModel;
};
BoxDemoApp.cpp:
#include "BoxDemoApp.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
BoxDemoApp theApp(hInstance);
if (!theApp.Init())
return 0;
return theApp.Run();
}
BoxDemoApp::BoxDemoApp(HINSTANCE hInstance)
: D3DApp(hInstance)
{
mMainWndCaption = L"Box Demo";
m_bLoaded = false;
m_bInitModel = false;
m_Model = NULL;
}
BoxDemoApp::~BoxDemoApp()
{
m_Model->Destroy();
SafeDelete(m_Model);
}
bool BoxDemoApp::Init()
{
if (!D3DApp::Init())
return false;
InitScene();
return true;
}
bool BoxDemoApp::InitScene()
{
//Camera information
m_Camera->setCamera(XMFLOAT4(0.0f, 3.0f, -8.0f, 0.0f),
XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f),
XMFLOAT4(0.0f, 1.0f, 0.0f, 0.0f));
//Set the Projection matrix
m_Camera->setFOV(0.4f*3.14f, (float)mClientWidth / mClientHeight, 1.0f, 1000.0f);
///////////////**************new**************////////////////////
return true;
}
void BoxDemoApp::OnResize()
{
D3DApp::OnResize();
//Create the Viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = this->mClientWidth;
viewport.Height = this->mClientHeight;
//Set the Viewport
md3dImmediateContext->RSSetViewports(1, &viewport);
//Set the Projection matrix
m_Camera->setFOV(0.4f*3.14f, (float)mClientWidth / mClientHeight, 1.0f, 1000.0f);
///////////////**************new**************////////////////////
}
void BoxDemoApp::UpdateScene(float dt)
{
if (m_bLoaded && !m_bInitModel)
{
m_Model = new DefinedModel(this);
m_Model->create3DCube(4, 4, 4);
m_bInitModel = true;
}
}
void BoxDemoApp::DrawScene()
{
assert(md3dImmediateContext);
assert(mSwapChain);
md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::LightSteelBlue));
md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
if (m_bInitModel)
{
m_Model->Draw();
}
if (!m_bLoaded)
{
m_bLoaded = true;
}
HRESULT hr = (mSwapChain->Present(0, 0));
}
MathHelper.h:
//***************************************************************************************
// MathHelper.h by Frank Luna (C) 2011 All Rights Reserved.
//
// Helper math class.
//***************************************************************************************
#pragma once
#ifndef MATHHELPER_H
#define MATHHELPER_H
#include <Windows.h>
#include <xnamath.h>
class MathHelper
{
public:
// Returns random float in [0, 1).
static float RandF()
{
return (float)(rand()) / (float)RAND_MAX;
}
// Returns random float in [a, b).
static float RandF(float a, float b)
{
return a + RandF()*(b - a);
}
template<typename T>
static T Min(const T& a, const T& b)
{
return a < b ? a : b;
}
template<typename T>
static T Max(const T& a, const T& b)
{
return a > b ? a : b;
}
template<typename T>
static T Lerp(const T& a, const T& b, float t)
{
return a + (b - a)*t;
}
template<typename T>
static T Clamp(const T& x, const T& low, const T& high)
{
return x < low ? low : (x > high ? high : x);
}
// Returns the polar angle of the point (x,y) in [0, 2*PI).
static float AngleFromXY(float x, float y);
static XMMATRIX InverseTranspose(CXMMATRIX M)
{
// Inverse-transpose is just applied to normals. So zero out
// translation row so that it doesn't get into our inverse-transpose
// calculation--we don't want the inverse-transpose of the translation.
XMMATRIX A = M;
A.r[3] = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
XMVECTOR det = XMMatrixDeterminant(A);
return XMMatrixTranspose(XMMatrixInverse(&det, A));
}
static XMVECTOR RandUnitVec3();
static XMVECTOR RandHemisphereUnitVec3(XMVECTOR n);
static const float Infinity;
static const float Pi;
};
#endif // MATHHELPER_H
MathHelper.cpp:
//***************************************************************************************
// MathHelper.cpp by Frank Luna (C) 2011 All Rights Reserved.
//***************************************************************************************
#include "MathHelper.h"
#include <float.h>
#include <cmath>
const float MathHelper::Infinity = FLT_MAX;
const float MathHelper::Pi = 3.1415926535f;
float MathHelper::AngleFromXY(float x, float y)
{
float theta = 0.0f;
// Quadrant I or IV
if (x >= 0.0f)
{
// If x = 0, then atanf(y/x) = +pi/2 if y > 0
// atanf(y/x) = -pi/2 if y < 0
theta = atanf(y / x); // in [-pi/2, +pi/2]
if (theta < 0.0f)
theta += 2.0f*Pi; // in [0, 2*pi).
}
// Quadrant II or III
else
theta = atanf(y / x) + Pi; // in [0, 2*pi).
return theta;
}
XMVECTOR MathHelper::RandUnitVec3()
{
XMVECTOR One = XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f);
XMVECTOR Zero = XMVectorZero();
// Keep trying until we get a point on/in the hemisphere.
while (true)
{
// Generate random point in the cube [-1,1]^3.
XMVECTOR v = XMVectorSet(MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), 0.0f);
// Ignore points outside the unit sphere in order to get an even distribution
// over the unit sphere. Otherwise points will clump more on the sphere near
// the corners of the cube.
if (XMVector3Greater(XMVector3LengthSq(v), One))
continue;
return XMVector3Normalize(v);
}
}
XMVECTOR MathHelper::RandHemisphereUnitVec3(XMVECTOR n)
{
XMVECTOR One = XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f);
XMVECTOR Zero = XMVectorZero();
// Keep trying until we get a point on/in the hemisphere.
while (true)
{
// Generate random point in the cube [-1,1]^3.
XMVECTOR v = XMVectorSet(MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), 0.0f);
// Ignore points outside the unit sphere in order to get an even distribution
// over the unit sphere. Otherwise points will clump more on the sphere near
// the corners of the cube.
if (XMVector3Greater(XMVector3LengthSq(v), One))
continue;
// Ignore points in the bottom hemisphere.
if (XMVector3Less(XMVector3Dot(n, v), Zero))
continue;
return XMVector3Normalize(v);
}
}
StaticCamera.h:
#pragma once
#include "MathHelper.h"
#include "Conversion.h"
class StaticCamera
{
public:
StaticCamera();
~StaticCamera();
XMMATRIX* WVP();
XMMATRIX* World();
XMMATRIX* camView();
XMMATRIX* camProjection();
XMVECTOR* camPosition();
XMVECTOR* camTarget();
XMVECTOR* camUp();
void WVP(XMMATRIX WVP);
void World(XMMATRIX World);
void setFOV(float FOV, float aspectRatio, float nearZ, float farZ);
void setCamera(XMFLOAT4 position, XMFLOAT4 Target, XMFLOAT4 Up);
void updateMatrix();
private:
///////////////**************new**************////////////////////
XMMATRIX m_WVP;
XMMATRIX m_World;
XMMATRIX m_camView;
XMMATRIX m_camProjection;
XMVECTOR m_camPosition;
XMVECTOR m_camTarget;
XMVECTOR m_camUp;
///////////////**************new**************////////////////////
};
StaticCamera.cpp:
#include "StaticCamera.h"
StaticCamera::StaticCamera()
{
}
StaticCamera::~StaticCamera()
{
}
XMMATRIX* StaticCamera::WVP()
{
return &m_WVP;
}
XMMATRIX* StaticCamera::World()
{
return &m_World;
}
XMMATRIX* StaticCamera::camView()
{
return &m_camView;
}
XMMATRIX* StaticCamera::camProjection()
{
return &m_camProjection;
}
XMVECTOR* StaticCamera::camPosition()
{
return &m_camPosition;
}
XMVECTOR* StaticCamera::camTarget()
{
return &m_camTarget;
}
XMVECTOR* StaticCamera::camUp()
{
return &m_camUp;
}
void StaticCamera::WVP(XMMATRIX WVP)
{
m_WVP = WVP;
}
void StaticCamera::World(XMMATRIX World)
{
m_World = World;
}
void StaticCamera::setFOV(float FOV, float aspectRatio, float nearZ, float farZ)
{
//Set the Projection matrix
m_camProjection = XMMatrixPerspectiveFovLH(FOV, aspectRatio, nearZ, farZ);
updateMatrix();
}
void StaticCamera::setCamera(XMFLOAT4 position, XMFLOAT4 Target, XMFLOAT4 Up)
{
//Camera information
m_camPosition = Conversion::XMFLOAT4TOXMVECTOR(position);
m_camTarget = Conversion::XMFLOAT4TOXMVECTOR(Target);
m_camUp = Conversion::XMFLOAT4TOXMVECTOR(Up);
//Set the View matrix
m_camView = XMMatrixLookAtLH(m_camPosition, m_camTarget, m_camUp);
///////////////**************new**************////////////////////
updateMatrix();
}
void StaticCamera::updateMatrix()
{
m_World = XMMatrixIdentity();
m_WVP = (m_World * m_camView * m_camProjection);
}
Conversion.h:
#pragma once
#include "MathHelper.h"
#include <vector>
using namespace std;
static class Conversion
{
public:
static XMFLOAT4 XMVECTORTOXMFLOAT4(XMVECTOR Xmvector);
static XMFLOAT3 XMVECTORTOXMFLOAT3(XMVECTOR Xmvector);
static XMVECTOR XMFLOAT4TOXMVECTOR(XMFLOAT4 Xmfloat);
static void INTVECTORTOARRAY(std::vector<int> vector, int *arr);
static LPCWSTR STRINGTOLPCWSTR(std::string stdstr);
};
Conversion.cpp:
#include "Conversion.h"
XMFLOAT4 Conversion::XMVECTORTOXMFLOAT4(XMVECTOR Xmvector)
{
XMFLOAT4 pos;
XMStoreFloat4(&pos, Xmvector);
return pos;
}
XMFLOAT3 Conversion::XMVECTORTOXMFLOAT3(XMVECTOR Xmvector)
{
XMFLOAT3 pos;
XMStoreFloat3(&pos, Xmvector);
return pos;
}
XMVECTOR Conversion::XMFLOAT4TOXMVECTOR(XMFLOAT4 Xmfloat)
{
return XMLoadFloat4(&Xmfloat);
}
void Conversion::INTVECTORTOARRAY(std::vector<int> vector, int *arr)
{
arr = &vector[0];
}
LPCWSTR Conversion::STRINGTOLPCWSTR(std::string stdstr)
{
std::wstring stemp = std::wstring(stdstr.begin(), stdstr.end());
LPCWSTR sw = stemp.c_str();
return sw;
}
DefinedModel.h:
#pragma once
#include <windows.h>
#include <d3d11_1.h>
#include "ShaderHelper.h"
#include "d3dx11effect.h"
#include "Conversion.h"
#include "Vector3.h"
#include "d3dApp.h"
class DefinedModel
{
public:
enum RastMode {
Solid,
Wireframe
};
public:
DefinedModel(D3DApp* parent);
~DefinedModel();
protected:
D3DApp* m_pParent;
//Vertex Structure and Vertex Layout (Input Layout)//
struct Vertex //Overloaded Vertex Structure
{
Vertex() {}
Vertex(float x, float y, float z,
float cr, float cg, float cb, float ca)
: pos(x, y, z), color(cr, cg, cb, ca) {}
XMFLOAT3 pos;
XMFLOAT4 color;
};
std::vector<Vertex> m_VertexArray;
std::vector<int> m_indices;
struct cbPerObject
{
XMMATRIX WVP;
};
cbPerObject cbPerObj;
ID3D11Buffer* cbPerObjectBuffer;
ID3D11Buffer* squareIndexBuffer;
ID3D11Buffer* squareVertBuffer;
ID3D11VertexShader* VS;
ID3D11PixelShader* PS;
ID3D10Blob* VS_Buffer;
ID3D10Blob* PS_Buffer;
ID3D11InputLayout* vertLayout;
///////////////**************new**************////////////////////
Vector3 m_Rotation;
Vector3 m_Scale;
Vector3 m_Offset;
XMMATRIX m_modelWorld;
///////////////**************new**************////////////////////
RastMode m_RastMode;
ID3D11RasterizerState* m_RastState;
public:
virtual void create3DCube(float Width, float Height, float Depth);
void Init();
void Draw();
void Rotation(float X, float Y, float Z);
void Scale(float X, float Y, float Z);
void Offset(float X, float Y, float Z);
void rastMode(RastMode rastmode);
Vector3 Rotation();
Vector3 Scale();
Vector3 Offset();
XMMATRIX worldMatrix();
void Destroy();
private:
virtual void InitBuffers();
virtual void InitFX();
virtual void InitInputLayout();
virtual void InitCBBuffer();
};
DefinedModel.cpp:
#include "DefinedModel.h"
DefinedModel::DefinedModel(D3DApp* parent): m_pParent(parent)
{
m_VertexArray = std::vector<Vertex>();
m_indices = std::vector<int>();
m_modelWorld = XMMatrixIdentity();
Offset(0, 0, 0);
Scale(1, 1, 1);
Rotation(0, 0, 0);
rastMode(RastMode::Solid);
}
DefinedModel::~DefinedModel()
{
}
void DefinedModel::create3DCube(float Width, float Height, float Depth)
{
///////////////**************new**************////////////////////
//Create the vertex buffer
m_VertexArray = {
Vertex(-Width / 2, -Height / 2, -Depth / 2, 1.0f, 0.0f, 0.0f, 1.0f),
Vertex(-Width / 2, +Height / 2, -Depth / 2, 0.0f, 1.0f, 0.0f, 1.0f),
Vertex(+Width / 2, +Height / 2, -Depth / 2, 0.0f, 0.0f, 1.0f, 1.0f),
Vertex(+Width / 2, -Height / 2, -Depth / 2, 1.0f, 1.0f, 0.0f, 1.0f),
Vertex(-Width / 2, -Height / 2, +Depth / 2, 0.0f, 1.0f, 1.0f, 1.0f),
Vertex(-Width / 2, +Height / 2, +Depth / 2, 1.0f, 1.0f, 1.0f, 1.0f),
Vertex(+Width / 2, +Height / 2, +Depth / 2, 1.0f, 0.0f, 1.0f, 1.0f),
Vertex(+Width / 2, -Height / 2, +Depth / 2, 1.0f, 0.0f, 0.0f, 1.0f),
};
///////////////**************new**************////////////////////
m_indices = {
// front face
0, 1, 2,
0, 2, 3,
// back face
4, 6, 5,
4, 7, 6,
// left face
4, 5, 1,
4, 1, 0,
// right face
3, 2, 6,
3, 6, 7,
// top face
1, 5, 6,
1, 6, 2,
// bottom face
4, 0, 3,
4, 3, 7
};
Init();
}
void DefinedModel::Init()
{
InitBuffers();
InitFX();
InitInputLayout();
InitCBBuffer();
}
void DefinedModel::InitBuffers()
{
HRESULT hr;
//index buffer creation
D3D11_BUFFER_DESC indexBufferDesc;
ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(DWORD) * 12 * 3;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &m_indices[0];
hr = m_pParent->Device()->CreateBuffer(&indexBufferDesc, &iinitData, &squareIndexBuffer);
//vertex buffer creation
D3D11_BUFFER_DESC vertexBufferDesc;
ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(Vertex) * 8;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vertexBufferData;
ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
vertexBufferData.pSysMem = &m_VertexArray[0];
hr = m_pParent->Device()->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &squareVertBuffer);
}
void DefinedModel::InitFX()
{
HRESULT hr;
//Compile Shaders from shader file
hr = D3DX11CompileFromFile(L"Trans.fx", 0, 0, "VS", "vs_4_0", 0, 0, 0, &VS_Buffer, 0, 0);
hr = D3DX11CompileFromFile(L"Trans.fx", 0, 0, "PS", "ps_4_0", 0, 0, 0, &PS_Buffer, 0, 0);
//Create the Shader Objects
hr = m_pParent->Device()->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS);
hr = m_pParent->Device()->CreatePixelShader(PS_Buffer->GetBufferPointer(), PS_Buffer->GetBufferSize(), NULL, &PS);
//Set Vertex and Pixel Shaders
m_pParent->DeviceContext()->VSSetShader(VS, 0, 0);
m_pParent->DeviceContext()->PSSetShader(PS, 0, 0);
}
void DefinedModel::InitInputLayout()
{
HRESULT hr;
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE(layout);
//Create the Input Layout
hr = m_pParent->Device()->CreateInputLayout(layout, numElements, VS_Buffer->GetBufferPointer(),
VS_Buffer->GetBufferSize(), &vertLayout);
}
void DefinedModel::InitCBBuffer()
{
HRESULT hr;
//Create the buffer to send to the cbuffer in effect file
D3D11_BUFFER_DESC cbbd;
ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC));
cbbd.Usage = D3D11_USAGE_DEFAULT;
cbbd.ByteWidth = sizeof(cbPerObject);
cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbbd.CPUAccessFlags = 0;
cbbd.MiscFlags = 0;
hr = m_pParent->Device()->CreateBuffer(&cbbd, NULL, &cbPerObjectBuffer);
}
void DefinedModel::Draw()
{
//set index buffer
m_pParent->DeviceContext()->IASetIndexBuffer(squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
//Set the vertex buffer
UINT stride = sizeof(Vertex);
UINT offset = 0;
m_pParent->DeviceContext()->IASetVertexBuffers(0, 1, &squareVertBuffer, &stride, &offset);
//Set the Input Layout
m_pParent->DeviceContext()->IASetInputLayout(vertLayout);
//Set Primitive Topology
m_pParent->DeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
//set rasteriser state
m_pParent->DeviceContext()->RSSetState(m_RastState);
//Matrices
///////////////**************new**************////////////////////
//Set the WVP matrix and send it to the constant buffer in effect file
XMMATRIX WVP = (worldMatrix()) * (*m_pParent->Camera()->camView()) * (*m_pParent->Camera()->camProjection());
cbPerObj.WVP = XMMatrixTranspose(WVP);
m_pParent->DeviceContext()->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0);
m_pParent->DeviceContext()->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer);
//draw shape
m_pParent->DeviceContext()->DrawIndexed(m_indices.size(), 0, 0);
}
void DefinedModel::Rotation(float X, float Y, float Z)
{
m_Rotation = Vector3(X, Y, Z);
//m_Rotation.X = X;
//m_Rotation.Y = Y;
//m_Rotation.Z = Z;
}
void DefinedModel::Scale(float X, float Y, float Z)
{
m_Scale = Vector3(X, Y, Z);
//m_Scale.X = X;
//m_Scale.Y = Y;
//m_Scale.Z = Z;
}
void DefinedModel::Offset(float X, float Y, float Z)
{
m_Offset = Vector3(X, Y, Z);
//m_Offset.X = X;
//m_Offset.Y = Y;
//m_Offset.Z = Z;
}
Vector3 DefinedModel::Rotation()
{
return m_Rotation;
}
Vector3 DefinedModel::Scale()
{
return m_Scale;
}
Vector3 DefinedModel::Offset()
{
return m_Offset;
}
XMMATRIX DefinedModel::worldMatrix()
{
XMMATRIX Scale = XMMatrixScaling(m_Scale.X(), m_Scale.Y(), m_Scale.Z());
XMMATRIX Rot = (XMMatrixRotationX(m_Rotation.X())) * (XMMatrixRotationY(m_Rotation.Y())) * (XMMatrixRotationZ(m_Rotation.Z()));
XMMATRIX Trans = XMMatrixTranslation(m_Offset.X(), m_Offset.Y(), m_Offset.Z());
// orbital
//m_modelWorld = Trans * Rot * Scale;
//on spot
m_modelWorld = Scale * Rot * Trans;
return m_modelWorld;
}
void DefinedModel::Destroy()
{
squareVertBuffer->Release();
squareIndexBuffer->Release();
VS->Release();
PS->Release();
VS_Buffer->Release();
PS_Buffer->Release();
vertLayout->Release();
cbPerObjectBuffer->Release();
m_VertexArray.clear();
m_indices.clear();
}
void DefinedModel::rastMode(RastMode rastmode)
{
HRESULT hr;
m_RastMode = rastmode;
switch (rastmode)
{
case RastMode::Solid:
{
///////////////**************new**************////////////////////
D3D11_RASTERIZER_DESC wfdesc;
ZeroMemory(&wfdesc, sizeof(D3D11_RASTERIZER_DESC));
wfdesc.FillMode = D3D11_FILL_SOLID;
wfdesc.CullMode = D3D11_CULL_BACK;
hr = m_pParent->Device()->CreateRasterizerState(&wfdesc, &m_RastState);
///////////////**************new**************////////////////////
break;
}
case RastMode::Wireframe:
{
///////////////**************new**************////////////////////
D3D11_RASTERIZER_DESC wfdesc;
ZeroMemory(&wfdesc, sizeof(D3D11_RASTERIZER_DESC));
wfdesc.FillMode = D3D11_FILL_WIREFRAME;
wfdesc.CullMode = D3D11_CULL_BACK;
hr = m_pParent->Device()->CreateRasterizerState(&wfdesc, &m_RastState);
///////////////**************new**************////////////////////
break;
}
}
}
Effect file (trans.fx):
cbuffer cbPerObject
{
float4x4 WVP;
};
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR;
};
VS_OUTPUT VS(float4 inPos : POSITION, float4 inColor : COLOR)
{
VS_OUTPUT output;
output.Pos = mul(inPos, WVP);
output.Color = inColor;
return output;
}
float4 PS(VS_OUTPUT input) : SV_TARGET
{
return input.Color;
}
I have been trying to add a particle system to my Directx11 graphics demo, and so i have been using the 'Introduction to 3d Game Programming with directx 11' book.
Because of this am attempting to use a HLSL StreamOut technique to update the particle system and a separate technique to render the particles.
Below is the HLSL code for the particle system, i have tried adjusting the acceleration and velocity in the off chance the speed was sending the particles off the screen, however this had no effect.
cbuffer cbPerFrame
{
float3 gEyePosW;
float3 gEmitPosW;
float3 gEmitDirW;
float gGameTime;
float gTimeStep;
float4x4 gViewProj;
};
cbuffer cbFixed
{
// Net constant acceleration used to accerlate the particles.
float3 gAccelW = {0.0f, 0.2f, 0.0f};
// Texture coordinates for billbording are always the same - we use a qquad in this effect :)
float2 gTexC[4] =
{
float2(0.0f, 1.0f),
float2(0.0f, 0.0f),
float2(1.0f, 1.0f),
float2(1.0f, 0.0f)
};
};
// Nonnumeric values cannot be added to a cbuffer.
Texture2DArray gTextureMapArray;
// Random texture used to generate random numbers in shaders.
Texture1D gRandomTexture;
SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
DepthStencilState DisableDepth
{
DepthEnable = FALSE;
DepthWriteMask = ZERO;
};
DepthStencilState NoDepthWrites
{
DepthEnable = TRUE;
DepthWriteMask = ZERO;
};
BlendState AdditiveBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = ONE;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
///////////////////////////////////////////////////////////////
// Helper functions
//
///////////////////////////////////////////////////////////////
float3 RandUnitVec3(float offset)
{
// Use game time plus offset to sample random texture.
float u = (gGameTime + offset);
// coordinates in [-1,1]
float3 v = gRandomTexture.SampleLevel(samLinear, u, 0).xyz;
// project onto unit sphere (Normalize)
return normalize(v);
}
///////////////////////////////////////////////////////////////
// Stream Out Technique
//
///////////////////////////////////////////////////////////////
#define PT_EMITTER 0
#define PT_FLARE 1
struct Particle
{
float3 InitPosW : POSITION;
float3 InitVelW : VELOCITY;
float2 SizeW : SIZE;
float Age : AGE;
uint Type : Type;
};
Particle StreamOutVS(Particle vin)
{
return vin;
}
// The stream-out GS is just responsible for emitting
// new particles and destroying old particles. The logic
// programed here will generally vary from particle system
// to particle system, as the destroy/spawn rules will be
// different.
[maxvertexcount(2)]
void StreamOutGS(point Particle gin[1],
inout PointStream<Particle> ptStream)
{
gin[0].Age += gTimeStep;
// if particle is emitter particle
if (gin[0].Type == PT_EMITTER)
{
// If it's time to emit new particle
if (gin[0].Age > 0.005f)
{
float3 vRandom = RandUnitVec3(0.0f);
vRandom.x *= 0.5f;
vRandom.z *= 0.5f;
Particle p;
p.InitPosW = gEmitPosW.xyz;
p.InitVelW = 0.5f*vRandom;
p.SizeW = float2(3.0f, 3.0f);
p.Age = 0.0f;
p.Type = PT_FLARE;
ptStream.Append(p);
// reset the time to emit
gin[0].Age = 0.0f;
}
// always keep emitters
ptStream.Append(gin[0]);
}
else
{
// Set conditions to keep a particle - in this case age limit
if (gin[0].Age <= 1.0f)
{
ptStream.Append(gin[0]);
}
}
}
GeometryShader gsStreamOut = ConstructGSWithSO(
CompileShader( gs_5_0, StreamOutGS() ),
"POSITION.xyz; VELOCITY.xyz; SIZE.xyz; AGE.x; TYPE.x" );
technique11 StreamOutTech
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, StreamOutVS() ) );
SetGeometryShader( gsStreamOut );
// disable pixel shader for stream-out only
SetPixelShader(NULL);
// we must also disable the depth buffer for stream-out only
SetDepthStencilState( DisableDepth, 0 );
}
}
///////////////////////////////////////////////////////////////
// Draw Technique
//
///////////////////////////////////////////////////////////////
struct VertexIn
{
float3 Pos : POSITION;
float2 SizeW : SIZE;
};
struct VertexOut
{
float3 PosW : POSITION;
float2 SizeW : SIZE;
float4 Colour : COLOR;
uint Type : TYPE;
};
VertexOut DrawVS(Particle vin)
{
VertexOut vout;
float t = vin.Age;
// constant Acceleration equation
vout.PosW = 0.5f*t*t*gAccelW + t*vin.InitVelW + vin.InitPosW;
// fade colour with time
float opacity = 1.0f - smoothstep(0.0f, 1.0f, t/1.0f);
vout.Colour = float4(1.0f, 1.0f, 1.0f, opacity);
vout.SizeW = vin.SizeW;
vout.Type = vin.Type;
return vout;
}
struct GeoOut
{
float4 PosH : SV_POSITION;
float4 Colour : COLOR;
float2 Tex : TEXCOORD;
};
// Expand each 'Point' into a quad (4 verticies)
[maxvertexcount(4)]
void DrawGS(point VertexOut gin[1],
inout TriangleStream<GeoOut> triStream)
{
// Do not draw Emiter particles in this system
if (gin[0].Type != PT_EMITTER)
{
//
// Compute world matrix so that billboard faces the camera.
//
float3 look = normalize(gEyePosW.xyz - gin[0].PosW);
float3 right = normalize(cross(float3(0,1,0), look));
float3 up = cross(look, right);
//
// Compute triangle strip vertices (quad) in world space.
//
float halfWidth = 0.5f*gin[0].SizeW.x;
float halfHeight = 0.5f*gin[0].SizeW.y;
float4 v[4];
v[0] = float4(gin[0].PosW + halfWidth*right - halfHeight*up, 1.0f);
v[1] = float4(gin[0].PosW + halfWidth*right + halfHeight*up, 1.0f);
v[2] = float4(gin[0].PosW - halfWidth*right - halfHeight*up, 1.0f);
v[3] = float4(gin[0].PosW - halfWidth*right + halfHeight*up, 1.0f);
//
// Transform quad vertices to world space and output
// them as a triangle strip.
//
GeoOut gout;
[unroll]
for(int i = 0; i < 4; ++i)
{
gout.PosH = mul(v[i], gViewProj);
gout.Tex = gTexC[i];
gout.Colour = gin[0].Colour;
triStream.Append(gout);
}
}
}
float DrawPS(GeoOut pin) : SV_TARGET
{
return gTextureMapArray.Sample(samLinear, float3(pin.Tex, 0)) * pin.Colour;
}
technique11 DrawTech
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, DrawVS() ) );
SetGeometryShader( CompileShader( gs_5_0, DrawGS() ) );
SetPixelShader( CompileShader( ps_5_0, DrawPS() ) );
SetBlendState(AdditiveBlending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xffffffff);
SetDepthStencilState( NoDepthWrites, 0 );
}
}
Below is the code for building the VB.
void ParticleSystem::BuildVB(ID3D11Device* device)
{
/////////////////////////////////////////////////////////
// Create the buffer to start the particle system.
/////////////////////////////////////////////////////////
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_DEFAULT;
vbd.ByteWidth = sizeof(Vertex::Particle) * 1;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
// The initial particle emitter has type 0 and age 0. The rest
// of the particle attributes do not apply to an emitter.
Vertex::Particle p;
ZeroMemory(&p, sizeof(Vertex::Particle));
p.Age = 0.0f;
p.Type = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &p;
HR(device->CreateBuffer(&vbd, &vinitData, &mInitVB));
//////////////////////////////////////////////////////////////
// Create the buffers which swap back and forth for stream-out and drawing.
//////////////////////////////////////////////////////////////
vbd.ByteWidth = sizeof(Vertex::Particle) * mMaxParticles;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT;
HR(device->CreateBuffer(&vbd, 0, &mDrawVB));
HR(device->CreateBuffer(&vbd, 0, &mStreamOutVB));
}
And now the Draw cpp code.
void ParticleSystem::Draw(ID3D11DeviceContext* dc, const XMMATRIX& viewProj)
{
//
// Set constants.
//
mFX->SetViewProj(viewProj);
mFX->SetGameTime(mGameTime);
mFX->SetTimeStep(mTimeStep);
mFX->SetEyePosW(mEyePosW);
mFX->SetEmitPosW(mEmitPosW);
mFX->SetEmitDirW(mEmitDirW);
mFX->SetTexArray(mTextureArraySRV);
mFX->SetRandomTex(mRandomTextureSRV);
//
// Set IA stage.
//
dc->IASetInputLayout(InputLayouts::Particle);
dc->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
UINT stride = sizeof(Vertex::Particle);
UINT offset = 0;
// On the first pass, use the initialization VB. Otherwise, use
// the VB that contains the current particle list.
if( mFirstRun )
dc->IASetVertexBuffers(0, 1, &mInitVB, &stride, &offset);
else
dc->IASetVertexBuffers(0, 1, &mDrawVB, &stride, &offset);
//
// Draw the current particle list using stream-out only to update them.
// The updated vertices are streamed-out to the target VB.
//
dc->SOSetTargets(1, &mStreamOutVB, &offset);
D3DX11_TECHNIQUE_DESC techDesc;
mFX->StreamOutTech->GetDesc( &techDesc );
for(UINT p = 0; p < techDesc.Passes; ++p)
{
mFX->StreamOutTech->GetPassByIndex( p )->Apply(0, dc);
if(mFirstRun)
{
dc->Draw(1, 0);
mFirstRun = false;
}
else
{
dc->DrawAuto();
}
}
// done streaming-out--unbind the vertex buffer
ID3D11Buffer* bufferArray[1] = {0};
dc->SOSetTargets(1, bufferArray, &offset);
// ping-pong the vertex buffers
std::swap(mDrawVB, mStreamOutVB);
//
// Draw the updated particle system we just streamed-out.
//
dc->IASetVertexBuffers(0, 1, &mDrawVB, &stride, &offset);
mFX->DrawTech->GetDesc( &techDesc );
for(UINT p = 0; p < techDesc.Passes; ++p)
{
mFX->DrawTech->GetPassByIndex( p )->Apply(0, dc);
dc->DrawAuto();
}
}
I had thought that perhaps either a blend state or Depth state in use by some of the other objects in my scene may be causing the issue, (perhaps i have misunderstood something I have set earlier). I tried removing all other render code leaving just the draw code above, but with no results.
To my mind, I can only think of a few possible causes for the issue i am having, but so far i am unable to find a solution.
The scale of the system is wrong for my scene. eg. the particles are drawing but are moving off the screen to fast to be seen.
As mentioned above i have tried removing the acceleration and velocity of the particles in the HLSL code, in order to see stationary particles. This had no effect.
Blend state/Depth stencil state is incorrect. Eg. As mentioned above.
The Emitter particle is, for some reason, not being produced/placed correctly. causing no 'drawable' particles to be produced in turn.
As most of this code is in the .fx file, I am unable to step through to check the emitter particles. I think this is the more likely issue, but i have been wrong before.
Any help on this would be greatly appreciated, I am well and truly stuck on this.
Below I have added additional snippets of code which may be of use.
E.G. Input layout.
const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::Particle[5] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"VELOCITY", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"SIZE", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"AGE", 0, DXGI_FORMAT_R32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TYPE", 0, DXGI_FORMAT_R32_UINT, 0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
And particle system INIT
mFire.Init(md3dDevice, AppEffects::FireFX, mFlareTextureSRV, mRandomTextureSRV, 500);
mFire.SetEmitPos(XMFLOAT3(1.0f, 0.5f, 0.0f));
void ParticleSystem::Init(ID3D11Device* device, ParticleEffect* fx,
ID3D11ShaderResourceView* textureArraySRV,
ID3D11ShaderResourceView* randomTextureSRV,
UINT maxParticles)
{
mMaxParticles = maxParticles;
mFX = fx;
mTextureArraySRV = textureArraySRV;
mRandomTextureSRV = randomTextureSRV;
BuildVB(device);
}
If i have missed any section of the code you would need to see, let me know.
Thanks in advance.
Sorry about this stupid question all. Turns out it was a stupid mistake in the pixel shader. I had set the pixel shader as a float instead of float4.