Забавы с пиксельным шейдером. Тиснение, Пульсация. Dream

В этой статье мы рассмотрим еще несколько пиксельных эффектов.

Начнем с эффекта Тиснения — Emboss.

Вот что говорит википедия о Тиснении:

Тисне́ние — это полиграфический процесс, относящийся к послепечатной отделке продукции, производящийся на ручных, полуавтоматических и автоматических прессах для тиснения, основанный на припрессовке горячим или холодным способом металлизированной или пигментной фольги или полимерной пленки с напылением нужного вещества для улучшения привлекательности упаковки, этикетки или рекламно-акцидентной продукции.

float4 PSEmboss( float2 TexCoords : TEXCOORD0 ) : COLOR0
{
float4 Color;

Color.a = 1.0f;
Color.rgb = 0.5f;

Color -= tex2D( ColorSampler, TexCoords.xy-0.001)*2.0f;
Color += tex2D( ColorSampler, TexCoords.xy+0.001)*2.0f;

Color.rgb = (Color.r+Color.g+Color.b)/3.0f;

return Color;
}

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

Следующий наш эффект будет немного сложнее, так как он будет использовать дополнительный параметр, которым нам нужно будет передавать из основной программы. Это будет время. А сам эффект будет создавать «пульсацию» изображения, то есть оно будет постепенно приближаться и удаляться от экрана.

        /// <summary>        
/// This is called when the game should draw itself.        
/// </summary>        
/// <param name="gameTime">Provides a snapshot of timing values.</param>        
protected override void Draw(GameTime gameTime)        
{           
 GraphicsDevice.Clear(Color.Black);        
     // TODO: Add your drawing code here

            effect.Parameters["time"].SetValue((float)gameTime.TotalGameTime.TotalSeconds);
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, nullnullnull, effect); 
           spriteBatch.Draw(background3, new Rectangle(0, 0, 640, 480), Color.White);  
          spriteBatch.End();       
      base.Draw(gameTime);      
  } 
float4 PSPulsing(float2 TexCoord : TEXCOORD0)    :    COLOR
{    
float2 vecSkill1 = float2(1,1);    
TexCoord -= 0.5;    
TexCoord *= 1-(sin(time*vecSkill1.x)*vecSkill1.y+vecSkill1.y)*0.5;    
TexCoord += 0.5;        
float4 Color = tex2D(ColorSampler,TexCoord);     
return Color;}
 
technique Pulsing
{    
pass Pass1    
{        
PixelShader = compile ps_2_0 PSPulsing();    
}
} 

Параметры пульсации задаются через вектор vecSkill1

Еще один интересный шейдер основанный на времени я «позаимствовал» с сайта NVidia.

float4 PSDream( float2 Tex : TEXCOORD0 ) : COLOR0
{    float4 vecSkill1 = float4(1,1,1,1);    
float4 Color;        
Tex.xy -= 0.5;    
Tex.xy *= 1-(sin(time*vecSkill1[2])*vecSkill1[3]+vecSkill1[3])*0.5;    
Tex.xy += 0.5;        
Color = tex2D( ColorSampler, Tex.xy);     
Color += tex2D( ColorSampler, Tex.xy+0.001*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.003*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.005*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.007*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.009*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.011*vecSkill1[0]);     
Color += tex2D( ColorSampler, Tex.xy-0.001*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.003*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.005*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.007*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.009*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.011*vecSkill1[0]);     
Color.rgb = (Color.r+Color.g+Color.b)/3.0f;     
Color /= vecSkill1[1];    
return Color;
}
technique Dream
{    
pass Pass1    
{
        PixelShader = compile ps_2_0 PSDream();    
}
} 

Хотя мне больше нравится, когда в этом шейдере картинка не делается монохромной:

float4 PSDream( float2 Tex : TEXCOORD0 ) : COLOR0
{    
float4 vecSkill1 = float4(1,1,1,1);    
float4 Color;      
  Tex.xy -= 0.5;    
Tex.xy *= 1-(sin(time*vecSkill1[2])*vecSkill1[3]+vecSkill1[3])*0.5;    
Tex.xy += 0.5;        
Color = tex2D( ColorSampler, Tex.xy);     
Color += tex2D( ColorSampler, Tex.xy+0.001*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.003*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.005*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.007*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.009*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy+0.011*vecSkill1[0]);     
Color += tex2D( ColorSampler, Tex.xy-0.001*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.003*vecSkill1[0]);   
 Color += tex2D( ColorSampler, Tex.xy-0.005*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.007*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.009*vecSkill1[0]);    
Color += tex2D( ColorSampler, Tex.xy-0.011*vecSkill1[0]);     
//Color.rgb = (Color.r+Color.g+Color.b)/3.0f;     
Color /= vecSkill1[1];    
return Color;}
 
