D3D11: рендеринг (глубина) текстуры приводит к красному квадрату, нормальный рендеринг работает - PullRequest
1 голос
/ 11 апреля 2019

В настоящее время я работаю над проектом D3D и хочу реализовать направленное отображение теней.Я настроил все в соответствии с Руководством Microsoft , но оно просто не работает.

Я создал двухмерный текстурный объект, вид трафарета глубины, а также вид ресурса шейдера и установил его.используйте следующие описания:

    D3D11_TEXTURE2D_DESC shadowMapDesc;
    ZeroMemory(&shadowMapDesc, sizeof(D3D11_TEXTURE2D_DESC));
    shadowMapDesc.Width = width;
    shadowMapDesc.Height = height;
    shadowMapDesc.MipLevels = 1;
    shadowMapDesc.ArraySize = 1;
    shadowMapDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
    shadowMapDesc.SampleDesc.Count = 1;
    shadowMapDesc.SampleDesc.Quality = 0;
    shadowMapDesc.Usage = D3D11_USAGE_DEFAULT;
    shadowMapDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
    shadowMapDesc.CPUAccessFlags = 0;
    shadowMapDesc.MiscFlags = 0;

    ID3D11Device& d3ddev = dev.getD3DDevice();

    uint32_t *initData = new uint32_t[width * height];
    ZeroMemory(initData, sizeof(uint32_t) * width * height);

    D3D11_SUBRESOURCE_DATA data;
    ZeroMemory(&data, sizeof(D3D11_SUBRESOURCE_DATA));
    data.pSysMem = initData;
    data.SysMemPitch = sizeof(uint32_t) * width;
    data.SysMemSlicePitch = 0;

    HRESULT hr = d3ddev.CreateTexture2D(&shadowMapDesc, &data, &texture_);

    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
    ZeroMemory(&depthStencilViewDesc, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC));
    depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    depthStencilViewDesc.Texture2D.MipSlice = 0;

    hr = d3ddev.CreateDepthStencilView(texture_, &depthStencilViewDesc, &stencilView_);

    D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
    ZeroMemory(&shaderResourceViewDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
    shaderResourceViewDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
    shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    shaderResourceViewDesc.Texture2D.MipLevels = 1;
    shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;

    hr = d3ddev.CreateShaderResourceView(texture_, &shaderResourceViewDesc, &shaderView_);

Между этими шагами выполняется дополнительная проверка ошибок, но все функции create возвращаются успешно.Затем я связываю текстуру, отрисовываю свою сцену и отсоединяю текстуру, используя следующие функции:

void D3DDepthTexture2D::bindAsTarget(D3DDevice& dev)
{
    dev.getDeviceContext().ClearDepthStencilView(stencilView_, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

    // Bind target
    dev.getDeviceContext().OMSetRenderTargets(0, 0, stencilView_);

    // Set viewport
    dev.setViewport(static_cast<float>(width_), static_cast<float>(height_), 0.0f, 0.0f);
}

void D3DDepthTexture2D::unbindAsTarget(D3DDevice& dev, float width, float height)
{
    // Unbind target
    dev.resetRenderTarget();

    // Reset viewport
    dev.setViewport(width, height, 0.0f, 0.0f);
}

Моя процедура рендеринга в глубину текстуры в основном выглядит следующим образом (удаляя все ненужные детали):

camera = buildCameraFromLight(light);
setCameraCBuffer(camera);
bindTexture();
activateShader();
for(Object j : objects) {setTransformationCBuffer(j); renderObject(j);}
deactivateShader();
unbindTexture();

Рендеринг сцены с точки зрения источника света на обычную цель рендеринга (экран) приводит к правильному изображению (как к действительному изображению, так и просто к отображению значений глубины).Я использую простой вершинный шейдер, который просто преобразует вершины, и пиксельный шейдер, который вообще ничего не делает, ИЛИ не возвращает значения глубины (я пробовал оба, ничего не меняет в конечном результате, так как нас не заботит цветовой буфер).

После очистки текстуры и ее рендеринга я рендерил ее на четырехугольник на свой экран, но все, что я получил, это красный квадрат - поэтому значение глубины равно 1,0f, значение, которое я очистил,Текстура для.Я действительно в растерянности, что делать, я перепробовал все, реализовал все возможные решения из онлайн-уроков или изменил все самостоятельно, но ничего не помогает.Вот список всех вещей, которые я уже проверил:

  • Все вызовы FAILED (hr) возвращают false, на консоль не выводится сообщение об ошибке
  • Я проверял, получает ли геометрияправильно преобразовал путем рендеринга геометрии и их значений глубины (z / w) на экран, который работал и выглядел правильно
  • Я протестировал вычисление значений глубины в фрагментном шейдере и рендеринг в обычную цель рендеринга (в основном пытаясьрендеринг моего цветового буфера в текстуру) вместо трафаретной текстуры глубины, но это тоже не сработало, красный квадрат
  • Я протестировал разные форматы и комбинации форматов для карты теней и видов, которые либо вызвали созданиепотерпеть неудачу или ничего не изменить
  • Я проверил, сбрасывал ли какой-либо вызов между установкой и отменой установки моей текстуры в качестве цели рендеринга во время вызова рендеринга, сбрасывал цель трафарета глубины на что-то другое - не случай
  • Я уже отладил свою процедуру рендеринга текстур на экран / quad, и этоks правильно с другими текстурами, так что я на самом деле вижу, как выглядит текстура глубины
  • Я изменил геометрию и перспективу камеры вокруг, чтобы увидеть, делает ли это что-нибудь видимым в текстуре глубины - это не
  • Я столкнулся с подобной проблемой StackOverflow и проверил, имеет ли мой буфер трафарета глубины по умолчанию те же размеры, настройки АА и т. Д., Что и у моей текстуры - и это так (количество 1, качество 0)

Я действительно не знаю, что случилось, я пытался отлаживать это часами.Я надеюсь, что кто-то здесь может дать мне какой-либо совет о том, что я делаю неправильно или что я мог бы попытаться исправить.Я использую C ++ 11 с Direct3D11.

Примечание: я не могу отладить ничего из этого с помощью NSight или каких-либо инструментов Visual Studio, так как они, кажется, сейчас не работают должным образом с моей системой, и яне имею никаких административных прав, чтобы исправить это.Я просто должен разобраться с этим сейчас.Я надеюсь, что приведенной информации и примеров кода достаточно, чтобы дать примерное представление о том, что я мог бы попытаться сделать этой работой.

Заранее спасибо.

1 Ответ

1 голос
/ 15 апреля 2019

Я заставил NSight работать и отлаживал все это. Оказывается, текстура глубины была правильно создана и заполнена данными глубины и трафарета, и я просто забыл, что вся информация о глубине хранится в первом канале - поэтому я проигнорировал данные g и b и использовал 1.0 для a, и это сработало. Использование каналов g и b каким-то образом сделало все это красным (возможно, кто-то захочет добавить к этому и объяснить, почему).

Отладка стала намного проще, когда я мог наблюдать текстуру, присутствующую в шейдере - я должен был использовать инструмент отладки, такой как NSight или RenderDoc, ранее. Спасибо @EgorShkorov за совет.

...