Modify a IDirect3DSurface9* with shader - c++

I got a IDirect3DSurface9 * from a DXVA2 video decoder. I'd like to modify that surface with a shader. I' m able to render the video frames without shader by "drawing" the surface in the back buffer.
I use the following code to render the frames without shader:
void Draw(Example* exps){
IDirect3DSurface9* backbuffer;
hwctx->d3d9device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
hwctx->d3d9device->BeginScene();
hwctx->swap_chain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
hwctx->d3d9device->StretchRect(videoSurface, NULL, backbuffer, NULL, D3DTEXF_LINEAR);
hwctx->d3d9device->EndScene();
hwctx->swap_chain->Present(0, 0, 0, 0, 0);
backbuffer->Release();
}
Up until here, everithing works.
I would modify the Draw function to render video frames with the following shader:
uniform extern float4x4 gWVP;
uniform extern texture gTexRGB;
uniform extern texture gTexAlpha;
sampler TexRGB = sampler_state
{
Texture = <gTexRGB>;
AddressU = WRAP;
AddressV = WRAP;
};
sampler TexAlpha = sampler_state
{
Texture = <gTexAlpha>;
AddressU = WRAP;
AddressV = WRAP;
};
struct OutputVS
{
float4 posH : POSITION0;
float2 tex0 : TEXCOORD0;
};
OutputVS DirLightTexVS(float3 posL : POSITION0, float3 normalL : NORMAL0, float2 tex0: TEXCOORD0)
{
// Zero out our output.
OutputVS outVS = (OutputVS)0;
// Transform to homogeneous clip space.
outVS.posH = mul(float4(posL, 1.0f), gWVP);
// Pass on texture coordinates to be interpolated in rasterization.
outVS.tex0 = tex0;
// Done--return the output.
return outVS;
}
float4 DirLightTexPS(float4 c : COLOR0, float4 spec : COLOR1, float2 tex0 : TEXCOORD0) : COLOR
{
float3 rgb = tex2D(TexRGB, tex0).rgb;
float alpha = tex2D(TexAlpha, tex0).g;
return float4(rgb, alpha);
}
technique DirLightTexTech
{
pass P0
{
// Specify the vertex and pixel shader associated with this pass.
vertexShader = compile vs_2_0 DirLightTexVS();
pixelShader = compile ps_2_0 DirLightTexPS();
}
}
where TexRGB is the texture associated to the video frame, while TexAlpha is another texture that contains alpha values.
How can I pass the decoded surface to the shader? I never used Directx9 so an example is appreciated and could help me to solve the problem.
UPDATE 1:
I created the InitEffect function to load the effect from file
void InitEffect(Example* ctx) {
auto hwctx = ctx->decoder->stream->HWAccelCtx;
// Create the FX from a .fx file.
ID3DXBuffer* errors = 0;
D3DXCreateEffectFromFile(hwctx->d3d9device, "basicEffect.fx", 0, 0, D3DXSHADER_DEBUG, 0, &ctx->mFX, &errors);
if (errors)
MessageBox(0, (LPCSTR)errors->GetBufferPointer(), 0, 0);
// Obtain handles.
ctx->mhTech = ctx->mFX->GetTechniqueByName("DirLightTexTech");
ctx->mhWVP = ctx->mFX->GetParameterByName(0, "gWVP");
ctx->mhTexAlpha = ctx->mFX->GetParameterByName(0, "gTexAlpha");
ctx->mhTexRGB = ctx->mFX->GetParameterByName(0, "gTexRGB");
}
and changed the rendering fuction to:
void Draw(Example* ctx) {
InitMatrices(ctx);
IDirect3DSurface9* backbuffer;
hwctx->d3d9device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffeeeeee, 1.0f, 0);
hwctx->d3d9device->BeginScene();
ctx->mFX->SetTechnique(ctx->mhTech);
ctx->mFX->SetMatrix(ctx->mhWVP, &(ctx->mCrateWorld*ctx->mView*ctx->mProj));
ctx->texRGB->GetSurfaceLevel(0, &ctx->surfRGB);
hwctx->d3d9device->SetRenderTarget(0, ctx->surfRGB);
hwctx->d3d9device->StretchRect((IDirect3DSurface9*)s->frame->data[3], NULL, ctx->surfRGB, NULL, D3DTEXF_LINEAR);
ctx->mFX->SetTexture(ctx->mhTexAlpha, ctx->texAlpha);
ctx->mFX->SetTexture(ctx->mhTexRGB, ctx->texRGB);
// Enable alpha blending.
hwctx->d3d9device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
hwctx->d3d9device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
hwctx->d3d9device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
hwctx->d3d9device->SetVertexDeclaration(VertexPNT::Decl);
hwctx->d3d9device->SetStreamSource(0, ctx->mBoxVB, 0, sizeof(VertexPNT));
hwctx->d3d9device->SetIndices(ctx->mBoxIB);
UINT numPasses = 0;
ctx->mFX->Begin(&numPasses, 0);
for (UINT i = 0; i < numPasses; ++i){
ctx->mFX->BeginPass(i);
hwctx->d3d9device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
ctx->mFX->EndPass();
}
ctx->mFX->End();
hwctx->d3d9device->EndScene();
hwctx->swap_chain->Present(0, 0, 0, 0, 0);
backbuffer->Release();
// Disable alpha blending.
hwctx->d3d9device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
}
but it still doesn't work.
UPDATE 2
I modified the code by following the code Asesh shared. In the InitEffect function I added the following lines to create a render target surface:
ctx->texRGB->GetSurfaceLevel(0, &ctx->surfRGB);
// store orginal rendertarget
hwctx->d3d9device->GetRenderTarget(0, &ctx->origTarget_);
D3DSURFACE_DESC desc;
ctx->origTarget_->GetDesc(&desc);
// create our surface as render target
hwctx->d3d9device->CreateRenderTarget(1920, 1080, D3DFMT_X8R8G8B8,
desc.MultiSampleType, desc.MultiSampleQuality,
false, &ctx->surfRGB, NULL);
the draw function is:
void drawScene(Example* ctx) {
InitMatrices(ctx);
auto hwctx = ctx->decoder->stream->HWAccelCtx;
auto s = (VdrStreamContext*)ctx->decoder->stream->vdrCodecCtx->opaque;
IDirect3DSurface9* backbuffer;
hwctx->d3d9device->SetRenderTarget(0, ctx->surfRGB);
hwctx->d3d9device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffeeeeee, 1.0f, 0);
hwctx->d3d9device->BeginScene();
hwctx->d3d9device->StretchRect((IDirect3DSurface9*)s->vdrFrame->data[3], NULL, ctx->surfRGB, NULL, D3DTEXF_NONE);
hwctx->d3d9device->SetRenderTarget(0, ctx->origTarget_);
if (!hwctx->d3d9device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer)) {
hwctx->d3d9device->StretchRect(ctx->surfRGB, NULL, backbuffer, NULL, D3DTEXF_NONE);
}
ctx->mFX->SetTechnique(ctx->mhTech);
ctx->mFX->SetMatrix(ctx->mhWVP, &(ctx->mCrateWorld*ctx->mView*ctx->mProj));
ctx->mFX->SetTexture(ctx->mhTexAlpha, ctx->texAlpha);
ctx->mFX->SetTexture(ctx->mhTexRGB, ctx->texRGB);
// Enable alpha blending.
hwctx->d3d9device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
hwctx->d3d9device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
hwctx->d3d9device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
hwctx->d3d9device->SetVertexDeclaration(VertexPNT::Decl);
hwctx->d3d9device->SetStreamSource(0, ctx->mBoxVB, 0, sizeof(VertexPNT));
hwctx->d3d9device->SetIndices(ctx->mBoxIB);
UINT numPasses = 0;
ctx->mFX->Begin(&numPasses, 0);
for (UINT i = 0; i < numPasses; ++i){
ctx->mFX->BeginPass(i);
hwctx->d3d9device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
ctx->mFX->EndPass();
}
ctx->mFX->End();
hwctx->d3d9device->EndScene();
hwctx->d3d9device->Present(0, 0, 0, 0);
backbuffer->Release();
// Disable alpha blending.
hwctx->d3d9device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
}
by drawing in the backbuffer by hwctx->d3d9device->StretchRect(ctx->surfRGB, NULL, backbuffer, NULL, D3DTEXF_NONE); even if the ctx->surfRGB is associated to the texture passed to the shader, the video frame is showed on the screen but alpha blending is not applied. If I remove hwctx->d3d9device->StretchRect(ctx->surfRGB, NULL, backbuffer, NULL, D3DTEXF_NONE); video frame is not showed even if the ctx->surfRGB is not empty.

