【问题标题】:DirectX 11 frontface directionDirectX 11 正面方向
【发布时间】:2013-07-07 02:44:07
【问题描述】:

创建光栅器时,我将光栅器描述设置为:

rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D11_CULL_BACK;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = true;
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.FrontCounterClockwise = true;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f;

这很好用。但是当我将FrontCounterClockwise 更改为false 时。什么都没有渲染(我猜一切都被剔除)。我是否误解了FrontCounterClockwise 的目的?因为我期待,它将顺时针的面作为正面,而不是逆时针的面。我做错了什么?

编辑:这是完整的初始化代码:

bool irrFireDX11::INITIALIZE(int screenWidth, int screenHeight, bool vsync)
{
HRESULT result;
IDXGIFactory* factory;
IDXGIAdapter* adapter;
IDXGIOutput* adapterOutput;
unsigned int numModes, i, numerator, denominator, stringLength;
DXGI_MODE_DESC* displayModeList;
DXGI_ADAPTER_DESC adapterDesc;
int error;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ID3D11Texture2D* backBufferPtr;
D3D11_TEXTURE2D_DESC depthBufferDesc;
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
D3D11_RASTERIZER_DESC rasterDesc;
D3D11_VIEWPORT viewport;
float fieldOfView, screenAspect;
m_vsync_enabled = vsync;
D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc;

// Create a DirectX graphics interface factory.
result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
if(FAILED(result)) return false;

// Use the factory to create an adapter for the primary graphics interface (video card).
result = factory->EnumAdapters(0, &adapter);
if(FAILED(result)) return false;

// Enumerate the primary adapter output (monitor).
result = adapter->EnumOutputs(0, &adapterOutput);
if(FAILED(result)) return false;

// Get the number of modes that fit the DXGI_FORMAT_R8G8B8A8_UNORM display format for the adapter output (monitor).
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
if(FAILED(result)) return false;

// Create a list to hold all the possible display modes for this monitor/video card combination.
displayModeList = new DXGI_MODE_DESC[numModes];
if(!displayModeList) return false;

// Now fill the display mode list structures.
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);
if(FAILED(result)) return false;

// Now go through all the display modes and find the one that matches the screen width and height.
// When a match is found store the numerator and denominator of the refresh rate for that monitor.
for(i=0; i<numModes; i++)
{
    if(displayModeList[i].Width == (unsigned int)screenWidth)
    {
        if(displayModeList[i].Height == (unsigned int)screenHeight)
        {
            numerator = displayModeList[i].RefreshRate.Numerator;
            denominator = displayModeList[i].RefreshRate.Denominator;
        }
    }
}

// Get the adapter (video card) description.
result = adapter->GetDesc(&adapterDesc);
if(FAILED(result)) return false;
m_videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024);
error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);
if(error != 0) return false;

delete [] displayModeList;
displayModeList = 0;
adapterOutput->Release();
adapterOutput = 0;
adapter->Release();
adapter = 0;
factory->Release();
factory = 0;

// Initialize the swap chain description.
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = screenWidth;
swapChainDesc.BufferDesc.Height = screenHeight;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

if(m_vsync_enabled)
{
    swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
    swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;
}else{
    swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
    swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
}

swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = ifDEVICE->getWindowHandle();
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = !ifDEVICE->getFullScreen();
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Flags = 0;

D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
D3D_FEATURE_LEVEL featureLevel[] =
{
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
};
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG, featureLevel, 3,
    D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, &g_featureLevel, &m_deviceContext);
if(FAILED(result)) return false;

result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
if(FAILED(result)) return false;

result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);
if(FAILED(result)) return false;

backBufferPtr->Release();
backBufferPtr = 0;

ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
depthBufferDesc.Width = screenWidth;
depthBufferDesc.Height = screenHeight;
depthBufferDesc.MipLevels = 1;
depthBufferDesc.ArraySize = 1;
depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDesc.SampleDesc.Count = 1;
depthBufferDesc.SampleDesc.Quality = 0;
depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDesc.CPUAccessFlags = 0;
depthBufferDesc.MiscFlags = 0;

result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
if(FAILED(result)) return false;

ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilDesc.StencilEnable = true;
depthStencilDesc.StencilReadMask = 0xFF;
depthStencilDesc.StencilWriteMask = 0xFF;
depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
if(FAILED(result)) return false;
m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1);

ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
    result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
    if(FAILED(result)) return false;
    m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);
rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D11_CULL_BACK;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = true;
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.FrontCounterClockwise = true;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f;

result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState);
if(FAILED(result)) return false;
m_deviceContext->RSSetState(m_rasterState);

viewport.Width = (float)screenWidth;
viewport.Height = (float)screenHeight;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
m_deviceContext->RSSetViewports(1, &viewport);

