Как передать объект Texture2D в Pixel Shader в XNA 4.0?

Я хочу захватить каждый кадр и изменить положение каждого пикселя в соответствии с таблицей поиска. Так, например, pixel (30,35) -> (40,50) и так далее.

Итак, я сделал захват кадра с помощью RenderTarget2D, прошел каждый пиксель и установил новую позицию каждого пикселя в новом растровом массиве. Но это снизило производительность из-за эффекта метода RenderTarget2D.GetColor.

Поэтому я подумал, что Pixel Shader может быть решением: в методе Draw: 1. вывести простой кадр 2. захватить его с помощью RenderTarget2D 3. и затем нарисовать модель с помощью шейдера

Но внутри шейдера мне нужно получить доступ к только что захваченному Texture2D, а также к таблице поиска, чтобы прочитать положение отображенного пикселя. Как я могу передать эти переменные в шейдер?

Редактировать: это код в методе Draw(), но я не могу понять, почему к модели не применяются никакие изменения

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Textures[0] = ShaderRenderTarget;
        GraphicsDevice.Textures[1] = LookupTexture;

        // Change to our offscreen render target. 
        GraphicsDevice.SetRenderTarget(ShaderRenderTarget); 
        // Render a simple scene.
        DrawAFrame(); 

        // Change back to the back buffer, and get our scene
        // as a texture. 
        GraphicsDevice.SetRenderTarget(null);

        waldramEffect.CurrentTechnique = waldramEffect.Techniques["Waldraam"];
        // Use Immediate mode and our effect to draw the scene
        // again, using our pixel shader. 
        GraphicsDevice.Clear(Color.CornflowerBlue);
        CreateViewMatrix();

        // Copy any parent transforms.
        Matrix[] transforms = new Matrix[myModel.Bones.Count];
        myModel.CopyAbsoluteBoneTransformsTo(transforms);

        // Draw the model. A model can have multiple meshes, so loop.
        foreach (ModelMesh mesh in myModel.Meshes)
        {
            // This is where the mesh orientation is set, as well 
            // as our camera and projection. 
            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                part.Effect = waldramEffect;
                waldramEffect.Parameters["World"].SetValue(Matrix.CreateRotationY(modelRotation) * Matrix.CreateTranslation(modelPosition));
                waldramEffect.Parameters["View"].SetValue(lookAt);
                waldramEffect.Parameters["Projection"].SetValue(projection); 
            }
            // Draw the mesh, using the effects set above.
            mesh.Draw();
        } 
        base.Draw(gameTime);

        int i = 0;
        foreach (ModelMesh mesh in myModel.Meshes)
        {
            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                part.Effect = basicEffects[i];
                i++;
            }
        }
    }

1 ответ

Решение

Превратите вашу таблицу поиска в текстуру, сохраняя смещения X и Y в двух каналах текстуры (например, красный и зеленый).

Установите обе текстуры (цель визуализации в XNA - это текстура) на графическом устройстве следующим образом:

GraphicsDevice.Textures[0] = myRenderTarget;
GraphicsDevice.Textures[1] = myLookupTable;

(Обратите внимание, что SpriteBatch установит Texture[0] внутренне, если вы используете это.)

В вашем шейдере объявите сэмплер для каждого:

sampler myRenderTarget: register(s0);
sampler myLookupTable: register(s1);

Затем модулируйте выбранную позицию в вашей цели рендеринга путем выборки из таблицы поиска:

tex2D(myRenderTarget, inTexCoord.xy + tex2D(myLookupTable, inTexCoord.xy).xy);

Обратите внимание, что я не проверял вышеуказанный код HLSL. И вам нужно будет предоставить дополнительную математику, если вы хотите, чтобы ваши смещения работали в пиксельных координатах и ​​учитывали отрицательные смещения.

Другие вопросы по тегам