technique Dream
{    
pass Pass1    
{        
PixelShader = compile ps_2_0 PSDream();    
}
} 

Исходный код:

Game1.cs

 
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;
 
namespace PixelShaderFun
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
 
        Texture2D background;
        Texture2D background2;
        Texture2D background3;
        Effect effect;
 
        int currentTehnique;
        KeyboardState oldKs;
 
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
 
            graphics.PreferredBackBufferWidth = 640;
            graphics.PreferredBackBufferHeight = 480;
        }
 
        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
 
            base.Initialize();
        }
 
        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
 
            // TODO: use this.Content to load your game content here
            background = Content.Load<Texture2D>("tulips");
            background2 = Content.Load<Texture2D>("koala");
            background3 = Content.Load<Texture2D>("flowers");
 
            effect = Content.Load<Effect>("pixelEffect");
        }
 
        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }
 
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
 
            // TODO: Add your update logic here
            KeyboardState ks = Keyboard.GetState();
            if (ks.IsKeyDown(Keys.Space) && oldKs.IsKeyUp(Keys.Space))
            {
                currentTehnique = (currentTehnique + 1) % effect.Techniques.Count;
                effect.CurrentTechnique = effect.Techniques[currentTehnique];
            }
 
            if (ks.IsKeyDown(Keys.Back) && oldKs.IsKeyUp(Keys.Back))
            {
                currentTehnique = (currentTehnique - 1);
                if (currentTehnique < 0) currentTehnique = effect.Techniques.Count - 1;
                effect.CurrentTechnique = effect.Techniques[currentTehnique];
            }
 
            oldKs = ks;
            Window.Title = effect.CurrentTechnique.Name;
            base.Update(gameTime);
        }
 
        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
 
            // TODO: Add your drawing code here

            effect.Parameters["time"].SetValue((float)gameTime.TotalGameTime.TotalSeconds);
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, effect);
            spriteBatch.Draw(background3, new Rectangle(0, 0, 640, 480), Color.White);
            spriteBatch.End();
 
            base.Draw(gameTime);
        }
    }
}

pixelEffect.fx

sampler  ColorSampler  : register(s0); 
float time; 
float4 donothing(float2 TexCoords : TEXCOORD0) : COLOR0
{
    return tex2D(ColorSampler, TexCoords);
} 
 
