I started learning Direct3D a week ago and I've been following many tutorials but after I got to the point where I had to create a Constant Buffer I got stuck, the creation of the buffer seems to be working correctly but the UpdateSubresource
function doesn't seem to update it, the value I'm trying to put in the buffer has no purpose apart from being a proof of concept, the value is the float brightness inside the struct VS_CONSTANT_BUFFER
.
It is set to 1.0 during the buffer creation, then it is set 0.5 when the frame is redrawn but it doesn't update the buffer on the shader side.
Here is the code, I put all of the Direct3D stuff in one place so there is nothing you don't see:
#include "GraphicsInit.h"
#include"Window.h"
float red = 0.0f;
int angle = 0;
struct Vertex
{
float x, y, z;
float r, g, b, a;
};
Vertex triangle[] = {
{-0.5f,-0.5f,0.5f, 1.0f,0.0f,0.0f,1.0f},
{-0.5f, 0.5f,0.5f, 0.0f,1.0f,0.0f,1.0f},
{ 0.5f, 0.5f,0.5f, 0.0f,0.0f,1.0f,1.0f},
{ 0.5f,-0.5f,0.5f, 0.0f,1.0f,0.0f,1.0f},
{-0.6f, 0.7,0.4f, 1.0f,1.0f,1.0f,1.0f},
{ 0.4f, 0.3f,0.9f, 1.0f,1.0f,1.0f,1.0f},
{ 0.9f,-0.8f,0.6f, 1.0f,1.0f,1.0f,1.0f}
};
unsigned int indices[] = {
0, 1, 2,
0, 2, 3,
4,5,6
};
ID3D11VertexShader* vs;
ID3D11PixelShader* ps;
ID3D11InputLayout* InputLayout;
ID3D11Buffer* VertexBuffer;
ID3D11Buffer* IndexBuffer;
ID3D11Buffer* VSConstantBuffer = NULL;
//Struct needs to be equal to the one in the shaders
struct VS_CONSTANT_BUFFER
{
float brightness;
};
VS_CONSTANT_BUFFER VSCBdata;
//CBStruct CBDat = {
// {
// std::cos(angle), std::sin(angle), 0.0f, 0.0f,
// -std::sin(angle), std::cos(angle), 0.0f, 0.0f,
// 0.0f, 0.0f, 0.0f, 0.0f,
// 0.0f, 0.0f, 0.0f, 0.0f
// }
//};
void InitD3D(HWND hWnd)
{
//////////////////DEVICE AND SWAPCHAIN//////////////////
DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.Windowed = TRUE; // windowed/full-screen mode
D3D11CreateDeviceAndSwapChain(
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);
/////////////////////////////////////////////////////////
//////////////////SET THE RENDER TARGET//////////////////
// get the address of the back buffer
ID3D11Texture2D* pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
/////////////////////////////////////////////////////////
//////////////////SET THE VIEW PORT//////////////////
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = sizeX;
viewport.Height = sizeY;
devcon->RSSetViewports(1, &viewport);
/////////////////////////////////////////////////////////
InitBuffers();
InitPipeline();
}
void InitPipeline()
{
//////////////////SHADERS COMPILING//////////////////
ID3D10Blob* blobvs, * blobps;
D3DX11CompileFromFile(L"Shaders.hlsl", 0, 0, "VS", "vs_4_0", 0, 0, 0, &blobvs, 0, 0);
D3DX11CompileFromFile(L"Shaders.hlsl", 0, 0, "PS", "ps_4_0", 0, 0, 0, &blobps, 0, 0);
dev->CreateVertexShader(blobvs->GetBufferPointer(), blobvs->GetBufferSize(), NULL, &vs);
dev->CreatePixelShader(blobps->GetBufferPointer(), blobps->GetBufferSize(), NULL, &ps);
devcon->VSSetShader(vs, 0, 0);
devcon->PSSetShader(ps, 0, 0);
/////////////////////////////////////////////////////////
//////////////////INPUT LAYOUT//////////////////
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 },
};
dev->CreateInputLayout(layout, 2, blobvs->GetBufferPointer(), blobvs->GetBufferSize(), &InputLayout);
devcon->IASetInputLayout(InputLayout);
/////////////////////////////////////////////////////////
blobvs->Release();
blobps->Release();
//////////////////IA//////////////////
// select which vertex buffer to display
UINT stride = sizeof(Vertex);
UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
// select which primtive type we are using
devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
/////////////////////////////////////////////////////////
}
// this is the function used to render a single frame
void RenderFrame(void)
{
VSCBdata.brightness = 0.5f;
// clear the back buffer to a deep blue
devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(red, 0.2f, 0.4f, 1.0f));
devcon->UpdateSubresource(VSConstantBuffer, 0, NULL, &VSCBdata, 0, 0);
devcon->VSSetConstantBuffers(0, 1, &VSConstantBuffer);
// draw the vertex buffer to the back buffer
devcon->DrawIndexed(9, 0,0);
// do 3D rendering on the back buffer here
// switch the back buffer and the front buffer
swapchain->Present(0, 0);
}
void InitBuffers()
{
//////////////////VERTEX BUFFER//////////////////
D3D11_BUFFER_DESC buffer_desc = { 0 };
buffer_desc.ByteWidth = sizeof(Vertex) * ARRAYSIZE(triangle);
buffer_desc.Usage = D3D11_USAGE_DEFAULT;
buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
buffer_desc.CPUAccessFlags = 0;
buffer_desc.MiscFlags = 0;
buffer_desc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA sub = { 0 };
sub.pSysMem = triangle;
sub.SysMemPitch = 0;
sub.SysMemSlicePitch = 0;
dev->CreateBuffer(&buffer_desc, &sub, &VertexBuffer);
/////////////////////////////////////////////////////////
//////////////////INDEX BUFFER//////////////////
D3D11_BUFFER_DESC index_desc = { 0 };
index_desc.Usage = D3D11_USAGE_DEFAULT;
index_desc.ByteWidth = sizeof(unsigned int) * ARRAYSIZE(indices);
index_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
index_desc.CPUAccessFlags = 0;
index_desc.MiscFlags = 0;
// Define the resource data.
D3D11_SUBRESOURCE_DATA index_data;
index_data.pSysMem = indices;
index_data.SysMemPitch = 0;
index_data.SysMemSlicePitch = 0;
dev->CreateBuffer(&index_desc, &index_data, &IndexBuffer);
/////////////////////////////////////////////////////////
//////////////////CONSTANT BUFFER//////////////////
// Define the constant data used to communicate with shaders.
// Supply the vertex shader constant data.
VSCBdata.brightness = 1.0f;
// Fill in a buffer description.
D3D11_BUFFER_DESC CBDesc;
/////VERY STRANGÊ BEHAVIOUR
CBDesc.ByteWidth = 16;
//////
CBDesc.Usage = D3D11_USAGE_DYNAMIC;
CBDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
CBDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
CBDesc.MiscFlags = 0;
CBDesc.StructureByteStride = 0;
// Fill in the subresource data.
D3D11_SUBRESOURCE_DATA CBInitData;
CBInitData.pSysMem = &VSCBdata;
CBInitData.SysMemPitch = 0;
CBInitData.SysMemSlicePitch = 0;
// Create the buffer.
dev->CreateBuffer(&CBDesc, &CBInitData,&VSConstantBuffer);
// Set the buffer.
devcon->VSSetConstantBuffers(0, 1, &VSConstantBuffer);
/////////////////////////////////////////////////////////
}
void CleanD3D(void)
{
//Device
dev->Release();
devcon->Release();
/////////
//Swapchain
swapchain->Release();
backbuffer->Release();
/////////
//Pipeline
vs->Release();
ps->Release();
InputLayout->Release();
/////////
//Buffers
VertexBuffer->Release();
IndexBuffer->Release();
VSConstantBuffer->Release();
/////////
}
Here is the header file:
#pragma once
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <directxmath.h>
#include <d3dx10math.h>
using namespace DirectX;
// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")
//////GLOBAL VARIABLES//////
static IDXGISwapChain* swapchain; // the pointer to the swap chain interface
static ID3D11Device* dev; // the pointer to our Direct3D device interface
static ID3D11DeviceContext* devcon; // the pointer to our Direct3D device context
static ID3D11RenderTargetView* backbuffer; // the pointer to our render target
/////////////////////////
void InitD3D(HWND hWnd); // sets up and initializes Direct3D
void RenderFrame(void);
void CleanD3D(void); // closes Direct3D and releases memory
void InitPipeline();
void InitBuffers();
And the shaders:
cbuffer VS_CONSTANT_BUFFER
{
float brightness;
};
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VOut VS(float4 position : POSITION, float4 color : COLOR)
{
VOut output;
float4 col = { brightness,brightness,brightness,1.0f };
output.position = position;
output.color = col;
return output;
}
float4 PS(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}