Gamasutra is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Gamasutra: The Art & Business of Making Gamesspacer
From XNA to MonoGame
arrowPress Releases
November 16, 2019
Games Press
View All     RSS







If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 

From XNA to MonoGame


May 15, 2013 Article Start Previous Page 3 of 6 Next
 

Using Custom Effects

If you want to use Effect files from a previous XNA project or an XNA sample, you'll need to process them with the MonoGame Effect processor to compile them for that specific platform. Some of these use OpenGL rather than DirectX as their graphics API, so the Effect file from XNA will need to be converted to OpenGL shader language for it to work.

Rather than have developers rewrite their shaders to GLSL, MonoGame installs some tooling to automatically convert the HLSL in the Effect file to the appropriate shader language for the target platform. For the DirectX-based platforms, MonoGame uses the DirectX 11 tool chain to compile your Effect into a shader optimized for that platform. For the OpenGL-based platforms, the Effect is processed by a tool called MojoShader, which does a low-level conversion from HLSL to GLSL that allows the Effect to work on that platform.

Of course, this conversion process can occasionally introduce errors or unsupported features that the target platform does not support. For example, with OpenGL Shader Model 3.0, you cannot do a texture lookup in a Vertex Shader, so if your Effect uses that feature it probably won't work. Let's take a sample effect from one of the XNA samples available on the Xbox Creators Club website -- the Bloom Extract Effect is a good example . Although it is only a pixel shader, it will give you a good idea of what kind of things we need to look at.

Listing 1: Bloom extract.

// Pixel shader extracts the brighter areas of an image.

// This is the first step in applying a bloom postprocess.

sampler TextureSampler : register(s0);

float BloomThreshold;

float4 PixelShaderFunction(

float2 texCoord : TEXCOORD0

) : COLOR0

{

// Look up the original image color.

float4 c = tex2D(TextureSampler, texCoord);

// Adjust it to keep only values brighter than the specified threshold.

return saturate((c - BloomThreshold) / (1 - BloomThreshold));

}

technique BloomExtract

{

pass Pass1

{

PixelShader = compile ps_2_0 PixelShaderFunction();

}

}

If you look at the code for the effect in Listing 1, one of the first things to note is that this effect is using pixel shader 2.0 (ps_2_0). This is fine for DirectX 9, but for OpenGL and DirectX 11 this needs to change. Before we get into the code changes, it is worth noting that you can use conditional defines within effect files to change the behavior depending on the shader model you are targeting. If you are targeting shader model 4, you can use this:

#if SM4

// code

#endif

to handle that special case. These defines are still valid when using the MonoGame Content processor, so in order to make this shader support all the platforms we want, we need to update the technique section to handle all the platforms you want to support. In this case, we need to support Shader Model 4 for DirectX 11 and Shader Model 3 for OpenGL/GLES. With that in mind, the Pass becomes:

pass Pass1

{

#if SM4

PixelShader = compile ps_4_0_level_9_1 PixelShaderFunction();

#elif SM3

PixelShader = compile ps_3_0 PixelShaderFunction();

#else

PixelShader = compile ps_2_0 PixelShaderFunction();

#endif

}

For each type of Shader Model, we define a different Pixel Shader; you can also do this with Vertex Shaders, so a declaration of vs_2_0 would become vs_3_0 for SM3 and vs_4_0_level_9_1 for SM4.

Next, let's look at the parameters passed into PixelShaderFunction. In the sample effect, it only takes one parameter -- but in order for this effect to work correctly with the SpriteBatch Effect within MonoGame, we'll need to add the additional parameters. (This is a limitation with MonoGame at the moment that will probably be resolved in the future.) The good news is that adding these extra parameters does not break the effect in normal XNA, so in this case, we can just add the missing parameters like so:

void PixelShaderFunction( float3 position: POSITION0, float4 color : COLOR0, float2 texCoord : TEXCOORD0)

Watch out: In XNA 3.1, the PixelShader and VertexShader functions were called PixelShader and VertexShader. This is no longer valid in XNA 4.0 or MonoGame, which is why in Listing 1 we renamed the vertex and pixel shader functions to VertexShaderFunction and PixelShaderFunction. Of course, you can call them anything you like. 

Supergiant Games used a fork of MonoGame code to port Bastion to iPad.

If you apply this technique to all of the effects that are included in the Bloom sample, porting that project over to Windows 8, Android, and iOS simply becomes a matter of using the Content Builder to produce the .xnb files for each platform you are targeting, and then linking to those files for your project.


Article Start Previous Page 3 of 6 Next

Related Jobs

Hidden Path Entertainment
Hidden Path Entertainment — Belleview, Washington, United States
[11.15.19]

Senior Gameplay Programmer
Disbelief
Disbelief — Chicago, Illinois, United States
[11.15.19]

Senior Programmer, Chicago
Disbelief
Disbelief — Chicago, Illinois, United States
[11.15.19]

Junior Programmer, Chicago
Sony PlayStation
Sony PlayStation — San Diego, California, United States
[11.15.19]

Character Rigging Supervisor





Loading Comments

loader image