Empty Vertex + Pixel Shader

Structure

The code starts with #defines we already know from C or C++. We basically map HLSL and GLSL constants (shader and vertex models, etc.) into a variable; beeing chosed during the compile time, in order to support HLSL and GLSL in one single .fx file.

#if OPENGL
	#define SV_POSITION POSITION
	#define VS_SHADERMODEL vs_3_0
	#define PS_SHADERMODEL ps_3_0
#else
	#define VS_SHADERMODEL vs_4_0_level_9_1
	#define PS_SHADERMODEL ps_4_0_level_9_1
#endif

Variables

The first thing we place below the defines are variables. Those variables are automatically “public” and can be set from outer space. Quick reference to variable declarations.

Texture2D SpriteTexture;
sampler2D SpriteTextureSampler = sampler_state
{
	Texture = <SpriteTexture>;
};

float4x4 projectionMatrix;
float4x4 viewMatrix;

MonoGame does apply on each drawn Texture2D a “default” shader. Hence, the default shader already takes in account the projection and view matrix. However, while using a custom shader, the proj and view matrix must be provided in order to render the Texture2D at the correct position. Therefore, we declare two variables: projectionMatrix and viewMatrix.

Vertex Logic

The parameters of the method (or function) must equal exactly this syntax! Even a different order of the variables will cause an exception.

  • position: The vertex positions
  • color: The colors on the texture
  • texCoord: The coordinates of the texture

Since we receive those values, we can modify each one of them in order to apply our custom shader effect. We return a custom struct (VertexShaderOutput) which is arbitrary. But since the pixel-shader builds up on the result of the vertex shader, texCoord and color are at least required.

The variables “viewMatrix” and “projectionMatrix” are multiplied by the position of the object. (Position = float4 = (x,y,z,w))

VertexShaderOutput VertexShaderLogic(float4 position : SV_POSITION, float4 color : COLOR0, float2 texCoord : TEXCOORD0)
{
	VertexShaderOutput output = (VertexShaderOutput)0;

	output.Position = mul(position, viewMatrix);
	output.Position = mul(output.Position, projectionMatrix);
	output.TexCoord = texCoord;
	output.Color = color;

	return output;
}

Pixel Logic

The result of the vertex shader will be passed on to the pixel shader. The pixel shader picks the color for each pixel and returns a float4.

PixelShaderOutput PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
	PixelShaderOutput output = (PixelShaderOutput)0;

	output.Color = tex2D(SpriteTextureSampler, input.TexCoord) * input.Color;

	return output;
}

I did create a struct for the return. Also possible would be a simple: “return tex2D(…);”

Technique

The technique contains n passes. Thus, a shader may contain several vertex and pixel manipulations. Since MonoGame only allows one shader per spriteBatch.Draw to be applied, we not only need one pass, but n passes to call as many shader functions as we want.

technique SpriteDrawing
{
	pass P0
	{
		VertexShader = compile VS_SHADERMODEL VertexShaderLogic();
		PixelShader = compile PS_SHADERMODEL PixelShaderFunction();
	}
};

Vertex vs Pixel Shader

As the name already indicates, the vertex shader modifies the vertices and the pixel shader modifies the pixels drawn onto the screen. Based on the required effect, the code belongs into the vertex and/or pixel function. As an example

PixelShader

  • Color adjustments
  • Texture2D combinations
  • Pixel removal
  • Lights

VertexShader

  • Distortion
  • Position adjustments

Source

#if OPENGL
	#define SV_POSITION POSITION
	#define VS_SHADERMODEL vs_3_0
	#define PS_SHADERMODEL ps_3_0
#else
	#define VS_SHADERMODEL vs_4_0_level_9_1
	#define PS_SHADERMODEL ps_4_0_level_9_1
#endif

Texture2D SpriteTexture;
sampler2D SpriteTextureSampler = sampler_state
{
	Texture = <SpriteTexture>;
};

float4x4 projectionMatrix;
float4x4 viewMatrix;

struct PixelShaderOutput
{
	float4 Color: COLOR0;
};

struct VertexShaderOutput
{
	float4 Position : SV_POSITION;
	float2 TexCoord : TEXCOORD0;
	float4 Color: COLOR0;
};

VertexShaderOutput VertexShaderLogic(float4 position : SV_POSITION, float4 color : COLOR0, float2 texCoord : TEXCOORD0)
{
	VertexShaderOutput output = (VertexShaderOutput)0;

	output.Position = mul(position, viewMatrix);
	output.Position = mul(output.Position, projectionMatrix);
	output.TexCoord = texCoord;
	output.Color = color;

	return output;
}

PixelShaderOutput PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
	PixelShaderOutput output = (PixelShaderOutput)0;

	output.Color = tex2D(SpriteTextureSampler, input.TexCoord) * input.Color;

	return output;
}

technique SpriteDrawing
{
	pass P0
	{
		VertexShader = compile VS_SHADERMODEL VertexShaderLogic();
		PixelShader = compile PS_SHADERMODEL PixelShaderFunction();
	}
};

1
Hinterlasse einen Kommentar

Please Login to comment
  Subscribe  
newest oldest most voted
Notify of
trackback

[…] Wind is one way to improve the scenery with vegetation. Thus, my first shader focuses on horizontal force influence. The target is to move trees, plants, etc. horizontally (in a kinda wavy form) to simulate wind. (Empty template reused) […]