Почему действительная текстура не достигает шейдера? (Direct3D9) - PullRequest
1 голос
/ 28 августа 2011

Привет всем! В настоящее время я пытаюсь создать отложенный рендер для моего графического движка, используя c # и SlimDX. В качестве ресурса я использую это руководство, которое очень полезно, даже если оно предназначено для XNA. Но сейчас я застрял ... У меня есть мой рендерер, настроенный для рисования всех цветов геометрии, нормалей и глубины для разделения рендеринга целевых текстур. Это работает. Я могу нарисовать полученные текстуры в восстановленном буфере в виде спрайтов, и я вижу, что они содержат только то, что они должны. Но когда я пытаюсь передать эти текстуры другому шейдеру, в данном случае для создания карты освещения, происходят странные вещи. Вот как я рисую один кадр:

public bool RenderFrame(FrameInfo fInfo){
    if(!BeginRender()) //checks Device, resizes buffers, calls BeginScene(), etc.
         return false;
    foreach(RenderQueue queue in fInfo.GetRenderQueues()){
        RenderQueue(queue);
    }
    EndRender(); //currently only calls EndScene, used to do more
    ResolveGBuffer();
    DrawDirectionalLight(
        new Vector3(1f, -1f, 0), 
        new Color4(1f,1f,1f,1f), 
        fi.CameraPosition, 
        SlimMath.Matrix.Invert(fi.ViewProjectionMatrix));
}

private void ResolveGBuffer() {
    if(DeviceContext9 == null || DeviceContext9.Device == null)
        return;
    DeviceContext9.Device.SetRenderTarget(0, _backbuffer);
    DeviceContext9.Device.SetRenderTarget(1, null);
    DeviceContext9.Device.SetRenderTarget(2, null);
}

private void DrawDirectionalLight(Vector3 lightDirection, Color4 color, SlimMath.Vector3 cameraPosition, SlimMath.Matrix invertedViewProjection) {
    if(DeviceContext9 == null || DeviceContext9.Device == null)
        return;
        DeviceContext9.Device.BeginScene();
       _directionalLightShader.Shader.SetTexture(
           _directionalLightShader.Parameters["ColorMap"], 
           _colorTexture);
       _directionalLightShader.Shader.SetTexture(
           _directionalLightShader.Parameters["NormalMap"], 
           _normalTexture);
       _directionalLightShader.Shader.SetTexture(
           _directionalLightShader.Parameters["DepthMap"], 
           _depthTexture);
       _directionalLightShader.Shader.SetValue<Vector3>(
           _directionalLightShader.Parameters["lightDirection"], 
           lightDirection);
       _directionalLightShader.Shader.SetValue<Color4>(
           _directionalLightShader.Parameters["Color"], 
           color);
       _directionalLightShader.Shader.SetValue<SlimMath.Vector3>(
           _directionalLightShader.Parameters["cameraPosition"], 
           cameraPosition);
       _directionalLightShader.Shader.SetValue<SlimMath.Matrix>(
           _directionalLightShader.Parameters["InvertViewProjection"], 
           invertedViewProjection);
       _directionalLightShader.Shader.SetValue<Vector2>(
           _directionalLightShader.Parameters["halfPixel"], 
           _halfPixel);

       _directionalLightShader.Shader.Technique = 
           _directionalLightShader.Technique("Technique0");

       _directionalLightShader.Shader.Begin();
       _directionalLightShader.Shader.BeginPass(0);
       RenderQuad(SlimMath.Vector2.One * -1, SlimMath.Vector2.One);
       _directionalLightShader.Shader.EndPass();
       _directionalLightShader.Shader.End();
       DeviceContext9.Device.EndScene();
}

Теперь, когда я заменяю вызов DrawDirectionalLight некоторым кодом для рисования _colorTexture, _normalTexture и _depthTexture на экране, все выглядит нормально, но когда я вместо этого использую функцию DrawDirectionalLight, я вижу дикое мерцание. Из вывода PIX похоже, что мои текстуры не передаются в шейдер правильно:

pix_screenshot

Следуя инструкции, параметры текстуры и сэмплеры определяются следующим образом:

float3 lightDirection;
float3 Color;
float3 cameraPosition;
float4x4 InvertViewProjection;
texture ColorMap;
texture NormalMap;
texture DepthMap;

sampler colorSampler = sampler_state{
Texture  = ColorMap;
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter= LINEAR;
MinFilter= LINEAR;
MipFilter= LINEAR;
};

sampler depthSampler = sampler_state{
Texture  = DepthMap;
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter= POINT;
MinFilter= POINT;
MipFilter= POINT;
};

sampler normalSampler = sampler_state{
Texture  = NormalMap;
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter= POINT;
MinFilter= POINT;
MipFilter= POINT;
};

Теперь мой большой вопрос - ПОЧЕМУ? Для отладки не выводятся сообщения об ошибках.

EDIT:

Рендеринг цели / текстуры создаются следующим образом:

_colorTexture = new Texture(DeviceContext9.Device,
            DeviceContext9.PresentParameters.BackBufferWidth,
            DeviceContext9.PresentParameters.BackBufferHeight,
            1,
            Usage.RenderTarget,
            Format.A8R8G8B8,
            Pool.Default);

        _colorSurface = _colorTexture.GetSurfaceLevel(0);

        _normalTexture = new Texture(DeviceContext9.Device,
            DeviceContext9.PresentParameters.BackBufferWidth,
            DeviceContext9.PresentParameters.BackBufferHeight,
            1,
            Usage.RenderTarget,
            Format.A8R8G8B8,
            Pool.Default);

        _normalSurface = _normalTexture.GetSurfaceLevel(0);

        _depthTexture = new Texture(DeviceContext9.Device,
            DeviceContext9.PresentParameters.BackBufferWidth,
            DeviceContext9.PresentParameters.BackBufferHeight,
            1,
            Usage.RenderTarget,
            Format.A8R8G8B8,
            Pool.Default);

        _depthSurface = _depthTexture.GetSurfaceLevel(0);

РЕДАКТИРОВАТЬ 2:

Проблемы, похоже, кроются в самом directionalLightShader, поскольку пропуск других обычных текстур также не работает.

1 Ответ

0 голосов
/ 30 августа 2011

Ответ на мою проблему так же прост, как проблема была глупой. Странное поведение было вызвано двумя разными ошибками:

  1. Я просто смотрел на неправильные события в PIX. Текстуры, которые мы правильно передали шейдеру, но я не увидел, потому что они были «скрыты» в событии BeginPass (за «+»).
  2. Пиксельный шейдер, который я пытался выполнить, так и не был вызван, потому что вершины полноэкранного квадрата, который я использовал для рендеринга, были нарисованы по часовой стрелке ... мой CullMode также был установлен по часовой стрелке ...

Спасибо всем, кто прочитал этот вопрос!

...