float4 PSRed(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float4 color1 = tex2D(ColorSampler, TexCoords);
     color1.g = 0;
    color1.b = 0;     
return color1;
} 
float4 PSGreen(float2 TexCoords : TEXCOORD0) : COLOR0
{    
float4 color1 = tex2D(ColorSampler, TexCoords); 
    color1.r = 0;
color1.b = 0;     
return color1;
} 
float4 PSBlue(float2 TexCoords : TEXCOORD0) : COLOR0
{    
float4 color1 = tex2D(ColorSampler, TexCoords);     
color1.g = 0;
    color1.r = 0;
     return color1;
} 
technique DoNothing
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 donothing();
    }
} 
technique Red
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSRed();
    }
}
technique Green
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSGreen();
    }
}
technique Blue
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSBlue();
    }
} 
float4 PSNoRed(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float4 color1 = tex2D(ColorSampler, TexCoords);
     color1.r = 0;
     return color1;
} 
float4 PSNoGreen(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float4 color1 = tex2D(ColorSampler, TexCoords);
     color1.g = 0;
     return color1;
}
 
 float4 PSNoBlue(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float4 color1 = tex2D(ColorSampler, TexCoords);
     color1.b = 0;
     return color1;
} 
technique NoRed
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSNoRed();
    }
}
technique NoGreen
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSNoGreen();
    }
}
technique NoBlue
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSNoBlue();
    }
}
 float4 PSCyan(float2 TexCoords : TEXCOORD0) : COLOR0

   float4 color1 = tex2D(ColorSampler, TexCoords);
     float computedC = 0;
    float computedM = 0;
    float computedY = 0;
    float computedK = 0;
      if (color1.r==0 && color1.g==0 && color1.b==0) 
{        
computedK = 1;        
return float4(0,0,0,1);     
}     
computedC = 1 - (color1.r);
    computedM = 1 - (color1.g);
    computedY = 1 - (color1.b);
      float minCMY = min(computedC,              min(computedM,computedY));
 computedC = (computedC - minCMY) / (1 - minCMY) ;
 computedM = (computedM - minCMY) / (1 - minCMY) ;
 computedY = (computedY - minCMY) / (1 - minCMY) ;
 computedK = minCMY;
     color1.r = 0;
    color1.g = computedC-computedK;
    color1.b = computedC-computedK;
     return color1;
} 
float4 PSMagenta(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float4 color1 = tex2D(ColorSampler, TexCoords);
     float computedC = 0;
    float computedM = 0;
    float computedY = 0;
    float computedK = 0;
      if (color1.r==0 && color1.g==0 && color1.b==0) 
{
        computedK = 1;
        return float4(0,0,0,1);
     }
     computedC = 1 - (color1.r);
    computedM = 1 - (color1.g);
    computedY = 1 - (color1.b);
              float minCMY = min(computedC,
              min(computedM,computedY));
 computedC = (computedC - minCMY) / (1 - minCMY) ;
 computedM = (computedM - minCMY) / (1 - minCMY) ;
 computedY = (computedY - minCMY) / (1 - minCMY) ;
 computedK = minCMY;
     color1.r = computedM-computedK;
    color1.g = 0;
    color1.b = computedM-computedK;
     return color1;
}
 float4 PSYellow(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float4 color1 = tex2D(ColorSampler, TexCoords);
     float computedC = 0;
    float computedM = 0;
    float computedY = 0;
    float computedK = 0;
      if (color1.r==0 && color1.g==0 && color1.b==0) 
{
        computedK = 1;
        return float4(0,0,0,1);
     }
     computedC = 1 - (color1.r);
    computedM = 1 - (color1.g);
    computedY = 1 - (color1.b);
          float minCMY = min(computedC,
              min(computedM,computedY));
 computedC = (computedC - minCMY) / (1 - minCMY) ;
 computedM = (computedM - minCMY) / (1 - minCMY) ;
 computedY = (computedY - minCMY) / (1 - minCMY) ;
 computedK = minCMY;
     color1.r = computedY - computedK;
    color1.g = computedY - computedK;
    color1.b = 0;
     return color1;
}
 float4 PSBlack(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float4 color1 = tex2D(ColorSampler, TexCoords);
     float computedC = 0;
    float computedM = 0;
    float computedY = 0;
    float computedK = 0;
      if (color1.r==0 && color1.g==0 && color1.b==0) {
        computedK = 1;
        return float4(0,0,0,1);
     }
     computedC = 1 - (color1.r);
    computedM = 1 - (color1.g);
    computedY = 1 - (color1.b);
          float minCMY = min(computedC,
              min(computedM,computedY));
 computedC = (computedC - minCMY) / (1 - minCMY) ;
 computedM = (computedM - minCMY) / (1 - minCMY) ;
 computedY = (computedY - minCMY) / (1 - minCMY) ;
 computedK = minCMY;
     color1.r = 1 - computedK;
    color1.g = 1 - computedK;
    color1.b = 1 - computedK;
     return color1;
} 
technique Cyan
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSCyan();
    }
} t
echnique Magenta
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSMagenta();
    }
} 
technique Yellow
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSYellow();
    }
}
 technique Black
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSBlack();
    }
}
 float4 PSInverse(float2 TexCoords : TEXCOORD0) : COLOR0

   float4 color1 = tex2D(ColorSampler, TexCoords);
     color1.r = 1 - color1.r;
    color1.g = 1 - color1.g;
    color1.b = 1 - color1.b;
     return color1;
}
 float4 PSBlocks(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float kx = 50;
    float ky = 50;
    TexCoords.x = round(TexCoords.x * kx) / kx;
    TexCoords.y = round(TexCoords.y * ky) / ky;
    float4 color1 = tex2D(ColorSampler, TexCoords);
     return color1;
}
 technique Inverse
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSInverse();
    }
} 
technique Blocks
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSBlocks();
    }
} 
float4 PSBlackAndWhite(float2 TexCoords : TEXCOORD0) : COLOR0

   float4 color1 = tex2D(ColorSampler, TexCoords);
     float c = (color1.r + color1.g + color1.b) / 3.0f;
     if (c < 0.5)
        c = 0.0f;
    else
        c = 1.0f;
     color1.r = c;
    color1.g = c;
    color1.b = c;
     return color1;
}
 
