mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-10 22:31:32 +00:00
* Wireframes can render without a near plane clip and be mostly fine, but solid renders need the depth so they should clip. Behaviour was inconsistent between APIs before
646 lines
24 KiB
C++
646 lines
24 KiB
C++
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2019-2025 Baldur Karlsson
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
#include "maths/camera.h"
|
|
#include "maths/formatpacking.h"
|
|
#include "maths/matrix.h"
|
|
#include "d3d11_context.h"
|
|
#include "d3d11_debug.h"
|
|
#include "d3d11_device.h"
|
|
#include "d3d11_replay.h"
|
|
#include "d3d11_resources.h"
|
|
|
|
#include "data/hlsl/hlsl_cbuffers.h"
|
|
|
|
static uint32_t VisModeToMeshDisplayFormat(const MeshDisplay &cfg)
|
|
{
|
|
switch(cfg.visualisationMode)
|
|
{
|
|
default: return (uint32_t)cfg.visualisationMode;
|
|
case Visualisation::Secondary:
|
|
return cfg.second.showAlpha ? MESHDISPLAY_SECONDARY_ALPHA : MESHDISPLAY_SECONDARY;
|
|
case Visualisation::Meshlet:
|
|
RDCERR("D3D11 does not support meshlet rendering");
|
|
return MESHDISPLAY_SOLID;
|
|
}
|
|
}
|
|
|
|
void D3D11Replay::RenderMesh(uint32_t eventId, const rdcarray<MeshFormat> &secondaryDraws,
|
|
const MeshDisplay &cfg)
|
|
{
|
|
if(cfg.position.vertexResourceId == ResourceId() || cfg.position.numIndices == 0)
|
|
return;
|
|
|
|
D3D11MarkerRegion renderMesh(
|
|
StringFormat::Fmt("RenderMesh with %zu secondary draws", secondaryDraws.size()));
|
|
|
|
MeshVertexCBuffer vertexData;
|
|
MeshPixelCBuffer pixelData;
|
|
|
|
D3D11RenderStateTracker tracker(m_pImmediateContext);
|
|
|
|
float nearPlane = cfg.cam ? ((Camera *)cfg.cam)->GetNear() : 0.1f;
|
|
float farPlane = cfg.cam ? ((Camera *)cfg.cam)->GetFar() : 100000.0f;
|
|
|
|
Matrix4f projMat =
|
|
Matrix4f::Perspective(90.0f, nearPlane, farPlane, m_OutputWidth / m_OutputHeight);
|
|
|
|
Matrix4f camMat = cfg.cam ? ((Camera *)cfg.cam)->GetMatrix() : Matrix4f::Identity();
|
|
|
|
Matrix4f axisMapMat = Matrix4f(cfg.axisMapping);
|
|
|
|
Matrix4f guessProjInv;
|
|
|
|
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(axisMapMat));
|
|
vertexData.SpriteSize = Vec2f();
|
|
vertexData.homogenousInput = cfg.position.unproject;
|
|
vertexData.vtxExploderSNorm = cfg.vtxExploderSliderSNorm;
|
|
vertexData.exploderCentre =
|
|
Vec3f((cfg.minBounds.x + cfg.maxBounds.x) * 0.5f, (cfg.minBounds.y + cfg.maxBounds.y) * 0.5f,
|
|
(cfg.minBounds.z + cfg.maxBounds.z) * 0.5f);
|
|
vertexData.exploderScale =
|
|
(cfg.visualisationMode == Visualisation::Explode) ? cfg.exploderScale : 0.0f;
|
|
|
|
Vec4f col(0.0f, 0.0f, 0.0f, 1.0f);
|
|
ID3D11Buffer *psCBuf = GetDebugManager()->MakeCBuffer(&col, sizeof(col));
|
|
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &psCBuf);
|
|
m_pImmediateContext->PSSetShader(m_General.FixedColPS, NULL, 0);
|
|
|
|
m_pImmediateContext->HSSetShader(NULL, NULL, 0);
|
|
m_pImmediateContext->DSSetShader(NULL, NULL, 0);
|
|
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
|
|
|
|
m_pImmediateContext->OMSetDepthStencilState(NULL, 0);
|
|
m_pImmediateContext->OMSetBlendState(m_MeshRender.WireframeHelpersBS, NULL, 0xffffffff);
|
|
|
|
// don't cull in wireframe mesh display
|
|
m_pImmediateContext->RSSetState(m_MeshRender.WireframeRasterState);
|
|
|
|
const ResourceFormat &resFmt = cfg.position.format;
|
|
const ResourceFormat &resFmt2 = cfg.second.format;
|
|
|
|
if(m_MeshRender.PrevPositionFormat != resFmt || m_MeshRender.PrevSecondaryFormat != resFmt2)
|
|
{
|
|
SAFE_RELEASE(m_MeshRender.MeshLayout);
|
|
|
|
D3D11_INPUT_ELEMENT_DESC layoutdesc[2];
|
|
|
|
layoutdesc[0].SemanticName = "pos";
|
|
layoutdesc[0].SemanticIndex = 0;
|
|
layoutdesc[0].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
if(cfg.position.vertexResourceId != ResourceId() && (resFmt.Special() || resFmt.compCount > 0))
|
|
layoutdesc[0].Format = MakeDXGIFormat(resFmt);
|
|
layoutdesc[0].AlignedByteOffset = 0; // offset will be handled by vertex buffer offset
|
|
layoutdesc[0].InputSlot = 0;
|
|
layoutdesc[0].InputSlotClass =
|
|
cfg.position.instanced ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
|
|
layoutdesc[0].InstanceDataStepRate = 0;
|
|
|
|
layoutdesc[1].SemanticName = "sec";
|
|
layoutdesc[1].SemanticIndex = 0;
|
|
layoutdesc[1].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
if(cfg.second.vertexResourceId != ResourceId() && (resFmt2.Special() || resFmt2.compCount > 0))
|
|
layoutdesc[1].Format = MakeDXGIFormat(resFmt2);
|
|
layoutdesc[1].AlignedByteOffset = 0;
|
|
layoutdesc[1].InputSlot = 1;
|
|
layoutdesc[1].InputSlotClass =
|
|
cfg.second.instanced ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
|
|
layoutdesc[1].InstanceDataStepRate = 0;
|
|
|
|
HRESULT hr = m_pDevice->CreateInputLayout(layoutdesc, 2, m_MeshRender.MeshVSBytecode,
|
|
m_MeshRender.MeshVSBytelen, &m_MeshRender.MeshLayout);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failed to create m_MeshRender.m_MeshDisplayLayout HRESULT: %s", ToStr(hr).c_str());
|
|
m_MeshRender.MeshLayout = NULL;
|
|
}
|
|
}
|
|
|
|
m_MeshRender.PrevPositionFormat = resFmt;
|
|
m_MeshRender.PrevSecondaryFormat = resFmt2;
|
|
|
|
RDCASSERT(cfg.position.indexByteOffset < 0xffffffff);
|
|
|
|
ID3D11Buffer *ibuf = NULL;
|
|
DXGI_FORMAT ifmt = DXGI_FORMAT_R16_UINT;
|
|
UINT ioffs = (UINT)cfg.position.indexByteOffset;
|
|
|
|
D3D11_PRIMITIVE_TOPOLOGY topo = MakeD3DPrimitiveTopology(cfg.position.topology);
|
|
|
|
ID3D11Buffer *vsCBuf = NULL;
|
|
|
|
// render the mesh itself (solid, then wireframe)
|
|
{
|
|
if(cfg.position.unproject)
|
|
{
|
|
// the derivation of the projection matrix might not be right (hell, it could be an
|
|
// orthographic projection). But it'll be close enough likely.
|
|
Matrix4f guessProj =
|
|
cfg.position.farPlane != FLT_MAX
|
|
? Matrix4f::Perspective(cfg.fov, cfg.position.nearPlane, cfg.position.farPlane,
|
|
cfg.aspect)
|
|
: Matrix4f::ReversePerspective(cfg.fov, cfg.position.nearPlane, cfg.aspect);
|
|
|
|
if(cfg.ortho)
|
|
{
|
|
guessProj = Matrix4f::Orthographic(cfg.position.nearPlane, cfg.position.farPlane);
|
|
}
|
|
|
|
if(cfg.position.flipY)
|
|
{
|
|
guessProj[5] *= -1.0f;
|
|
}
|
|
|
|
guessProjInv = guessProj.Inverse();
|
|
|
|
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(guessProjInv));
|
|
}
|
|
|
|
vsCBuf = GetDebugManager()->MakeCBuffer(&vertexData, sizeof(vertexData));
|
|
|
|
m_pImmediateContext->VSSetConstantBuffers(0, 1, &vsCBuf);
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &psCBuf);
|
|
|
|
m_pImmediateContext->VSSetShader(m_MeshRender.MeshVS, NULL, 0);
|
|
m_pImmediateContext->PSSetShader(m_MeshRender.MeshPS, NULL, 0);
|
|
|
|
// secondary draws - this is the "draw since last clear" feature. We don't have
|
|
// full flexibility, it only draws wireframe, and only the final rasterized position.
|
|
if(secondaryDraws.size() > 0)
|
|
{
|
|
m_pImmediateContext->IASetInputLayout(m_MeshRender.GenericLayout);
|
|
|
|
pixelData.MeshDisplayFormat = MESHDISPLAY_SOLID;
|
|
|
|
for(size_t i = 0; i < secondaryDraws.size(); i++)
|
|
{
|
|
const MeshFormat &fmt = secondaryDraws[i];
|
|
|
|
if(fmt.vertexResourceId != ResourceId())
|
|
{
|
|
pixelData.MeshColour = Vec3f(fmt.meshColor.x, fmt.meshColor.y, fmt.meshColor.z);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &pixelData, sizeof(pixelData));
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &psCBuf);
|
|
|
|
m_pImmediateContext->IASetPrimitiveTopology(MakeD3DPrimitiveTopology(fmt.topology));
|
|
|
|
auto it = WrappedID3D11Buffer::m_BufferList.find(fmt.vertexResourceId);
|
|
|
|
ID3D11Buffer *buf = it->second.m_Buffer;
|
|
m_pImmediateContext->IASetVertexBuffers(0, 1, &buf, (UINT *)&fmt.vertexByteStride,
|
|
(UINT *)&fmt.vertexByteOffset);
|
|
if(fmt.indexResourceId != ResourceId())
|
|
{
|
|
RDCASSERT(fmt.indexByteOffset < 0xffffffff);
|
|
|
|
it = WrappedID3D11Buffer::m_BufferList.find(fmt.indexResourceId);
|
|
buf = it->second.m_Buffer;
|
|
m_pImmediateContext->IASetIndexBuffer(
|
|
buf, fmt.indexByteStride == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT,
|
|
(UINT)fmt.indexByteOffset);
|
|
|
|
m_pImmediateContext->DrawIndexed(fmt.numIndices, 0, fmt.baseVertex);
|
|
}
|
|
else
|
|
{
|
|
m_pImmediateContext->Draw(fmt.numIndices, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ID3D11InputLayout *layout = m_MeshRender.MeshLayout;
|
|
|
|
if(layout == NULL)
|
|
{
|
|
RDCWARN("Couldn't get a mesh display layout");
|
|
return;
|
|
}
|
|
|
|
m_pImmediateContext->IASetInputLayout(layout);
|
|
|
|
RDCASSERT(cfg.position.vertexByteOffset < 0xffffffff && cfg.second.vertexByteOffset < 0xffffffff);
|
|
|
|
ID3D11Buffer *vbs[2] = {NULL, NULL};
|
|
UINT str[] = {cfg.position.vertexByteStride, cfg.second.vertexByteStride};
|
|
UINT offs[] = {(UINT)cfg.position.vertexByteOffset, (UINT)cfg.second.vertexByteOffset};
|
|
|
|
// we source all data from the first instanced value in the instanced case, so make sure we
|
|
// offset correctly here.
|
|
if(cfg.position.instanced && cfg.position.instStepRate)
|
|
offs[0] += cfg.position.vertexByteStride * (cfg.curInstance / cfg.position.instStepRate);
|
|
|
|
if(cfg.second.instanced && cfg.second.instStepRate)
|
|
offs[1] += cfg.second.vertexByteStride * (cfg.curInstance / cfg.second.instStepRate);
|
|
|
|
{
|
|
auto it = WrappedID3D11Buffer::m_BufferList.find(cfg.position.vertexResourceId);
|
|
|
|
if(it != WrappedID3D11Buffer::m_BufferList.end())
|
|
vbs[0] = it->second.m_Buffer;
|
|
|
|
it = WrappedID3D11Buffer::m_BufferList.find(cfg.second.vertexResourceId);
|
|
|
|
if(it != WrappedID3D11Buffer::m_BufferList.end())
|
|
vbs[1] = it->second.m_Buffer;
|
|
|
|
it = WrappedID3D11Buffer::m_BufferList.find(cfg.position.indexResourceId);
|
|
|
|
if(it != WrappedID3D11Buffer::m_BufferList.end())
|
|
ibuf = it->second.m_Buffer;
|
|
|
|
if(cfg.position.indexByteStride == 4)
|
|
ifmt = DXGI_FORMAT_R32_UINT;
|
|
}
|
|
|
|
m_pImmediateContext->IASetVertexBuffers(0, 2, vbs, str, offs);
|
|
if(cfg.position.indexByteStride)
|
|
m_pImmediateContext->IASetIndexBuffer(ibuf, ifmt, ioffs);
|
|
else
|
|
m_pImmediateContext->IASetIndexBuffer(NULL, DXGI_FORMAT_UNKNOWN, NULL);
|
|
|
|
// draw solid shaded mode
|
|
if(cfg.visualisationMode != Visualisation::NoSolid &&
|
|
cfg.position.topology < Topology::PatchList_1CPs)
|
|
{
|
|
m_pImmediateContext->RSSetState(m_General.RasterClipState);
|
|
|
|
m_pImmediateContext->IASetPrimitiveTopology(topo);
|
|
|
|
pixelData.MeshDisplayFormat = VisModeToMeshDisplayFormat(cfg);
|
|
|
|
pixelData.MeshColour = Vec3f(0.8f, 0.8f, 0.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &pixelData, sizeof(pixelData));
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &psCBuf);
|
|
|
|
if(cfg.visualisationMode == Visualisation::Lit ||
|
|
cfg.visualisationMode == Visualisation::Explode)
|
|
{
|
|
MeshGeometryCBuffer geomData;
|
|
|
|
geomData.InvProj = projMat.Inverse();
|
|
|
|
ID3D11Buffer *gsBuf = GetDebugManager()->MakeCBuffer(&geomData, sizeof(MeshGeometryCBuffer));
|
|
|
|
m_pImmediateContext->GSSetConstantBuffers(0, 1, &gsBuf);
|
|
|
|
m_pImmediateContext->GSSetShader(m_MeshRender.MeshGS, NULL, 0);
|
|
}
|
|
|
|
if(cfg.position.indexByteStride)
|
|
m_pImmediateContext->DrawIndexed(cfg.position.numIndices, 0, cfg.position.baseVertex);
|
|
else
|
|
m_pImmediateContext->Draw(cfg.position.numIndices, 0);
|
|
|
|
if(cfg.visualisationMode == Visualisation::Lit ||
|
|
cfg.visualisationMode == Visualisation::Explode)
|
|
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
|
|
}
|
|
|
|
// draw wireframe mode
|
|
if(cfg.visualisationMode == Visualisation::NoSolid || cfg.wireframeDraw ||
|
|
cfg.position.topology >= Topology::PatchList_1CPs)
|
|
{
|
|
m_pImmediateContext->RSSetState(m_MeshRender.WireframeRasterState);
|
|
|
|
m_pImmediateContext->OMSetDepthStencilState(m_MeshRender.LessEqualDepthState, 0);
|
|
|
|
pixelData.MeshDisplayFormat = MESHDISPLAY_SOLID;
|
|
pixelData.MeshColour =
|
|
Vec4f(cfg.position.meshColor.x, cfg.position.meshColor.y, cfg.position.meshColor.z, 0.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &pixelData, sizeof(pixelData));
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &psCBuf);
|
|
|
|
if(cfg.position.topology >= Topology::PatchList_1CPs)
|
|
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
|
|
else
|
|
m_pImmediateContext->IASetPrimitiveTopology(topo);
|
|
|
|
if(cfg.position.indexByteStride)
|
|
m_pImmediateContext->DrawIndexed(cfg.position.numIndices, 0, cfg.position.baseVertex);
|
|
else
|
|
m_pImmediateContext->Draw(cfg.position.numIndices, 0);
|
|
}
|
|
}
|
|
|
|
m_pImmediateContext->RSSetState(m_MeshRender.WireframeRasterState);
|
|
|
|
vertexData.homogenousInput = 0U;
|
|
|
|
// set up state for drawing helpers
|
|
{
|
|
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(axisMapMat));
|
|
vertexData.vtxExploderSNorm = 0.0f;
|
|
vertexData.exploderScale = 0.0f;
|
|
GetDebugManager()->FillCBuffer(vsCBuf, &vertexData, sizeof(vertexData));
|
|
|
|
m_pImmediateContext->RSSetState(m_MeshRender.SolidRasterState);
|
|
|
|
m_pImmediateContext->OMSetDepthStencilState(m_MeshRender.NoDepthState, 0);
|
|
|
|
m_pImmediateContext->VSSetConstantBuffers(0, 1, &vsCBuf);
|
|
m_pImmediateContext->VSSetShader(m_MeshRender.MeshVS, NULL, 0);
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &psCBuf);
|
|
m_pImmediateContext->PSSetShader(m_General.FixedColPS, NULL, 0);
|
|
}
|
|
|
|
// axis markers
|
|
if(!cfg.position.unproject)
|
|
{
|
|
m_pImmediateContext->PSSetConstantBuffers(0, 1, &psCBuf);
|
|
|
|
UINT strides[] = {sizeof(Vec4f)};
|
|
UINT offsets[] = {0};
|
|
|
|
m_pImmediateContext->IASetVertexBuffers(0, 1, &m_MeshRender.AxisHelper, strides, offsets);
|
|
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
|
|
m_pImmediateContext->IASetInputLayout(m_MeshRender.GenericLayout);
|
|
|
|
col = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
m_pImmediateContext->Draw(2, 0);
|
|
|
|
col = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
m_pImmediateContext->Draw(2, 2);
|
|
|
|
col = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
m_pImmediateContext->Draw(2, 4);
|
|
}
|
|
|
|
if(cfg.highlightVert != ~0U)
|
|
{
|
|
vertexData.homogenousInput = cfg.position.unproject;
|
|
|
|
m_HighlightCache.CacheHighlightingData(eventId, cfg);
|
|
|
|
D3D11_PRIMITIVE_TOPOLOGY meshtopo = topo;
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// vectors to be set from buffers, depending on topology
|
|
|
|
// this vert (blue dot, required)
|
|
FloatVector activeVertex;
|
|
|
|
// primitive this vert is a part of (red prim, optional)
|
|
rdcarray<FloatVector> activePrim;
|
|
|
|
// for patch lists, to show other verts in patch (green dots, optional)
|
|
// for non-patch lists, we use the activePrim and adjacentPrimVertices
|
|
// to show what other verts are related
|
|
rdcarray<FloatVector> inactiveVertices;
|
|
|
|
// adjacency (line or tri, strips or lists) (green prims, optional)
|
|
// will be N*M long, N adjacent prims of M verts each. M = primSize below
|
|
rdcarray<FloatVector> adjacentPrimVertices;
|
|
|
|
D3D11_PRIMITIVE_TOPOLOGY primTopo = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; // tri or line list
|
|
uint32_t primSize = 3; // number of verts per primitive
|
|
|
|
if(meshtopo == D3D11_PRIMITIVE_TOPOLOGY_LINELIST ||
|
|
meshtopo == D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ ||
|
|
meshtopo == D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP ||
|
|
meshtopo == D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ)
|
|
{
|
|
primSize = 2;
|
|
primTopo = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
|
|
}
|
|
|
|
bool valid = m_HighlightCache.FetchHighlightPositions(cfg, activeVertex, activePrim,
|
|
adjacentPrimVertices, inactiveVertices);
|
|
|
|
if(valid)
|
|
{
|
|
////////////////////////////////////////////////////////////////
|
|
// prepare rendering (for both vertices & primitives)
|
|
|
|
// if data is from post transform, it will be in clipspace
|
|
if(cfg.position.unproject)
|
|
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(guessProjInv));
|
|
else
|
|
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(axisMapMat));
|
|
|
|
m_pImmediateContext->IASetInputLayout(m_MeshRender.GenericLayout);
|
|
|
|
GetDebugManager()->FillCBuffer(vsCBuf, &vertexData, sizeof(vertexData));
|
|
|
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
|
HRESULT hr = S_OK;
|
|
UINT strides[] = {sizeof(Vec4f)};
|
|
UINT offsets[] = {0};
|
|
m_pImmediateContext->IASetVertexBuffers(0, 1, &m_MeshRender.TriHighlightHelper, strides,
|
|
offsets);
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// render primitives
|
|
|
|
m_pImmediateContext->IASetPrimitiveTopology(primTopo);
|
|
|
|
// Draw active primitive (red)
|
|
col = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
|
|
if(activePrim.size() >= primSize)
|
|
{
|
|
hr = m_pImmediateContext->Map(m_MeshRender.TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD,
|
|
0, &mapped);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failde to map m_MeshRender.m_TriHighlightHelper HRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
memcpy(mapped.pData, &activePrim[0], sizeof(Vec4f) * primSize);
|
|
m_pImmediateContext->Unmap(m_MeshRender.TriHighlightHelper, 0);
|
|
|
|
m_pImmediateContext->Draw(primSize, 0);
|
|
}
|
|
|
|
// Draw adjacent primitives (green)
|
|
col = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
|
|
if(adjacentPrimVertices.size() >= primSize && (adjacentPrimVertices.size() % primSize) == 0)
|
|
{
|
|
hr = m_pImmediateContext->Map(m_MeshRender.TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD,
|
|
0, &mapped);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failde to map m_MeshRender.m_TriHighlightHelper HRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
memcpy(mapped.pData, &adjacentPrimVertices[0], sizeof(Vec4f) * adjacentPrimVertices.size());
|
|
m_pImmediateContext->Unmap(m_MeshRender.TriHighlightHelper, 0);
|
|
|
|
m_pImmediateContext->Draw((UINT)adjacentPrimVertices.size(), 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// prepare to render dots (set new VS params and topology)
|
|
float scale = 800.0f / m_OutputHeight;
|
|
float asp = m_OutputWidth / m_OutputHeight;
|
|
|
|
vertexData.SpriteSize = Vec2f(scale / asp, scale);
|
|
GetDebugManager()->FillCBuffer(vsCBuf, &vertexData, sizeof(vertexData));
|
|
|
|
// Draw active vertex (blue)
|
|
col = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
|
|
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
|
|
FloatVector vertSprite[4] = {
|
|
activeVertex,
|
|
activeVertex,
|
|
activeVertex,
|
|
activeVertex,
|
|
};
|
|
|
|
hr = m_pImmediateContext->Map(m_MeshRender.TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD, 0,
|
|
&mapped);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failde to map m_MeshRender.m_TriHighlightHelper HRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
memcpy(mapped.pData, vertSprite, sizeof(vertSprite));
|
|
m_pImmediateContext->Unmap(m_MeshRender.TriHighlightHelper, 0);
|
|
|
|
m_pImmediateContext->Draw(4, 0);
|
|
|
|
// Draw inactive vertices (green)
|
|
col = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
|
|
for(size_t i = 0; i < inactiveVertices.size(); i++)
|
|
{
|
|
vertSprite[0] = vertSprite[1] = vertSprite[2] = vertSprite[3] = inactiveVertices[i];
|
|
|
|
hr = m_pImmediateContext->Map(m_MeshRender.TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD,
|
|
0, &mapped);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RDCERR("Failde to map m_MeshRender.m_TriHighlightHelper HRESULT: %s", ToStr(hr).c_str());
|
|
return;
|
|
}
|
|
|
|
memcpy(mapped.pData, vertSprite, sizeof(vertSprite));
|
|
m_pImmediateContext->Unmap(m_MeshRender.TriHighlightHelper, 0);
|
|
|
|
m_pImmediateContext->Draw(4, 0);
|
|
}
|
|
}
|
|
|
|
if(cfg.position.unproject)
|
|
m_pImmediateContext->VSSetShader(m_MeshRender.MeshVS, NULL, 0);
|
|
}
|
|
|
|
vertexData.homogenousInput = 0U;
|
|
|
|
// bounding box
|
|
if(cfg.showBBox)
|
|
{
|
|
UINT strides[] = {sizeof(Vec4f)};
|
|
UINT offsets[] = {0};
|
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
|
|
|
vertexData.SpriteSize = Vec2f();
|
|
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(axisMapMat));
|
|
GetDebugManager()->FillCBuffer(vsCBuf, &vertexData, sizeof(vertexData));
|
|
|
|
HRESULT hr = m_pImmediateContext->Map(m_MeshRender.TriHighlightHelper, 0,
|
|
D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
|
RDCASSERTEQUAL(hr, S_OK);
|
|
|
|
Vec4f a = Vec4f(cfg.minBounds.x, cfg.minBounds.y, cfg.minBounds.z, cfg.minBounds.w);
|
|
Vec4f b = Vec4f(cfg.maxBounds.x, cfg.maxBounds.y, cfg.maxBounds.z, cfg.maxBounds.w);
|
|
|
|
Vec4f TLN = Vec4f(a.x, b.y, a.z, 1.0f); // TopLeftNear, etc...
|
|
Vec4f TRN = Vec4f(b.x, b.y, a.z, 1.0f);
|
|
Vec4f BLN = Vec4f(a.x, a.y, a.z, 1.0f);
|
|
Vec4f BRN = Vec4f(b.x, a.y, a.z, 1.0f);
|
|
|
|
Vec4f TLF = Vec4f(a.x, b.y, b.z, 1.0f);
|
|
Vec4f TRF = Vec4f(b.x, b.y, b.z, 1.0f);
|
|
Vec4f BLF = Vec4f(a.x, a.y, b.z, 1.0f);
|
|
Vec4f BRF = Vec4f(b.x, a.y, b.z, 1.0f);
|
|
|
|
// 12 frustum lines => 24 verts
|
|
Vec4f bbox[24] = {
|
|
TLN, TRN, TRN, BRN, BRN, BLN, BLN, TLN,
|
|
|
|
TLN, TLF, TRN, TRF, BLN, BLF, BRN, BRF,
|
|
|
|
TLF, TRF, TRF, BRF, BRF, BLF, BLF, TLF,
|
|
};
|
|
|
|
memcpy(mapped.pData, bbox, sizeof(bbox));
|
|
|
|
m_pImmediateContext->Unmap(m_MeshRender.TriHighlightHelper, 0);
|
|
|
|
// we want this to clip
|
|
m_pImmediateContext->OMSetDepthStencilState(m_MeshRender.LessEqualDepthState, 0);
|
|
|
|
m_pImmediateContext->IASetVertexBuffers(0, 1, &m_MeshRender.TriHighlightHelper, strides, offsets);
|
|
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
|
|
m_pImmediateContext->IASetInputLayout(m_MeshRender.GenericLayout);
|
|
|
|
col = Vec4f(0.2f, 0.2f, 1.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
|
|
m_pImmediateContext->Draw(24, 0);
|
|
|
|
m_pImmediateContext->OMSetDepthStencilState(m_MeshRender.NoDepthState, 0);
|
|
}
|
|
|
|
// 'fake' helper frustum
|
|
if(cfg.position.unproject)
|
|
{
|
|
UINT strides[] = {sizeof(Vec4f)};
|
|
UINT offsets[] = {0};
|
|
|
|
vertexData.SpriteSize = Vec2f();
|
|
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(guessProjInv));
|
|
GetDebugManager()->FillCBuffer(vsCBuf, &vertexData, sizeof(vertexData));
|
|
|
|
m_pImmediateContext->IASetVertexBuffers(0, 1, &m_MeshRender.FrustumHelper, strides, offsets);
|
|
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
|
|
m_pImmediateContext->IASetInputLayout(m_MeshRender.GenericLayout);
|
|
|
|
col = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
GetDebugManager()->FillCBuffer(psCBuf, &col, sizeof(col));
|
|
|
|
m_pImmediateContext->Draw(24, 0);
|
|
}
|
|
}
|