Рендеринг линии в RenderTarget2D размером 1x1 не меняет цвет целевого пикселя.

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

Я попытался выполнить рендеринг в текстуру 2000x1, а затем сэмплировал ее на ЦП с помощью RenderTarget2d.GetData‹>() и цикла foreach. Это было ужасно медленно :). Поэтому я обошел свою проблему, и теперь идея состоит в том, чтобы многократно отображать текстуру 1x1. В промежутках между проходами я буду расширять массив параметров в своем шейдере, чтобы включить уже возвращенные числа. Каждый пиксель будет затем запрашивать массив и обрезать себя, если он содержит уже появившееся число.

Проблема сейчас в том, что цвет пикселя никогда не меняется независимо от того, что я визуализирую - он всегда возвращает какие-то случайные числа. Когда я добавил Game.GraphicsDevice.Clear(Color.Transparent); перед вызовом отрисовки, он начал возвращать нули, хотя код шейдера должен возвращать 0.2f (или его эквивалент от 0 до 255). Может ли это быть из-за того, что я визуализирую в нем слишком маленький контент (я рисую линию на экране и пробую цвет сцены вдоль линии), и в какой-то момент он прерывается?

Код С#/XNA:

                            CollisionRT = new RenderTarget2D(Game.GraphicsDevice, 1, 1, false, SurfaceFormat.Color, DepthFormat.None);

...             
                Game.GraphicsDevice.BlendState = BlendState.AlphaBlend;
                Game.GraphicsDevice.SetRenderTarget(CollisionRT);
                Game.GraphicsDevice.Clear(Color.Transparent);
                Game.GraphicsDevice.DepthStencilState = DepthStencilState.None;

                foreach (ModelMesh mesh in PPCBulletInvis.Model.Meshes)
                    // PPCBulletInvis is a line that covers 1/18 of the screen (approx).
                {
                    foreach (Effect effect in mesh.Effects)
                    {
                        //effect.Parameters["Texture"].SetValue(vfTex);
                        effect.Parameters["halfPixel"].SetValue(halfPixel);
                        effect.Parameters["sceneMap"].SetValue(sceneRT);
                        effect.Parameters["World"].SetValue(testVWall.World);
                        effect.Parameters["View"].SetValue(camera.View);
                        effect.Parameters["Projection"].SetValue(camera.Projection);
                    }
                    mesh.Draw();
                }

                Game.GraphicsDevice.SetRenderTarget(null);

                Rectangle sourceRectangle =
                    new Rectangle(0, 0, 1, 1);

                Color[] retrievedColor = new Color[1];
                CollisionRT.GetData<Color>(retrievedColor);

                Console.WriteLine(retrievedColor[0].R); // Returns zeroes.

Код шейдера:

float4x4 World;
float4x4 View;
float4x4 Projection;

texture sceneMap;
sampler sceneSampler = sampler_state
{
    Texture = (sceneMap);
    AddressU = CLAMP;
    AddressV = CLAMP;
    MagFilter = POINT;
    MinFilter = POINT;
    Mipfilter = POINT;
};

float2 halfPixel;

struct VS_INPUT
{
    float4 Position     : POSITION0;
};
struct VS_OUTPUT
{
    float4 Position         : POSITION0;
    float4 ScreenPosition   : TEXCOORD2;
};


VS_OUTPUT VertexShaderFunction(VS_INPUT input)
{
    VS_OUTPUT output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    output.ScreenPosition = output.Position;
    return output;
}

float4 PixelShaderFunction(VS_OUTPUT input) : COLOR0
{
    input.ScreenPosition.xy /= input.ScreenPosition.w;

    float2 screenTexCoord = 0.5f * (float2(input.ScreenPosition.x,-input.ScreenPosition.y) + 1);

    screenTexCoord -=halfPixel;

    return (0.2f,0.2f,0.2f,0.2f);//tex2D(sceneSampler, screenTexCoord);
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_3_0 VertexShaderFunction();
        PixelShader = compile ps_3_0 PixelShaderFunction();
    }
}

person cubrman    schedule 26.07.2013    source источник
comment
Вы можете попытаться отобразить свою линию с помощью XYZRHW для отображения в определенных пикселях. Это должно избежать случая, когда ваша геометрия обрезается. Вы настроили окно просмотра?   -  person Gnietschow    schedule 27.07.2013
comment
Не могли бы вы пояснить, я не совсем понимаю вас в двух моментах: что такое XYZRHW? Что я действительно пытался избежать отсечения, так это писать output.Position = (0,0,0,0); и output.Position = (1,1,1,1); в шейдере VERTEX но это не помогло - пиксель все равно держит 0,0,0,0. Во-вторых, скажите, пожалуйста, что вы подразумеваете под регулировкой окна просмотра?   -  person cubrman    schedule 27.07.2013
comment
Я думаю, что если вы выполняете рендеринг в цели рендеринга с другим измерением в качестве экрана, вам нужно настроить размер в окне просмотра графического устройства: msdn.microsoft.com/en-us/library/. Не могли бы вы попробовать установить output.Position = (0,0,0,1)? XYZRHW — это тип формата вершин для установки положения в пространстве экрана, а не в мировом пространстве, что упрощает рендеринг с выравниванием по экрану.   -  person Gnietschow    schedule 27.07.2013
comment
Вау, я обязательно попробую это!   -  person cubrman    schedule 27.07.2013
comment
Почему-то вообще не работает. Даже когда я устанавливаю окно просмотра на 1 пиксель для всей игры, оно все равно отображается на экране. Область просмотра ColViewport = новая область просмотра(); ColViewport.X = 0; ColViewport.Y = 0; ColViewport.Width = 1; ColViewport.Height = 1; Game.GraphicsDevice.Viewport = ColViewport;   -  person cubrman    schedule 28.07.2013
comment
кстати position = (0,0,0,1) тоже не дало результата   -  person cubrman    schedule 28.07.2013
comment
Я попытался выполнить рендеринг с текстурой большего размера и заметил, что пиксели просто искажаются вместе с остальными пикселями, когда я пытаюсь отрисовать много пикселей в маленькую цель рендеринга. Я предполагаю, что моя настоящая проблема заключается в том, что мне нужно предотвратить скачки пикселей.   -  person cubrman    schedule 28.07.2013