Related

How do you update the vertex buffer or constant buffer attached to a sprite to move it smoothly across the screen in Direct3D 11?

I have attached a texture to a set of 4 indexed vertices which are stored in a dynamic vertex buffer. I have also added a translation matrix to the constant buffer of the vertex shader. However, when I try updating the constant buffer to alter the translation matrix so the I can move the sprite, the sprite does not move smoothly. It stops randomly for short amounts of time before moving a short distance again.
Below are the render functions, the main loop and the shaders being used:
void Sprite::Render(ID3D11DeviceContext* devcon, float dt) {
// 2D rendering on backbuffer here
UINT stride = sizeof(VERTEX);
UINT offset = 0;
spr_const_data.translateMatrix.r[3].m128_f32[0] += 60.0f*dt;
devcon->IASetInputLayout(m_data_layout);
devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
devcon->VSSetShader(m_spr_vert_shader, 0, 0);
devcon->PSSetShader(m_spr_pixel_shader, 0, 0);
devcon->VSSetConstantBuffers(0, 1, &m_spr_const_buffer);
devcon->PSSetSamplers(0, 1, &m_tex_sampler_state);
devcon->PSSetShaderResources(0, 1, &m_shader_resource_view);
// select vertex and index buffers
devcon->IASetIndexBuffer(m_sprite_index_buffer, DXGI_FORMAT_R32_UINT, offset);
devcon->IASetVertexBuffers(0, 1, &m_sprite_vertex_buffer, &stride, &offset);
D3D11_MAPPED_SUBRESOURCE ms;
ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE));
devcon->Map(m_spr_const_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms);
memcpy(ms.pData, &spr_const_data, sizeof(spr_const_data));
devcon->Unmap(m_spr_const_buffer, 0);
// select which primitive type to use
// draw vertex buffer to backbuffer
devcon->DrawIndexed(6, 0, 0);
}
void RenderFrame(float dt) {
float background_color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
// clear backbuffer
devcon->ClearRenderTargetView(backbuffer, background_color);
knight->Render(devcon, dt);
// switch back and front buffer
swapchain->Present(0, 0);
}
void MainLoop() {
MSG msg;
auto tp1 = std::chrono::system_clock::now();
auto tp2 = std::chrono::system_clock::now();
while (GetMessage(&msg, nullptr, 0, 0) > 0) {
tp2 = std::chrono::system_clock::now();
std::chrono::duration<float> dt = tp2 - tp1;
tp1 = tp2;
TranslateMessage(&msg);
DispatchMessage(&msg);
RenderFrame(dt.count());
}
}
cbuffer CONST_BUFFER_DATA : register(b0)
{
matrix orthoMatrix;
matrix translateMatrix;
};
struct VOut {
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
};
VOut VShader(float4 position : POSITION, float2 tex : TEXCOORD0) {
VOut output;
position = mul(translateMatrix, position);
output.position = mul(orthoMatrix, position);
output.tex = tex;
return output;
}
Texture2D square_tex;
SamplerState tex_sampler;
float4 PShader(float4 position : SV_POSITION, float2 tex : TEXCOORD0) : SV_TARGET
{
float4 tex_col = square_tex.Sample(tex_sampler, tex);
return tex_col;
}
I have also included the initialization of the swapchain and backbuffer in case there is a mistake owing to it.
DXGI_SWAP_CHAIN_DESC scd; // hold swap chain information
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill swap chian description struct
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 (draw into back buffer)
scd.OutputWindow = hWnd; // window to be used
scd.SampleDesc.Count = 1; // how many multisamples
scd.Windowed = true; // windowed/full screen
// create device, device context and swap chain using scd
D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_DEBUG, nullptr, NULL, D3D11_SDK_VERSION, &scd, &swapchain, &dev, nullptr, &devcon);
// get address of back buffer
ID3D11Texture2D* pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use back buffer address to create render target
dev->CreateRenderTargetView(pBackBuffer, nullptr, &backbuffer);
pBackBuffer->Release();
// set the render target as the backbuffer
devcon->OMSetRenderTargets(1, &backbuffer, nullptr);
// Set the viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = WINDOW_WIDTH;
viewport.Height = WINDOW_HEIGHT;
devcon->RSSetViewports(1, &viewport); // activates viewport
I have also tried getting a pointer to the vertex data via the pData member of the D3D11_MAPPED_SUBRESOURCE object and then casting it to a VERTEX* to manipulate the data, but the problem persists. I would like to know how to move the sprite smoothly across the window.
I solved the problem by writing a fixed FPS game loop and giving the interpolated values between the previous and current states to the render function. I was also updating the constant buffer in an incorrect manner.

