Edge Detection By Pixel Shader HLSL
自打为XPEC-BeiJing做事职务开发的缘故,这自己做些玩意儿的机会可少多了。
最近为年轻人准备了一些HLSL Shader的讲义,于是作了个lena的edge detection.
这技术很简单,不过在NPR方面还是有些用处。

图如上,还是比较清楚地把线段都弄出来了的。道理很简单,就是观察任意像素与周围八个像素是否有比较大的差异,如果比较大
那么就认为是边缘。常用的边缘检测算子有Laplace,Sobel,Canny等等,我这种是Roberts的一种"蛮力"推广.
完毕.下面该写Vertex Shader的讲义了,挑个简单的,来个Ocean Water Simulation吧.主要为了破除新同事对Shader和Graphics
的神秘感以及'科学文章'的神秘感.揭露一下那些用所谓的FFT和其他古怪的数学记法的本质就是个加号和逼近而已.
说实话,与那些连sin(x)都要写成复数形式的所谓科学家,我们专业的游戏程序员没有二话,推倒,打到死!哈哈
HLSL Pixel Shader:
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
float4 g_MaterialAmbientColor; // Material's ambient color
float4 g_MaterialDiffuseColor; // Material's diffuse color
float3 g_LightDir; // Light's direction in world space
float4 g_LightDiffuse; // Light's diffuse color
texture g_MeshTexture; // Color texture for mesh
float g_fTime; // App's time in seconds
float4x4 g_mWorld; // World matrix for object
float4x4 g_mWorldViewProjection; // World * View * Projection matrix
//--------------------------------------------------------------------------------------
// Texture samplers
//--------------------------------------------------------------------------------------
sampler MeshTextureSampler =
sampler_state
{
Texture = <g_MeshTexture>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
//--------------------------------------------------------------------------------------
// Vertex shader output structure
//--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
float4 Position : POSITION; // vertex position
float4 Diffuse : COLOR0; // vertex diffuse color (note that COLOR0 is clamped from 0..1)
float2 TextureUV : TEXCOORD0; // vertex texture coords
};
//--------------------------------------------------------------------------------------
// This shader computes standard transform and lighting
//--------------------------------------------------------------------------------------
VS_OUTPUT RenderSceneVS( float4 vPos : POSITION,
float3 vNormal : NORMAL,
float2 vTexCoord0 : TEXCOORD0 )
{
VS_OUTPUT Output;
float3 vNormalWorldSpace;
// Transform the position from object space to homogeneous projection space
Output.Position = mul(vPos, g_mWorldViewProjection);
// Transform the normal from object space to world space
vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)
// Calc diffuse color
Output.Diffuse.rgb = g_MaterialDiffuseColor * g_LightDiffuse * max(0,dot(vNormalWorldSpace, g_LightDir)) +
g_MaterialAmbientColor;
Output.Diffuse.a = 1.0f;
// Just copy the texture coordinate through
Output.TextureUV = vTexCoord0;
return Output;
}
//--------------------------------------------------------------------------------------
// Pixel shader output structure
//--------------------------------------------------------------------------------------
struct PS_OUTPUT
{
float4 RGBColor : COLOR0; // Pixel color
};
float2 PixelKernel2[9] =
{
float2(-1, -1),float2( 0, -1),float2( 1, -1),
float2(-1, 0),float2( 0, 0),float2( 1, 0),
float2(-1, 1),float2( 0, 1),float2( 1, 1),
};
float2 TexelKernel2[9]
<
string ConvertPixelsToTexels = "PixelKernel";
>;
float3 LuminanceConv = { 0.2125f, 0.7154f, 0.0721f };
//--------------------------------------------------------------------------------------
// This shader outputs the pixel's color by modulating the texture's
// color with diffuse material color
//--------------------------------------------------------------------------------------
PS_OUTPUT RenderScenePS( VS_OUTPUT In )
{
PS_OUTPUT Output;
//原始值
float4 Orig = tex2D( MeshTextureSampler, In.TextureUV );
float4 Sum = 0;
//看看和周围差多少
for( int i = 0; i < 9; i++ )
//这0.4,1.2,0.5都是可调参数 其中0.4是一个Threshold
Sum += ( abs(Orig - tex2D(MeshTextureSampler, In.TextureUV + TexelKernel2[i]))-0.4 ) * 1.2 + 0.5f;
Output.RGBColor = saturate(dot(LuminanceConv,Sum));;
return Output;
}
最近为年轻人准备了一些HLSL Shader的讲义,于是作了个lena的edge detection.
这技术很简单,不过在NPR方面还是有些用处。
图如上,还是比较清楚地把线段都弄出来了的。道理很简单,就是观察任意像素与周围八个像素是否有比较大的差异,如果比较大
那么就认为是边缘。常用的边缘检测算子有Laplace,Sobel,Canny等等,我这种是Roberts的一种"蛮力"推广.
完毕.下面该写Vertex Shader的讲义了,挑个简单的,来个Ocean Water Simulation吧.主要为了破除新同事对Shader和Graphics
的神秘感以及'科学文章'的神秘感.揭露一下那些用所谓的FFT和其他古怪的数学记法的本质就是个加号和逼近而已.
说实话,与那些连sin(x)都要写成复数形式的所谓科学家,我们专业的游戏程序员没有二话,推倒,打到死!哈哈
HLSL Pixel Shader:
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
float4 g_MaterialAmbientColor; // Material's ambient color
float4 g_MaterialDiffuseColor; // Material's diffuse color
float3 g_LightDir; // Light's direction in world space
float4 g_LightDiffuse; // Light's diffuse color
texture g_MeshTexture; // Color texture for mesh
float g_fTime; // App's time in seconds
float4x4 g_mWorld; // World matrix for object
float4x4 g_mWorldViewProjection; // World * View * Projection matrix
//--------------------------------------------------------------------------------------
// Texture samplers
//--------------------------------------------------------------------------------------
sampler MeshTextureSampler =
sampler_state
{
Texture = <g_MeshTexture>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
//--------------------------------------------------------------------------------------
// Vertex shader output structure
//--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
float4 Position : POSITION; // vertex position
float4 Diffuse : COLOR0; // vertex diffuse color (note that COLOR0 is clamped from 0..1)
float2 TextureUV : TEXCOORD0; // vertex texture coords
};
//--------------------------------------------------------------------------------------
// This shader computes standard transform and lighting
//--------------------------------------------------------------------------------------
VS_OUTPUT RenderSceneVS( float4 vPos : POSITION,
float3 vNormal : NORMAL,
float2 vTexCoord0 : TEXCOORD0 )
{
VS_OUTPUT Output;
float3 vNormalWorldSpace;
// Transform the position from object space to homogeneous projection space
Output.Position = mul(vPos, g_mWorldViewProjection);
// Transform the normal from object space to world space
vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)
// Calc diffuse color
Output.Diffuse.rgb = g_MaterialDiffuseColor * g_LightDiffuse * max(0,dot(vNormalWorldSpace, g_LightDir)) +
g_MaterialAmbientColor;
Output.Diffuse.a = 1.0f;
// Just copy the texture coordinate through
Output.TextureUV = vTexCoord0;
return Output;
}
//--------------------------------------------------------------------------------------
// Pixel shader output structure
//--------------------------------------------------------------------------------------
struct PS_OUTPUT
{
float4 RGBColor : COLOR0; // Pixel color
};
float2 PixelKernel2[9] =
{
float2(-1, -1),float2( 0, -1),float2( 1, -1),
float2(-1, 0),float2( 0, 0),float2( 1, 0),
float2(-1, 1),float2( 0, 1),float2( 1, 1),
};
float2 TexelKernel2[9]
<
string ConvertPixelsToTexels = "PixelKernel";
>;
float3 LuminanceConv = { 0.2125f, 0.7154f, 0.0721f };
//--------------------------------------------------------------------------------------
// This shader outputs the pixel's color by modulating the texture's
// color with diffuse material color
//--------------------------------------------------------------------------------------
PS_OUTPUT RenderScenePS( VS_OUTPUT In )
{
PS_OUTPUT Output;
//原始值
float4 Orig = tex2D( MeshTextureSampler, In.TextureUV );
float4 Sum = 0;
//看看和周围差多少
for( int i = 0; i < 9; i++ )
//这0.4,1.2,0.5都是可调参数 其中0.4是一个Threshold
Sum += ( abs(Orig - tex2D(MeshTextureSampler, In.TextureUV + TexelKernel2[i]))-0.4 ) * 1.2 + 0.5f;
Output.RGBColor = saturate(dot(LuminanceConv,Sum));;
return Output;
}