technique BlackAndWhite
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSBlackAndWhite();
    }
}
 float4 PSMonochrome(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float4 color1 = tex2D(ColorSampler, TexCoords);
     float c = (color1.r + color1.g + color1.b) / 3.0f;
     color1.r = c;
    color1.g = c;
    color1.b = c;
     return color1;
}
technique Monochrome
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSMonochrome();
    }
} 
float4 PSIntensity(float2 TexCoords : TEXCOORD0) : COLOR0
{
    float3 luminance = float3(0.299, 0.587, 0.114);
    float4 color1 = tex2D(ColorSampler, TexCoords);
    float intensity = dot(color1, luminance); 
    color1.r = intensity;
    color1.g = intensity;
    color1.b = intensity;
        return color1;
} 
technique Intensity
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSIntensity();
    }
}
 float4 PSEmboss( float2 TexCoords : TEXCOORD0 ) : COLOR0
{
    float4 Color;
        Color.a = 1.0f;
    Color.rgb = 0.5f;
        Color -= tex2D( ColorSampler, TexCoords.xy-0.001)*2.0f;
    Color += tex2D( ColorSampler, TexCoords.xy+0.001)*2.0f;
        Color.rgb = (Color.r+Color.g+Color.b)/3.0f;
     return Color;
}
 technique Emboss
{
    pass Pass1
    { 
       PixelShader = compile ps_2_0 PSEmboss();
    }
}
 
 float4 PSPulsing(float2 TexCoord : TEXCOORD0)    :    COLOR
{
    float2 vecSkill1 = float2(1,1);
    TexCoord -= 0.5;
    TexCoord *= 1-(sin(time*vecSkill1.x)*vecSkill1.y+vecSkill1.y)*0.5;
    TexCoord += 0.5;
        float4 Color = tex2D(ColorSampler,TexCoord);
     return Color;
}
 technique Pulsing
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSPulsing();
    }
} 
float4 PSDream( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float4 vecSkill1 = float4(1,1,1,1);
    float4 Color;
        Tex.xy -= 0.5;
    Tex.xy *= 1-(sin(time*vecSkill1[2])*vecSkill1[3]+vecSkill1[3])*0.5;
    Tex.xy += 0.5;
        Color = tex2D( ColorSampler, Tex.xy);
     Color += tex2D( ColorSampler, Tex.xy+0.001*vecSkill1[0]);
    Color += tex2D( ColorSampler, Tex.xy+0.003*vecSkill1[0]);
    Color += tex2D( ColorSampler, Tex.xy+0.005*vecSkill1[0]);
    Color += tex2D( ColorSampler, Tex.xy+0.007*vecSkill1[0]);
    Color += tex2D( ColorSampler, Tex.xy+0.009*vecSkill1[0]);
    Color += tex2D( ColorSampler, Tex.xy+0.011*vecSkill1[0]);
     Color += tex2D( ColorSampler, Tex.xy-0.001*vecSkill1[0]); 
   Color += tex2D( ColorSampler, Tex.xy-0.003*vecSkill1[0]); 
   Color += tex2D( ColorSampler, Tex.xy-0.005*vecSkill1[0]); 
   Color += tex2D( ColorSampler, Tex.xy-0.007*vecSkill1[0]); 
   Color += tex2D( ColorSampler, Tex.xy-0.009*vecSkill1[0]);
    Color += tex2D( ColorSampler, Tex.xy-0.011*vecSkill1[0]);
     //Color.rgb = (Color.r+Color.g+Color.b)/3.0f; 
    Color /= vecSkill1[1];
    return Color;
}
technique Dream
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PSDream();
    }
} 
Реклама
Запись опубликована в рубрике Компьютерная графика с метками . Добавьте в закладки постоянную ссылку.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s