Directx11 drawing to wrong render target

I'm attempting to render to a texture for the purpose of shadow mapping in DirectX11. I've set up and bound a separate render target to draw to. Problem is, after calling OMSetRenderTargets it's still rendering to the previously bound render target.
The graphics diagnostics event list shows that OMSetRenderTargets is being called, setting "obj:30" as the render target view. However, the following DrawIndexed call shows the render target as "obj:17", which is the previously bound render target.
Event List
Draw Call
I have the DirectX debug layer enabled, however it does not show any errors or warning messages. I've also ensured that the texture is not bound as a shader resource when the draw call happens but no luck there either.
These are both called by the following function
void GraphicsHandler::DrawSceneToRenderTarget(ID3D11RenderTargetView* RenderTarget, ID3D11VertexShader* WithVertexShader, ID3D11PixelShader* WithPixelShader)
{
const unsigned int VertexSize = sizeof(Vertex);
const unsigned int Offset = 0;
DeviceContext->ClearDepthStencilView(DepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0.0f);
DeviceContext->VSSetShader(WithVertexShader, nullptr, 0);
DeviceContext->PSSetShader(WithPixelShader, nullptr, 0);
DeviceContext->OMSetRenderTargets(1, &RenderTarget, DepthStencilView); //Render target set here
for (auto& Obj : ActiveScene.Objects)
{
ObjectInfo ObjectData;
ObjectData.ObjectTransform = XMMatrixIdentity();
ObjectData.ObjectTransform *= XMMatrixRotationRollPitchYaw(Obj->Rotator.X, Obj->Rotator.Y, Obj->Rotator.Z);
ObjectData.ObjectTransform *= XMMatrixTranslation(Obj->Position.X, Obj->Position.Y, Obj->Position.Z);
ObjectData.ObjectTransform *= XMMatrixScaling(Obj->Scale.X, Obj->Scale.Y, Obj->Scale.Z);
ObjectData.NormalMatrix = XMMatrixTranspose(XMMatrixInverse(nullptr, ObjectData.ObjectTransform));
DeviceContext->UpdateSubresource(ObjectBuffer, 0, nullptr, &ObjectData, 0, 0);
DeviceContext->UpdateSubresource(MaterialBuffer, 0, nullptr, &Obj->Mat, 0, 0);
DeviceContext->IASetVertexBuffers(0, 1, &Obj->VertexBuffer, &VertexSize, &Offset);
DeviceContext->IASetIndexBuffer(Obj->IndexBuffer, DXGI_FORMAT_R16_UINT, 0);
DeviceContext->VSSetConstantBuffers(0, 1, &ObjectBuffer);
//DeviceContext->PSSetConstantBuffers(0, 1, &MaterialBuffer);
DeviceContext->DrawIndexed(Obj->Indices.size(), 0, 0); //Draw called here
}
}
with the problematic calls to that being in the following two functions
void GraphicsHandler::RenderSceneDepth()
{
DeviceContext->RSSetState(RasterizerState);
DeviceContext->PSSetShaderResources(0, 1, &SceneDepthSRV);
DeviceContext->UpdateSubresource(CameraBuffer, 0, nullptr, &ActiveScene.SceneCamera.GetCameraVSInfo(), 0, 0);
DeviceContext->VSSetConstantBuffers(1, 1, &CameraBuffer);
DeviceContext->ClearRenderTargetView(SceneDepthRTV, Colors::Black);
DrawSceneToRenderTarget(SceneDepthRTV, VertexShader, DepthShader);
}
void GraphicsHandler::RenderShadowMap(ShadowMap& SM)
{
//Clear shader resources, as the texture can't be bound as input and output
ID3D11ShaderResourceView* NullResources[2] = { nullptr, nullptr };
DeviceContext->PSSetShaderResources(0, 2, NullResources);
DeviceContext->RSSetState(SMRasterizerState); //Need to render back faces only
ID3D11SamplerState* Samplers[2] = { SamplerState, ShadowSamplerState };
DeviceContext->PSSetSamplers(0, 2, Samplers);
//If the light is a directional source, render a directional shadow map
DirectionalLight* DirLight = nullptr;
DirLight = dynamic_cast<DirectionalLight*>(SM.ParentLight);
if (DirLight)
{
ID3D11RenderTargetView* RTV = SM.RTVs[0];
SM.LightPovCamera.ForwardDirection = DirLight->Direction;
DeviceContext->ClearRenderTargetView(RTV, Colors::Black);
DeviceContext->UpdateSubresource(LightPovBuffer, 0, nullptr, &SM.LightPovCamera.GetCameraVSInfo(), 0, 0);
DeviceContext->VSSetConstantBuffers(1, 1, &LightPovBuffer);
DrawSceneToRenderTarget(RTV, VertexShader, DepthShader);
}
//Otherwise, render to each face of the texturecube
else
{
for (int N = 0; N < 6; N++)
{
DeviceContext->ClearRenderTargetView(SM.RTVs[N], Colors::Black);
Camera POVCam = SM.GetCameraForCubemapFace(N);
DeviceContext->UpdateSubresource(LightPovBuffer, 0, nullptr, &POVCam.GetCameraVSInfo(), 0, 0);
DeviceContext->VSSetConstantBuffers(1, 1, &LightPovBuffer);
DrawSceneToRenderTarget(SM.RTVs[N], VertexShader, DepthShader);
}
}
}
Woops my mistake, the debug layer actually wasn't enabled, the error was caused by the render target having different dimensions to the depth stencil view. Apologies!

