Как передать объект 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. И вам нужно будет предоставить дополнительную математику, если вы хотите, чтобы ваши смещения работали в пиксельных координатах и учитывали отрицательные смещения.