fieldOfView = (float)D3DX_PI / 4.0f;
screenAspect = (float)screenWidth / (float)screenHeight;

D3DXMatrixPerspectiveFovLH(&m_projectionMatrix, fieldOfView, screenAspect, nearValue, farValue);
D3DXMatrixIdentity(&m_worldMatrix);
D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, nearValue, farValue);

// Clear the second depth stencil state before setting the parameters.
ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc));

depthDisabledStencilDesc.DepthEnable = false;
depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthDisabledStencilDesc.StencilEnable = true;
depthDisabledStencilDesc.StencilReadMask = 0xFF;
depthDisabledStencilDesc.StencilWriteMask = 0xFF;
depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

result = m_device->CreateDepthStencilState(&depthDisabledStencilDesc, &m_depthDisabledStencilState);
if(FAILED(result)) return false;

return true;
}

【问题讨论】:

  • FrontCounterClockwise = false 将顺时针的面作为正面,所以所有的东西都会被剔除(如果你的几何布局是逆时针的)。你到底期望什么?
  • 好吧,如果我有一个用FrontCounterClockwise = true 顺时针建模的立方体(就是这种情况),只渲染背面。 (所以我可以通过立方体看到立方体的背面)。所以我希望在将它转到false 时看到立方体的正面。但相反,我什么也没看到。
  • 您的着色器/directx 设置代码可能有问题,所以最好在这里发布
  • 我编辑了完整的 dx 初始化代码。希望对您有所帮助。
  • 缺少填充顶点和索引缓冲区的部分。你能验证所有面的缠绕顺序吗?

标签: c++ directx directx-11 culling


【解决方案1】:

首先要澄清的是Direct3D中的背面不是你身后的脸,这里的“背面”这个词并不是正常单词中的方向,而是顶点顺序,除了正面之外的所有面都被处理作为背面。

关于您的问题,您说下面的代码可以正常工作。

rasterDesc.CullMode = D3D11_CULL_BACK;
rasterDesc.FrontCounterClockwise = true;

这里的“很好”是什么意思?每张脸都很好,还是其中一些很好?如果每张脸都很好,那就意味着

  1. 你告诉 D3D 剔除背面
  2. 您为每个面按逆时针方向定义顶点

所以你看到每个面都渲染得很好,因为它们被你的设置视为正面,然后你将 FrontCounterClockwise 更改为 false,如下所示。

rasterDesc.FrontCounterClockwise = false

这意味着,你告诉 d3d 逆时针定义的面是背面,所以 D3D 剔除所有面,因此没有渲染任何内容。

注意: 在 Direct3D 10/11 中,正面不仅由顶点顺序确定,还取决于 FrontCounterClockwise 的值。 ,这与仅由顶点顺序确定的 Direct3D 9 不同。

如果在 Direct3D 10/11 中

FrontCounterClockwise = true

  1. 如果面的顶点顺序为 逆时针
  2. 如果是顶点,则将面视为背面 顺序是顺时针

FrontCounterClockwise = fase

  1. 如果顶点顺序为顺时针,则将面视为正面
  2. 如果顶点顺序为逆时针方向,则将面视为背面

“FrontCounterClockwise”这个名字可能会让人感到困惑,我们可以将这些词分开如下

  • FrontCounterClockwise = true,表示正面为逆时针顶点 是真的。
  • FrontCounterClockwise = false,表示正面作为顶点 逆时针是假的,换句话说,正面作为顶点 顺时针为真。

【讨论】:

  • 谢谢你非常详细的回答,但你只是告诉我,我已经知道了。更清楚地说:我正在渲染一个球体。我所说的“很好”是指我可以从外面看到球体,但我不能从里面看到它。 (因为从内部看,所有的面都是背面,因为它们是朝外的,而不是向内的......)现在:如果我将 FrontCounterClockwise 更改为 false 我希望不要从外面看到球体,而是在里面,因为这些面现在应该面向内。但相反,从任何角度来看,我什么都看不到。还是我误会了?
  • 如果你按照你说的去做,相信你会看到预期的结果,但我不确定你是否做对了,因为有很多方面可能会影响到这一点,比如照明和查看参数,我用 DXUT sphere 做了一个测试,一切正常。
  • 在我的情况下,照明和类似的东西不应该影响这一点,因为当我设置CullMode = D3D11_CULL_NONE; 时,我可以从各个方向看到每一张脸。还有其他设置我可能设置错了吗?
  • 我不确定,我建议您使用 DXUT sphere 进行测试,这非常简单,不会花费您太多时间。您可以从 SDK_install_dir/Samples/C++/DXUT 获取 DXUT 源代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多