DirectX Toolkit loaded model with custom HLSL shader Vertex shader input signature

I am working on a project in which I use DirectX Toolkit to load FBX models. As I understood, DXTK does not support HLSL shaders for its models, so I have to get the model information (vertex buffer, index buffer, etc.) from the model object and implement a standart Direct3D drawing, if I want to use HLSL shaders for the rendering.
My problem is, that I can't reach the texture coordinates from the vertex shader. For testing, I set the vertex shader to pass through the coordinates to the pixel shader, where I color the whole object with the texture coordinates like this:
float4(input.texCoord, 0.0f, 1.0f);
In the result, the whole object is black, so the texcoords are (0.0, 0.0) everywhere. I checked the model with the DXTK Model::Draw(...) funcion, and it is textured the correct way, so my model, and my model loading code seems correct.
I learnt that DXTK model loading uses the following vertex buffer declaration:
const D3D11_INPUT_ELEMENT_DESC VertexPositionNormalTangentColorTexture::InputElements[] =
{
{ "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TANGENT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
So I tried to match my vertex shader input structure like this:
struct VertexShaderInput
{
float3 pos : SV_Position;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 color : COLOR;
float2 texCoord : TEXCOORD;
};
Here is how I load the model:
void SceneObject::LoadMesh(
std::shared_ptr<DX::DeviceResources> deviceResources,
const wchar_t* modelFile)
{
auto device = deviceResources->GetD3DDevice();
EffectFactory fx(device);
this->model = Model::CreateFromCMO(device, modelFile, fx, true);
}
And here is my draw function:
void SceneObject::Draw(std::shared_ptr<DX::DeviceResources> deviceResources)
{
auto device = deviceResources->GetD3DDevice();
auto context = deviceResources->GetD3DDeviceContext();
CommonStates states(device);
context->UpdateSubresource(
this->vsConstantBuffer.Get(),
0,
NULL,
&this->vsConstantBufferData,
0,
0);
context->UpdateSubresource(
this->psConstantBuffer.Get(),
0,
NULL,
&this->psConstantBufferData,
0,
0);
//model->Draw(context, states, local, view, proj);
XMVECTOR qid = XMQuaternionIdentity();
const XMVECTORF32 scale = { 1.f, 1.f, 1.f };
const XMVECTORF32 translate = { 0.f, 0.f, 0.f };
//XMVECTOR rotate = XMQuaternionRotationRollPitchYaw(0, XM_PI / 2.f, -XM_PI / 2.f);
XMVECTOR rotate = XMQuaternionRotationRollPitchYaw(0, 0, 0);
XMMATRIX worldMatrix = XMLoadFloat4x4(&this->vsConstantBufferData.model);
XMMATRIX local = XMMatrixMultiply(worldMatrix, XMMatrixTransformation(g_XMZero, qid, scale, g_XMZero, rotate, translate));
//this->model->Draw(context, states, local, XMLoadFloat4x4(&vsConstantBufferData.view), XMLoadFloat4x4(&vsConstantBufferData.projection), false);
XMStoreFloat4x4(&this->vsConstantBufferData.model, local);
for each(auto& mesh in model->meshes)
{
for each (auto& part in mesh->meshParts)
{
context->IASetVertexBuffers(
0,
1,
part->vertexBuffer.GetAddressOf(),
&part->vertexStride,
&part->vertexOffset
);
context->IASetIndexBuffer(
part->indexBuffer.Get(),
part->indexFormat,
0
);
context->IASetPrimitiveTopology(part->primitiveType);
//context->IASetInputLayout(inputLayout.Get());
context->IASetInputLayout(part->inputLayout.Get());
// Attach our vertex shader.
context->VSSetShader(
vertexShader.Get(),
nullptr,
0
);
// Send the constant buffer to the graphics device.
context->VSSetConstantBuffers(
0,
1,
vsConstantBuffer.GetAddressOf()
);
// Attach our pixel shader.
context->PSSetShader(
pixelShader.Get(),
nullptr,
0
);
// Send the constant buffer to the graphics device.
context->PSSetConstantBuffers(
1,
1,
psConstantBuffer.GetAddressOf()
);
context->PSSetShaderResources(0, 1, diffuseTexture.GetAddressOf());
context->PSSetSamplers(0, 1, linearSampler.GetAddressOf());
// Draw the objects.
context->DrawIndexed(
part->indexCount,
part->startIndex,
0
);
}
}
}
If you need more code, you can check my whole project here: https://github.com/GiGu92/WaterRenderingDemo
What am I messing up?
Your code above doesn't indicate where you are creating your vertex shader.
For CMOs, take a look at Src\Shaders\DGSLEffect.fx for how they are used with custom shaders.
The default EffectFactory or DGSLEffectFactory is setting up a standard vertex & pixel shader for rendering the Model as a BasicEffect, SkinnedEffect, or DGSLEffect. Details on doing custom rendering are covered in the wiki, but I suggest your first get it rendering using the default effects as you expect it. See the tutorial.
You can override the entire pipeline if desired in a number of ways:
Implement your own IEffect* interfaces and IEffectFactory to use with the Model loader
Override the shaders while rendering directly with ModelMesh / ModelMeshParts
For CMO files, the vertex format is indeed either VertexPositionNormalTangentColorTexture or VertexPositionNormalTangentColorTextureSkinning, although for SDKMESH files it is a bit more variable.
As always, ensure you have the debug device enabled and check the HRESULT of any Direct3D function that returns one to ensure you aren't missing some configuration or API usage problem.

D3D11 DrawIndexed() is drawing to the wrong render target

I'm attempting to render a scene to two textures (left and right) for use with the Oculus Rift. When I set the render target to a 2D texture render view and call DrawIndexed() it renders to the back buffer instead of the texture. I'm using Visual Studio, and I've run the Graphics Diagnostics on it. On the DrawIndexed() event, it shows the render target is the texture, but the pixel history doesn't show the event. If I don't clear the backbuffer, the scene shows up on the screen.
In the following code, the RenderLeft() function should render an image to a plane on a green background with the render target set as the left render texture. Then RenderRight() should take the texture rendered by RenderLeft(), and render it to the plane, then output that on the back buffer. (Note: This isn't the normal set up. This is just to help see if the texture is being rendered to or not)
In the final output, there should be nothing on the left side of the screen, and on the right should be the source image inside a green rectangle on a black background.
Instead, I get this: http://i.imgur.com/dHX5Ed3.png?1
RenderLeft is rendering to the back buffer, even though the render target is a texture, so then the texture used by RenderRight is just the color used to clear it.
Here is the code I'm currently using. I think I've included everything that's relevant.
// this is the function used to render a single frame
void Direct3D::RenderFrame()
{
CreateTransforms(); //this creates matFinalLeft and matFinalRight, which is (world matrix)*(view matrix)*(projection matrix) with the proper offsets for a stereoscopic view.
setVertices(); //this sets the vertex and index buffers.
setMainShaders(); // this sets the shaders used to render the 3D scene
RenderLeft(pTextureLeftRenderView, matFinalLeft, viewportLeft, true); //this renders an image to a plane on a green background. It SHOULD render to a texture.
RenderRight(backbuffer, matFinalRight, viewportRight, false);//this renders the render target from RenderLeft to the plane and renders to the back buffer.
swapchain->Present(0, 0); //output back buffer to screen.
}
This section should render a rectangle textured with an image to the left side of the render texture.
//Render the scene to the left side of a texture
void Direct3D::RenderLeft(ID3D11RenderTargetView *RenderTarget, D3DXMATRIX matFinal, D3D11_VIEWPORT viewport, bool clearRenderTarget){
devcon->OMSetRenderTargets(1, &RenderTarget, zbuffer);
devcon->RSSetViewports(1, &viewport);
// update shader resources
devcon->UpdateSubresource(pCBufferPrimaryShader, 0, 0, &matFinal, 0, 0);
devcon->PSSetShaderResources(0, 1, &pTextureLeftResourceView);
// clear the depth buffer and render target texture
devcon->ClearDepthStencilView(zbuffer, D3D11_CLEAR_DEPTH, 1.0f, 0);
if (clearRenderTarget){
devcon->ClearRenderTargetView(RenderTarget, D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f));
}
// render to texture on left side (oculus) or full texture
devcon->DrawIndexed(6, 0, 0);
}
This section should render a rectangle with the texture from RenderLeft() to the back buffer.
//Render the scene to the right side of the back buffer
void Direct3D::RenderRight(ID3D11RenderTargetView *RenderTarget, D3DXMATRIX matFinal, D3D11_VIEWPORT viewport, bool clearRenderTarget){
//render to texture
devcon->OMSetRenderTargets(1, &RenderTarget, zbuffer);
devcon->RSSetViewports(1, &viewport);
// update shader resources
devcon->UpdateSubresource(pCBufferPrimaryShader, 0, 0, &matFinal, 0, 0);
devcon->PSSetShaderResources(0, 1, &pRenderTextureLeftResourceView);
// clear the depth buffer and render target texture
devcon->ClearDepthStencilView(zbuffer, D3D11_CLEAR_DEPTH, 1.0f, 0);
if (clearRenderTarget){
devcon->ClearRenderTargetView(RenderTarget, D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f));
}
// render to texture on left side (oculus) or full texture
devcon->DrawIndexed(6, 0, 0);
}
Finally, the code that creates the various views and viewports
void Direct3D::InitD3D(HWND hWnd)
{
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferDesc.Width = screen_width;
scd.BufferDesc.Height = screen_height;
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
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
// create a device, device context and swap chain using the information in the scd struct
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);
// create the depth buffer texture
D3D11_TEXTURE2D_DESC texd;
ZeroMemory(&texd, sizeof(texd));
texd.Width = screen_width;
texd.Height = screen_height;
texd.ArraySize = 1;
texd.MipLevels = 1;
texd.SampleDesc.Count = 4;
texd.Format = DXGI_FORMAT_D32_FLOAT;
texd.BindFlags = D3D11_BIND_DEPTH_STENCIL;
ID3D11Texture2D *pDepthBuffer;
dev->CreateTexture2D(&texd, NULL, &pDepthBuffer);
// create the depth buffer
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
ZeroMemory(&dsvd, sizeof(dsvd));
dsvd.Format = DXGI_FORMAT_D32_FLOAT;
dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
dev->CreateDepthStencilView(pDepthBuffer, &dsvd, &zbuffer);
pDepthBuffer->Release();
// 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();
//create intermediate render textures
ID3D11Texture2D *pRenderTextureLeft;
D3D11_TEXTURE2D_DESC textureDesc;
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = screen_width;
textureDesc.Height = screen_height;
if (oculus){
textureDesc.Width = (UINT)((FLOAT)textureDesc.Width * oculus->renderScale);
textureDesc.Height = (UINT)((FLOAT)textureDesc.Height *oculus->renderScale);
}
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
dev->CreateTexture2D(&textureDesc, NULL, &pRenderTextureLeft);
renderTargetViewDesc.Format = textureDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
dev->CreateRenderTargetView(pRenderTextureLeft, &renderTargetViewDesc, &pTextureLeftRenderView);
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
dev->CreateShaderResourceView(pRenderTextureLeft, &shaderResourceViewDesc, &pRenderTextureLeftResourceView);
ID3D11Texture2D *pRenderTextureRight;
dev->CreateTexture2D(&textureDesc, NULL, &pRenderTextureRight);
dev->CreateRenderTargetView(pRenderTextureRight, &renderTargetViewDesc, &pTextureRightRenderView);
dev->CreateShaderResourceView(pRenderTextureRight, &shaderResourceViewDesc, &pRenderTextureRightResourceView);
/*if (oculus){
pOculusOutputDevice = oculus->searchForOculusDisplay(oculus->hmd.DisplayDeviceName);
swapchain->SetFullscreenState(TRUE, pOculusOutputDevice);
}*/
// Set the viewport
ZeroMemory(&viewportLeft, sizeof(D3D11_VIEWPORT));
ZeroMemory(&viewportRight, sizeof(D3D11_VIEWPORT));
ZeroMemory(&viewportCenter, sizeof(D3D11_VIEWPORT));
viewportCenter.TopLeftX = 0.0f;
viewportCenter.TopLeftY = 0.0f;
if (oculus){
viewportCenter.Width = (FLOAT)screen_width*oculus->renderScale;
viewportCenter.Height = (FLOAT)screen_height*oculus->renderScale;
}
else{
viewportCenter.Width = (FLOAT)screen_width;
viewportCenter.Height = (FLOAT)screen_height;
}
viewportCenter.MinDepth = 0.0f;
viewportCenter.MaxDepth = 1.0f;
if (dual_mode){
viewportLeft.TopLeftX = 0.0f;
viewportLeft.TopLeftY = 0.0f;
viewportLeft.Width = (FLOAT)screen_width / 2.0f;
viewportLeft.Height = (FLOAT)screen_height;
viewportLeft.MinDepth = 0.0f;
viewportLeft.MaxDepth = 1.0f;
viewportRight.TopLeftX = (FLOAT)screen_width / 2.0f;
viewportRight.TopLeftY = 0.0f;
viewportRight.Width = (FLOAT)screen_width / 2.0f;
viewportRight.Height = (FLOAT)screen_height;
viewportRight.MinDepth = 0.0f;
viewportRight.MaxDepth = 1.0f;
}
devcon->RSSetViewports(1, &viewportCenter);
InitPipeline();
InitGraphics();
}
Per request, here is some more code:
I'm including the entire Direct3D class header, so you can see what are and are not member variables.
#pragma once
#include "Oculus.h"
#include <OVR.h>
#include "Camera.h"
#include <d3d11.h>
#include <D3DX11.h>
#include <D3DX10.h>
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")
class Direct3D
{
public:
struct VERTEX{ FLOAT X, Y, Z; D3DXCOLOR Color; FLOAT U, V; };
struct DISTORTION{
FLOAT LensCenter[2];
FLOAT ScreenCenter[2];
FLOAT Scale[2];
FLOAT ScaleIn[2];
FLOAT HmdWarpParam[4];
};
IDXGISwapChain *swapchain; // the pointer to the swap chain interface
ID3D11Device *dev; // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon; // the pointer to our Direct3D device context
ID3D11RenderTargetView *backbuffer;
IDXGIOutput* pOculusOutputDevice;
ID3D11VertexShader *pVS_Primary; // the vertex shader
ID3D11PixelShader *pPS_Primary; // the pixel shader
ID3D11VertexShader *pVS_Distortion;
ID3D11PixelShader *pPS_Distortion; // the pixel shader
ID3D11Buffer *pVBuffer; //vertec buffer
ID3D11Buffer *pIBuffer;
ID3D11InputLayout *pLayout_Primary;
ID3D11InputLayout *pLayout_Distortion;
D3D11_VIEWPORT viewportLeft;
D3D11_VIEWPORT viewportRight;
D3D11_VIEWPORT viewportCenter;
ID3D11Buffer *pCBufferPrimaryShader;
ID3D11Buffer *pCBufferDistortionShader;
ID3D11DepthStencilView *zbuffer; // the pointer to our depth buffer
ID3D11ShaderResourceView *pTextureLeftResourceView; // the pointer to the texture
ID3D11ShaderResourceView *pTextureRightResourceView;
ID3D11ShaderResourceView *pRenderTextureLeftResourceView;
ID3D11ShaderResourceView *pRenderTextureRightResourceView;
ID3D11RenderTargetView *pTextureLeftRenderView;
ID3D11RenderTargetView *pTextureRightRenderView;
D3DXMATRIX matFinalLeft;
D3DXMATRIX matFinalRight;
Camera cameraLeft, cameraRight;
int screen_width;
int screen_height;
bool dual_mode;
Oculus* oculus;
Direct3D(Oculus* oculus);
Direct3D();
~Direct3D();
void InitD3D(HWND hWnd); // sets up and initializes Direct3D
void CleanD3D(void); // closes Direct3D and releases memory
void RenderFrame();
void InitPipeline();
void InitGraphics();
void RenderLeft(ID3D11RenderTargetView *RenderTarget, D3DXMATRIX matFinal, D3D11_VIEWPORT viewport, bool clearRenderTarget);
void RenderRight(ID3D11RenderTargetView *RenderTarget, D3DXMATRIX matFinal, D3D11_VIEWPORT viewport, bool clearRenderTarget);
void DistortionCorrection(ID3D11RenderTargetView *RenderTarget);
void CreateTransforms();
void setVertices();
void setMainShaders();
void OVRMatrix4fToD3DXMatrix(OVR::Matrix4f& source, D3DXMATRIX& dest);
};
And here is the code that initializes the image textures (right now they load the same image to two different textures. It's eventually going to be the two sides of the 3D image. Just as soon as i figure out how to access the second image in the file)
FILENAME is #defined as the name of the image file I'm displaying
void Direct3D::InitGraphics()
{
D3DX11CreateShaderResourceViewFromFile(dev, // the Direct3D device
FILENAME, // load Wood.png in the local folder
NULL, // no additional information
NULL, // no multithreading
&pTextureLeftResourceView, // address of the shader-resource-view
NULL); // no multithreading
D3DX11CreateShaderResourceViewFromFile(dev, // the Direct3D device
FILENAME, // load Wood.png in the local folder
NULL, // no additional information
NULL, // no multithreading
&pTextureRightResourceView, // address of the shader-resource-view
NULL); // no multithreading
// get image size for rectangle mesh size
D3DX11_IMAGE_INFO info;
D3DX11GetImageInfoFromFile(FILENAME, NULL, &info, NULL);
FLOAT textureWidth = info.Width*0.001f;
FLOAT textureHeight = info.Height*0.001f;
// create vertices to represent the corners of the cube
VERTEX OurVertices[] =
{
{ -textureWidth, -textureHeight, 2.0f, D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f), 1.0f, 1.0f },
{ textureWidth, -textureHeight, 2.0f, D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f), 0.0f, 1.0f },
{ -textureWidth, textureHeight, 2.0f, D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f), 1.0f, 0.0f },
{ textureWidth, textureHeight, 2.0f, D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f), 0.0f, 0.0f }
};
// create the vertex buffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(VERTEX)* 4;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
dev->CreateBuffer(&bd, NULL, &pVBuffer);
// copy the vertices into the buffer
D3D11_MAPPED_SUBRESOURCE ms;
devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, OurVertices, sizeof(OurVertices)); // copy the data
devcon->Unmap(pVBuffer, NULL);
// create the index buffer out of DWORDs
DWORD OurIndices[] =
{
0, 1, 2, // side 1
2, 1, 3,
};
// create the index buffer
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(DWORD)* 6;
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
dev->CreateBuffer(&bd, NULL, &pIBuffer);
devcon->Map(pIBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, OurIndices, sizeof(OurIndices)); // copy the data
devcon->Unmap(pIBuffer, NULL);
}
And just in case you need it, here is the initialization of the rendering pipeline.
void Direct3D::InitPipeline()
{
// compile the shaders
ID3D10Blob *VS_Primary, *PS_Primary, *VS_Distortion, *PS_Distortion;
D3DX11CompileFromFile("vs_primary.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS_Primary, 0, 0);
D3DX11CompileFromFile("ps_primary.hlsl", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS_Primary, 0, 0);
D3DX11CompileFromFile("vs_distortion.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS_Distortion, 0, 0);
D3DX11CompileFromFile("ps_distortion.hlsl", 0, 0, "main", "ps_5_0", 0, 0, 0, &PS_Distortion, 0, 0);
// create the shader objects
dev->CreateVertexShader(VS_Primary->GetBufferPointer(), VS_Primary->GetBufferSize(), NULL, &pVS_Primary);
dev->CreatePixelShader(PS_Primary->GetBufferPointer(), PS_Primary->GetBufferSize(), NULL, &pPS_Primary);
dev->CreateVertexShader(VS_Distortion->GetBufferPointer(), VS_Distortion->GetBufferSize(), NULL, &pVS_Distortion);
dev->CreatePixelShader(PS_Distortion->GetBufferPointer(), PS_Distortion->GetBufferSize(), NULL, &pPS_Distortion);
// set the shader objects
devcon->VSSetShader(pVS_Primary, 0, 0);
devcon->PSSetShader(pPS_Primary, 0, 0);
// create the input element object
D3D11_INPUT_ELEMENT_DESC ied[] =
{
{ "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 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
// use the input element descriptions to create the input layout
dev->CreateInputLayout(ied, 3, VS_Primary->GetBufferPointer(), VS_Primary->GetBufferSize(), &pLayout_Primary);
devcon->IASetInputLayout(pLayout_Primary);
dev->CreateInputLayout(ied, 3, VS_Distortion->GetBufferPointer(), VS_Distortion->GetBufferSize(), &pLayout_Distortion);
devcon->IASetInputLayout(pLayout_Distortion);
// create the constant buffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = 64;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
dev->CreateBuffer(&bd, NULL, &pCBufferPrimaryShader);
devcon->VSSetConstantBuffers(0, 1, &pCBufferPrimaryShader);
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = 48;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
dev->CreateBuffer(&bd, NULL, &pCBufferDistortionShader);
}
Pixel Shader:
Texture2D Texture;
SamplerState ss;
float4 PShader(float4 color : COLOR, float2 texcoord : TEXCOORD0) : SV_TARGET
{
return color * Texture.Sample(ss, texcoord);
}
Vertex Shader:
cbuffer ConstantBuffer
{
float4x4 matFinal;
}
struct VOut
{
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 position : SV_POSITION;
};
VOut VShader(float4 position : POSITION, float4 color : COLOR, float2 texcoord : TEXCOORD0)
{
VOut output;
output.position = mul(matFinal, position);
output.color = color;
output.texcoord = texcoord;
return output;
}
From the following code, I didn't see how you pass the texture from RenderLeft() to RenderRight(). You just pass backbuffer to RenderRight().
RenderLeft(pTextureLeftRenderView, matFinalLeft, viewportLeft, true);
RenderRight(backbuffer, matFinalRight, viewportRight, false);
So the result is the texture rendered to the left viewport and the right viewport only show the color(green) of the backbuffer.

Can't create vertex buffer

I have a Windows Phone 8 C#/XAML project with DirectX component. I'm trying to rendering some particles. I create a vertex buffer, which I saw it go into the function to create, but when it gets to an update vertex buffer, the buffer is NULL. I have not released the buffers yet. Do you know why this will happen? Does any of the output messages help? Thanks.
Printouts and errors on my Output Window:
'TaskHost.exe' (Win32): Loaded '\Device\HarddiskVolume4\Windows\System32\d3d11_1SDKLayers.dll'. Cannot find or open the PDB file.
D3D11 WARNING: ID3D11Texture2D::SetPrivateData: Existing private data of same name with different size found! [ STATE_SETTING WARNING #55: SETPRIVATEDATA_CHANGINGPARAMS]
Create vertex buffer
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 0, but none is bound. This is perfectly valid, as a NULL Sampler maps to default Sampler state. However, the developer may not want to rely on the defaults. [ EXECUTION WARNING #352: DEVICE_DRAW_SAMPLER_NOT_SET]
The thread 0xb64 has exited with code 0 (0x0).
m_vertexBuffer is null
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 0, but none is bound. This is perfectly valid, as a NULL Sampler maps to default Sampler state. However, the developer may not want to rely on the defaults. [ EXECUTION WARNING #352: DEVICE_DRAW_SAMPLER_NOT_SET]
m_vertexBuffer is null
In CreateDeviceResources, I call CreateVertexShader, CreateInputLayout, CreatePixelShader, CreateBuffer. Then I get to creating the sampler and vertex buffer, code below:
auto createCubeTask = (createPSTask && createVSTask).then([this] () {
// Create a texture sampler state description.
D3D11_SAMPLER_DESC samplerDesc;
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.BorderColor[0] = 0;
samplerDesc.BorderColor[1] = 0;
samplerDesc.BorderColor[2] = 0;
samplerDesc.BorderColor[3] = 0;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
// Create the texture sampler state.
HRESULT result = m_d3dDevice->CreateSamplerState(&samplerDesc, &m_sampleState);
if(FAILED(result))
{
OutputDebugString(L"Can't CreateSamplerState");
}
//InitParticleSystem();
// Set the maximum number of vertices in the vertex array.
m_vertexCount = m_maxParticles * 6;
// Set the maximum number of indices in the index array.
m_indexCount = m_vertexCount;
// Create the vertex array for the particles that will be rendered.
m_vertices = new VertexType[m_vertexCount];
if(!m_vertices)
{
OutputDebugString(L"Can't create the vertex array for the particles that will be rendered.");
}
else
{
// Initialize vertex array to zeros at first.
int sizeOfVertexType = sizeof(VertexType);
int totalSizeVertex = sizeOfVertexType * m_vertexCount;
memset(m_vertices, 0, totalSizeVertex);
D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
vertexBufferData.pSysMem = m_vertices;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
int sizeOfMVertices = sizeof(m_vertices);
CD3D11_BUFFER_DESC vertexBufferDesc(
totalSizeVertex, // byteWidth
D3D11_BIND_VERTEX_BUFFER, // bindFlags
D3D11_USAGE_DYNAMIC, // D3D11_USAGE usage = D3D11_USAGE_DEFAULT
D3D11_CPU_ACCESS_WRITE, // cpuaccessFlags
0, // miscFlags
0 // structureByteStride
);
OutputDebugString(L"Create vertex buffer\n");
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&vertexBufferDesc,
&vertexBufferData,
&m_vertexBuffer
)
);
}
unsigned long* indices = new unsigned long[m_indexCount];
if(!indices)
{
OutputDebugString(L"Can't create the index array.");
}
else
{
// Initialize the index array.
for(int i=0; i<m_indexCount; i++)
{
indices[i] = i;
}
// Set up the description of the static index buffer.
// Create the index array.
D3D11_BUFFER_DESC indexBufferDesc;
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;
// Give the subresource structure a pointer to the index data.
D3D11_SUBRESOURCE_DATA indexData;
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;
// Create the index buffer.
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&indexBufferDesc,
&indexData,
&m_indexBuffer
)
);
// Release the index array since it is no longer needed.
delete [] indices;
indices = 0;
}
});
createCubeTask.then([this] () {
m_loadingComplete = true;
});
}
My vertex is position, tex, and color:
struct VertexType
{
DirectX::XMFLOAT3 position;
DirectX::XMFLOAT2 texture;
DirectX::XMFLOAT4 color;
};
Microsoft::WRL::ComPtr<ID3D11SamplerState> m_sampleState;
VertexType* m_vertices;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_vertexBuffer;
const D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
VertexShader.HLSL:
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
struct VertexInputType
{
float4 position : POSITION;
float2 tex : TEXCOORD0;
float4 color : COLOR;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
float4 color : COLOR;
};
PixelInputType main(VertexInputType input)
{
PixelInputType output;
// Change the position vector to be 4 units for proper matrix calculations.
input.position.w = 1.0f;
// Calculate the position of the vertex against the world, view, and projection matrices.
output.position = mul(input.position, model);
output.position = mul(output.position, view);
output.position = mul(output.position, projection);
// Store the texture coordinates for the pixel shader.
output.tex = input.tex;
// Store the particle color for the pixel shader.
output.color = input.color;
return output;
}
After the call to: m_d3dDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &m_vertexBuffer) the m_vertexBuffer is not null.
But when I get to my Update() function, m_vertexBuffer is NULL!
D3D11_MAPPED_SUBRESOURCE mappedResource;
if (m_vertexBuffer == nullptr)
{
OutputDebugString(L"m_vertexBuffer is null\n");
}
else
{
// Lock the vertex buffer.
DX::ThrowIfFailed(m_d3dContext->Map(m_vertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource));
// Get a pointer to the data in the vertex buffer.
VertexType * verticesPtr = (VertexType*)mappedResource.pData;
//// Copy the data into the vertex buffer.
int sizeOfVertices = sizeof(VertexType) * m_vertexCount;
memcpy(verticesPtr, (void*)m_vertices, sizeOfVertices);
//// Unlock the vertex buffer.
m_d3dContext->Unmap(m_vertexBuffer.Get(), 0);
}
About the sampler, you need to assign it to your pixelshader.
m_d3dContext.Get()->PSSetSamplers(0,1,&m_sampleState);
I was making the incorrect call on m_vertexBuffer when I go Render it.
This fixes the error with the m_vertexBuffer being null.
Previous:
m_d3dContext.Get()->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
Fix:
m_d3dContext.Get()->IASetVertexBuffers(0, 1, m_vertexBuffer.GetAddressOf(), &stride, &offset);
It doesn't fix the error with the sampler states though:
DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot
0