10 . 2. hlsl effects ii
DESCRIPTION
10 . 2. HLSL Effects II. More advanced forms of effect. HLSL Effects : Refractoion. Refraction HLSL effect. Refraction. A refraction effect is the change in direction of a wave (e.g. light/sound) due to a change in speed (typically when moving from one medium to another). - PowerPoint PPT PresentationTRANSCRIPT
10.2. HLSL EFFECTS IIMore advanced forms of effect
HLSL EFFECTS : REFRACTOIONRefraction HLSL effect
A refraction effect is the change in direction of a wave (e.g. light/sound) due to a change in speed (typically when moving from one medium to another).
The effect can be described using Snell's law which states that the angle of incidence (θ1) is related to the angle of refraction (θ2) based on the refractive index of each medium (n1, n2) as follows:
Refraction
This particular implement will use three (full-screen) render targets:• Refraction target –
containing the source scene on which the refraction effect will be applied.
• Diffuse target – source texture (e.g. stained glass windows) that will be alpha combined within the refraction effect.
• Normal target – in order to simulate refraction we need to know the surface normal (held in this render target)
Refraction
Refraction (definitions)GraphicsDeviceManager graphics;
Texture2D scene;
Texture2D refractionNormal;Texture2D refractionDiffuse;
float refractionOpacity = .2f;
float normalMapHeight = .05f;
RenderTarget2D sceneTarget;RenderTarget2D refractionNormalTarget; RenderTarget2D refractionDiffuseTarget;
sceneTarget = new RenderTarget2D(graphics.GraphicsDevice,graphics.GraphicsDevice.Viewport.Width,graphics.GraphicsDevice.Viewport.Height,1, SurfaceFormat.Color );
refractionNormalTarget = // same as aboverefractionDiffuseTarget = // same as above
Three render targets are defined to hold the rendered scene and any refraction normal+diffuse textures
In this example, a ‘mock’ scene is held within a texture as the refraction background
The fraction surface normals are defined alongside a diffuse image (e.g. stained glass windows) that will be alpha combined with the background scene).
This specifies the alpha value to be used to combine the diffuse texture within the effect
Height of each normal, controlling the strength of the refraction effect
Each render target is constructed to be the same size as the screen. This is convenient, however it is inefficient if the refracted textures only covers a small bit of the screen.
Refraction (draw)protected override void Draw(GameTime gameTime){
RenderScene ();RenderRefractionDiffuseMap();RenderRefractionNormalMap();
refractionEffect.Parameters[“refractionDiffuse"].SetValue(refractionDiffuseTarget.GetTexture());
refractionEffect.Parameters[“refractionNormal"].
SetValue(refractionNormalTarget.GetTexture());
refractionEffect.Parameters[" refractionOpacity "].SetValue(refractionOpacity);
refractionEffect.Parameters["normalMapHeight"].SetValue(normalMapHeight);
Draw the base scene into the reflection map
Define the regions that will be refracted alongside refaction normals and diffuse textures
batch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
refractionEffect.Begin();refractionEffect.CurrentTechnique.Passes[0].Begin();
batch.Draw( sceneTarget.GetTexture(),new Rectangle( 0, 0,graphics.GraphicsDevice.PresentationParameters.BackBufferWidth,graphics.GraphicsDevice.PresentationParameters.BackBufferHeight),Color.White);
refractionEffect.CurrentTechnique.Passes[0].End();refractionEffect.End();batch.End();
base.Draw(gameTime);}
Pass the relevant parameters into the effect in preparation for drawing
Draw the generated scene texture to the screen, passing the texture through the refraction effect
The RenderScene , RenderRefractionDiffuseMap, and RenderRefractionNormalMap methods all have the same structure and simply draw the relevant texture to the corresponding full-screen render target.
Refraction (draw)private void RenderScene (){
graphics.GraphicsDevice.SetRenderTarget(0, sceneTarget);
graphics.GraphicsDevice.Clear(Color.TransparentBlack);
batch.Begin();batch.Draw( scene,
new Rectangle( 0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height),
Color.White);batch.End();
graphics.GraphicsDevice.SetRenderTarget(0, null);
}
Set the desired render target
Obviously the batch can be used to draw numerous images (either defining the background scene or using multiple refractive objects)
Ensure all pixels have a default alpha value of 0
Change the render target to the back buffer
Refraction (shader) float4 RefractionPixelShader(float2 texCoord : TEXCOORD0) : COLOR0
{float4 colour = 0;float4 texColour = tex2D(diffuseSampler, texCoord);
if (texColour.a > 0){
float4 normal = tex2D(normalSampler, texCoord);float2 offset = normalMapHeight * normal.rg;
float4 refractedColour = tex2D(sceneSampler , texCoord + offset);
colour = (texColour * refractionOpacity) + (refractedColour * (1.0f - refractionOpacity));
}
else{
colour = tex2D(sceneSampler , texCoord);}
return colour; }
Define the output colour and retrieve the diffuse refraction colour for current pixel
Test to see if this pixel should be refracted (alpha value > 0)
sampler sceneSampler : register(s0);
texture refractionDiffuse;sampler diffuseSampler = sampler_state{ Texture = (refractionDiffuse); };
float refractionOpacity = .5;
texture refractionNormal;sampler normalSampler = sampler_state{ Texture = (refractionDiffuse); };
float normalMapHeight = .05;
technique Refraction{
pass Pass0{
PixelShader = compile ps_2_0 RefractionPixelShader();
}}
Background scene sampler
Diffuse refraction texture and alpha value
Normal refraction texture and normal height
Technique definition
Extract the corresponding normal and transform into a texture lookup offset
Determine the refracted colour
Combine the refracted colour with the diffuse refraction colour
If alpha value = 0, it is assumed there is no refraction, i.e. just return normal colour
HLSL EFFECTS : SHOCKWAVEShockwave HLSL effect
A shockwave effect is a wavelike effect that expands out from some centre point.
A shockwave can be defined to have a wave front and wave tail. Typically the wave front is more ‘compressed’ than the wave tail.
Shockwave
Centre
RadiusWave
fron
tWa
ve ta
il
Shockwave (definitions)
GraphicsDeviceManager graphics;SpriteBatch batch;Effect shockwaveEffect;
Texture2D scene;
RenderTarget2D renderTarget;
double time;
bool isAdditive;
renderTarget = new RenderTarget2D(graphics.GraphicsDevice,
graphics.GraphicsDevice,graphics.GraphicsDevice.Viewport.Width,graphics.GraphicsDevice.Viewport.Height,1, SurfaceFormat.Color );
Core objects used to define and support the operation of the effect
In this example, a ‘mock’ scene is held within a texture as the refraction background
The render target is used to hold the shockwave (build using the scene texture), which is then recombined with the scene
The shockwave time spans from 0 (just started) to 1 (maximum duration)
The isAdditive flag determines if additive or normal alpha blending is employed.
Shockwave (update+draw)
protected override void Update(GameTime gameTime)
{time += gameTime.
ElapsedGameTime.TotalSeconds;if (time > 1.0f)
time = 0.0f;}
protected override void Draw(GameTime gameTime){
graphics.GraphicsDevice.SetRenderTarget(0, renderTarget);
batch.Begin();batch.Draw( scene,
new Rectangle( 0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height),Color.White);
batch.End();
graphics.GraphicsDevice.SetRenderTarget(0, null);
batch.Begin();batch.Draw( renderTarget.GetTexture(),
new Rectangle( 0, 0, graphics.GraphicsDevice.Viewport.Width,
graphics.GraphicsDevice.Viewport.Height),Color.White);
batch.End();
// ...
Draw the rendered scene to the back buffer
Setup the render target
Draw the base scene into the render target – typically lots of drawing
Shockwave (draw)shockwaveEffect.Parameters["xcenter"].SetValue(0.5f);shockwaveEffect.Parameters["ycenter"].SetValue(0.5f);
shockwaveEffect.Parameters["width"].SetValue((float) time * 0.75f);shockwaveEffect.Parameters["magnitude"].SetValue((1.0f - (float) time ));
batch.Begin( Additive ? SpriteBlendMode.Additive : SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
shockwaveEffect.Begin();EffectPass pass = shockwaveEffect.CurrentTechnique.Passes[0];pass.Begin();batch.Draw(renderTarget.GetTexture(), new Rectangle( 0, 0,
graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height),pass.End();shockwaveEffect.End();
batch.End();}
Generate the shockwave using the render target and draw to the back buffer.
Store the centre of the shockwave (in texture space, i.e. from 0 to 1) Set the current
width and magnitude of the shockwave (expanding width and diminishing magnitude over time)
Start the sprite batch with the correct blend mode
Render the generated scene using the shockwave effect
Shockwave (shader)sampler2D samplerState : register(s0);
float xcenter;float ycenter;float magnitude;float width;
technique shockwave { pass {
pixelShader = compile ps_2_0 shockwave();
} }
float4 shockwave(float2 texCoord : TEXCOORD0) : COLOR0 {
float4 colour;float xdif = texCoord.x - xcenter;float ydif = texCoord.y - ycenter;float distance = sqrt(xdif * xdif + ydif * ydif) - width;float offset = abs(d);
if (distance < 0.1 && distance > -0.2) {if (distance < 0.0)
offset = (0.2 - offset) / 2.0;else
offset = (0.1 - offset);
texCoord.x += -(xdif * offset * magnitude); texCoord.y += -(ydif * offset * magnitude); colour = tex2D(samplerState, texCoord );
colour.a = offset * 12.0;} else {
colour.a = 0.0;}
return colour; }
If pixel is within shockwave radius, then determine offset lookup (the front of the wave is more strongly ramped than the tail of the wave)
Determine the shockwave’s pixel colour
Fade the shockwave out towards the edges of the waveIf not part of the
shockwave, then set the alpha value to zero
Define the centre of the shockwave, alongside its current magnitude and width
Determine distance from centre of shockwave. Set initial texture lookup offset to abs(distance)
HLSL EFFECTS : POINT SPRITESUsing HLSL to draw point sprites
Point Sprites (particle effects with point sprites)
If not using point sprites, each particle must be rendered using a screen aligned quad (i.e. two triangles sharing four vertices).
Using point sprites, only one vertex need be sent per particle with any drawn texture automatically mapped and aligned towards the screen.
The vertex/pixel shader can be used to update the particle effect (i.e. freeing up the CPU). Point sprites can be equally used within 2D and 3D games.
Point Sprites (defining a custom vertex) public struct CustomVertexDefinition
{public Vector3 Position;public float PointSize;
public static int SizeInBytes = (3+1) * sizeof(float);
public CustomVertexDefinition( Vector3 Position, float PointSize) {this.Position = Position;this.PointSize = PointSize;
}
public static VertexElement[] VertexElements ={
new VertexElement( 0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
new VertexElement(0, sizeof(float)*3, VertexElementFormat.Single,VertexElementMethod.Default, VertexElementUsage.PointSize, 0)
};}
The parameters needed to drive the point sprite effect should be defined here (ranging from a simple position, to a scale, alpha value, etc., etc.
The total size of the vertex (in bytes) must be defined here. Currently four floats.
Each vertex element is defined here. The second VertexElement parameter defines the offset for that element. The VertexElementUsage will enable the vertex element to be semantically mapped within the shader.
CustomVertexDefinition[] spriteArray = new CustomVertexDefinition[numSprites];
VertexDeclaration customVertexDeclaration = new VertexDeclaration(graphics.GraphicsDevice, CustomVertexDefinition.VertexElements);
Point Sprites(world view projection matrix)Matrix projectionMatrix =
Matrix.CreatePerspectiveFieldOfView(fieldOfView, aspectRatio, nearPlaneDistance, farPlaneDistance );
Matrix viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraTarget, cameraUpVector );
Matrix worldMatrix = Matrix.Identity * Matrix.CreateTranslation(
new Vector3( 0, 0, -5) ) ;
Matrix wvpMatrix = worldMatrix * viewMatrix * projectionMatrix;
How wide and far the camera can see
What the camera is looking at
The world location of the camera
The combined world-view-projection matrix
Point Sprites(drawing point sprites)protected override void Draw(GameTime gameTime){
graphics.GraphicsDevice.RenderState.PointSpriteEnable = true;
graphics.GraphicsDevice.VertexDeclaration = vertexPosColDecl;
// ...
pointSpritesEffect.Begin();foreach (EffectPass pass in pointSpritesEffect.CurrentTechnique.Passes){
pass.Begin(); graphics.GraphicsDevice.DrawUserPrimitives<CustomVertexDefinition>(
PrimitiveType.PointList, spriteArray, 0, spriteArray.Length);pass.End();
}pointSpritesEffect.End();
graphics.GraphicsDevice.RenderState.PointSpriteEnable = false;}
Instruct the GPU to consider vertices as point sprites
Specify the vertex format that will be used
Run the shader (e.g. particle effect)
Pass the created point sprite verticies to the GPU
Turn off point sprite drawing
Store other shader parameters, e.g. wvp matrix, etc.
Point Sprites(shader)float4 vertexShader(
float4 position : POSITION0) : POSITION0{
// Vertex parameter transformation
return mul(position, wvpMatrix);}
float4 pixelShader(PixelShaderInput input) : COLOR0
{float4 colour =
tex2D(pointSpriteSampler, input.texCoord.xy );
// Transform pixel colour
return colour;}
Define the world-view-projection matrix
Define the point sprite texture
As the PC and XBox 360 use different input semantics when using point sprites, ensure a correct mapping
Transform any vertex parameters if needed
Translate world particle position to the on-screen position
Determine the base particle colour
Transform the output colour if needed
float4x4 wvpMatrix;
texture pointSpriteTexture;sampler pointSpriteSampler = sampler_state{
texture = <pointSpriteTexture>;};
struct PixelShaderInput{ #ifdef XBOX float2 texCoord : SPRITETEXCOORD; #else float2 texCoord : TEXCOORD0; #endif };
Summary
To do:Complete Question
ClinicIf using XNA, decide if
you want to introduce custom effects into your game.
Today we explored:
Development of a refraction and shockwave shader effect
Exploration of point sprites and how they can be used for particle effects