0

What I am trying to achieve is the following: my pass will return a huge array with several unique numbers repeating over and over, which I need to retrieve and process on CPU.

I tried rendering into a 2000x1 texture and then sampled it on the CPU with RenderTarget2d.GetData<>() and a foreach loop. It was awfully slow :). So I sidestepped my problem, the idea now is to render to a 1x1 texture multiple times. Inbetween passes I will extend a parameter array in my shader to include the numbers already returned.Each pixel will than query the array and clip itself if it holds a number that already appeared.

The problem now is that pixel color never changes nomatter what I render - it always returns some random numbers. When I added Game.GraphicsDevice.Clear(Color.Transparent); before the draw call it started returning zeroes, though the shader code should return 0.2f (or its 0 to 255 equivalent). Can it be because I render too small a content into it (I am drawing a line on the screen and sample the scene's color along the line) and it gets lerped at some point?

C#/XNA code:

                            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.

Shader code:

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();
    }
}
cubrman
  • 782
  • 6
  • 20
  • You could try to render your line with XYZRHW to render to specific pixels. This should avoid the case that your geometry is clipped. Did you adjusted your viewport? – Gnietschow Jul 27 '13 at 08:51
  • Could you please expand upon that, I can't clearly understand you at two points: what is XYZRHW? What I did try to avoid clipping was to write output.Position = (0,0,0,0); and output.Position = (1,1,1,1); in the VERTEX shader but it did not help - the pixel still holds 0,0,0,0. Secondly please tell me what you mean by "adjusting the viewport"? – cubrman Jul 27 '13 at 09:12
  • I think if you're rendering to a rendertarget with another dimension as the screen you have to adjust the size in the viewport of the graphicsdevice: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport%28v=xnagamestudio.35%29.aspx. Could you try to set output.Position = (0,0,0,1)? XYZRHW is a type of vertexformat to set the position in screenspace not in worldspace, easier for screen-aligned rendering. – Gnietschow Jul 27 '13 at 09:28
  • Wow, I'll be sure to try this! – cubrman Jul 27 '13 at 09:29
  • Somewhy it does not work at all. Even when I set my viewport as 1 pixel for the entire game - it still renders to the screen. Viewport ColViewport = new Viewport(); ColViewport.X = 0; ColViewport.Y = 0; ColViewport.Width = 1; ColViewport.Height = 1; Game.GraphicsDevice.Viewport = ColViewport; – cubrman Jul 28 '13 at 06:42
  • btw position = (0,0,0,1) also produced no result – cubrman Jul 28 '13 at 06:57
  • I tried rendering to a bigger texture and noticed that pixels simply get distorted (lerped) with the rest of the pixels when I try to draw many pixels into a small rendertarget. I guess my real problem is the fact that I need to prevent lerping of the pixels. – cubrman Jul 28 '13 at 10:07

0 Answers0