К основному контенту

XNA Первый 2D Шейдер

Кратко, быстро о том как написать шейдер для 2d в XNA.
Меня научили статьи и исходные коды:
http://creators.xna.com/sample/spriteeffects
http://www.facewound.com/tutorials/shader1/

Один из результатов:




Используемое ПО:
Microsoft Visual C# 2008 Express,
XNA 3.1

Исходная картинка:



Создаем новый проект игры для Windows, создаем в контенте файл типа Effect File, я назвал
ShaderEf.fx, пишем:

sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex = tex2D(TextureSampler, texCoord);
    tex.r = tex.r*sin(texCoord.y*100)*2;
 tex.g = tex.g*cos(texCoord.y*200)*2;
 tex.b = tex.b*sin(texCoord.y*300)*2;
    return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}


Код основной программы:
using System;
  using System.Collections.Generic;
  using System.Linq;
  using Microsoft.Xna.Framework;
  using Microsoft.Xna.Framework.Audio;
  using Microsoft.Xna.Framework.Content;
  using Microsoft.Xna.Framework.GamerServices;
  using Microsoft.Xna.Framework.Graphics;
  using Microsoft.Xna.Framework.Input;
  using Microsoft.Xna.Framework.Media;
  using Microsoft.Xna.Framework.Net;
  using Microsoft.Xna.Framework.Storage;
namespace test
  {
  public class Game1 : Microsoft.Xna.Framework.Game
  {
  /// <summary>
  /// Менеджер графических устройств
  /// </summary>
  GraphicsDeviceManager graphics;
  /// <summary>
  /// 
  /// </summary>
  SpriteBatch spriteBatch;
  /// <summary>
  /// Шейдер эфект
  /// </summary>
  Effect spriteEffect;
  /// <summary>
  /// Текстура для отображения
  /// </summary>
  Texture2D tex;
  /// <summary>
  /// Конструктор
  /// </summary>
  public Game1()
  {
  graphics = new GraphicsDeviceManager(this);
  Content.RootDirectory = "Content";
  graphics.PreferredBackBufferWidth = 1280;
  graphics.PreferredBackBufferHeight = 720;
  graphics.PreferMultiSampling = true;
 }
  /// <summary>
  /// Инициализация
  /// </summary>
  protected override void Initialize()
  {
  base.Initialize();
  }
  /// <summary>
  /// Загрузка данных
  /// </summary>
  protected override void LoadContent()
  {
  spriteBatch = new SpriteBatch(GraphicsDevice);
  //Загружаем текстуру
  tex = Content.Load<Texture2D>("menuBack");
  //Загружаем шейдер
  spriteEffect = Content.Load<Effect>("ShaderEf");
  }
  /// <summary>
  /// Выгрузка данных
  /// </summary>
  protected override void UnloadContent()
  {
  }
  /// <summary>
  /// Обновление данных
  /// </summary>
  /// <param name="gameTime">Игрове время</param>
  protected override void Update(GameTime gameTime)
  {
  if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  this.Exit();
 base.Update(gameTime);
  }
  /// <summary>
  /// Отображение данных
  /// </summary>
  /// <param name="gameTime">Игровое время</param>
  protected override void Draw(GameTime gameTime)
  {
  //Очищаем экран
  GraphicsDevice.Clear(Color.Black); 
  //Начинаем рисовать
  spriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
  //Начинаем обрабатывать шейдер
  spriteEffect.Begin();
  //Начинаеться текущая техника, 0-й проход шейдера
  spriteEffect.CurrentTechnique.Passes[0].Begin();
  //Рисуем текстуру
  spriteBatch.Draw(tex, new Vector2(0, 0), Color.White);
  //Заканчиваем рисовать
  spriteBatch.End();
  //Заканчиваем текущую технику, 0-й проход шейдера
  spriteEffect.CurrentTechnique.Passes[0].End();
  //Заканчиваем обрабатываеть шейдер
  spriteEffect.End();
}
}
}
Результат:



Теперь я представляю разные вариации кода шейдера
И результат – картинку:

Осветляем.

sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex = tex2D(TextureSampler, texCoord)*3;
    return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}

Затемняем.
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex = tex2D(TextureSampler, texCoord)*texCoord.y;
    return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}

Меняем цвета.
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex = tex2D(TextureSampler, texCoord);
    tex.r = tex.r*2;
    return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}


Манипулируем координатами: растягиваем
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    texCoord.y=texCoord.y*0.5;
    float4 tex = tex2D(TextureSampler, texCoord);
    return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}


Манипулируем координатами: волна
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    texCoord.y=texCoord.y+(sin(texCoord.x*200)*0.01);
    float4 tex = tex2D(TextureSampler, texCoord);
    return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}

Слолжение семплов
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex = tex2D( TextureSampler, texCoord.xy);
 tex += tex2D( TextureSampler, texCoord.xy+0.001);
 tex += tex2D( TextureSampler, texCoord.xy+0.002);
 tex += tex2D( TextureSampler, texCoord.xy+0.003);
 return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}


Размытие
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex = tex2D( TextureSampler, texCoord.xy);
 tex += tex2D( TextureSampler, texCoord.xy+0.001);
 tex += tex2D( TextureSampler, texCoord.xy+0.002);
 tex += tex2D( TextureSampler, texCoord.xy+0.003);
 return tex/4;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}

Четкость.
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex = tex2D( TextureSampler, texCoord.xy);
 tex -= tex2D( TextureSampler, texCoord.xy+0.0001)*10.0f;
 tex += tex2D( TextureSampler, texCoord.xy+0.0001)*10.0f;
 return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}


Embossed
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex;
    tex.a=1.0f;
    tex.rgb = 0.5f;
    tex = tex2D( TextureSampler, texCoord.xy);
 tex -= tex2D( TextureSampler, texCoord.xy-0.001)*2.0f;
 tex += tex2D( TextureSampler, texCoord.xy+0.001)*2.0f;
 tex.rgb = (tex.r+tex.g+tex.b)/3.0f;
 return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}


Черное и белое
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex;
    tex.a=1.0f;
    tex = tex2D( TextureSampler, texCoord.xy);
 tex.rgb = (tex.r+tex.g+tex.b)/3.0f;
 if (tex.r<0.2 || tex.r>0.8) tex.r = 0.0f; else tex.r = 1.0f;
 if (tex.g<0.2 || tex.g>0.8) tex.g = 0.0f; else tex.g = 1.0f;
 if (tex.b<0.2 || tex.b>0.8) tex.b = 0.0f; else tex.b = 1.0f;
 return tex;

}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}


Негатив.
sampler TextureSampler : register(s0);
float4 PixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 tex;
    tex = 1-tex2D( TextureSampler, texCoord.xy);
  tex.a = 1.0f;
 return tex;
}

technique Desaturate
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShader();
    }
}

Комментарии