Jul 20

When we last left our project we had a  fully working 3D model in XNA running on Windows Phone, alas there were no shaders so while it looked like a TopHat in shape it didn’t really look like much. In fact if we had put this on a white background  we wouldn’t have been able to tell there was a TopHat shape at all..


image

 

So now lets got back into our project and add some shaders, so the whole thing can be textured properly.

We have to do two things, here are the steps:

  1. Add the realtime DirectX Shaders into the content folder of our XNA Game Studio 4 Solution.
  2. Copy the shaders also into our XSI project models and assign them as our shaders we are using into the mod tool.

First we go back into our Autodesk XSI mod tool and find the shaders. When we updated the Mod Tool to support XNA Game Studio it installed everything we need including the FX Samples in the XNA Game Studio menu item including a menu ITEM to help us find the FX files we need to add back to  our XNA Game Studio 4 project....

We first need to add a folder called textures to our content folder in our content project as part of our solution file..  To do this right click on the content project in our Solution Project.. and select (from the pop-up menu Add –> New Folder…

image

now we have to add the shaders from within the Mod Tool’s add-on folders with the appropriate direct X shaders.. This will let the GPU access them via the XNA pipeline as part of the project when the game is compiled and run.,

If you notice in our solution explorer I have two “Models” folder, I have one in the main project as sort of a repository.. I usually don’t include this in the compile time resources, it’s mainly there for me to start back porting this Visual Studio Project sample back to Visual Studio 2008/XNA Game Studio 3.1 and the X-Box 360..

Next we are going to copy the textures over but we have to find them first..

So it’s back to the Autodesk SoftImage Mod Tool for the moment to our XNA menu.. and select “browse fx samples

browsefx

This will open the shaders that are available and we are allowed to use on our project. These are realtime rendered FX shaders (the DirectX variety). You can use these to apply surface FX to the project. WARNING: there are other shaders with Autodesk SoftImage tool but you shouldn’t use them in your project at all because they are designed for non-XNA use. In other words, if you were rendering out to film in SoftImage they would be for that purpose ONLY..

So after selecting the “Browse FX Samples” menu a new dialog will pop up with the location of our useable shader FX files and a list of them..

image

In the file list you will see both files ending in the .FX extension, we’ll need these copied over to our XNA Game Studio 4.0 project but also the files ending in “.HLSL”.  HLSL stands for “High Level Shader Language” and it is actually the DirectX 9 shader that we will be using to dress up our TopHat object..

The other files are mapping files that are attached to the surfaces and rendered by the shader.

we are going to add these as well, however they are not needed at this moment for this example..

In the top is the path to these files we will need to copy this full path and hop into visual our XNA Game Studio 4 project with this..

The default path to these files on my system is:

C:\Softimage\Softimage_Mod_Tool_7.5\Addons\XNAGSE\Data\XNA_SAMPLES\FX

addtextures1

So back in XNA Game Studio 4 we right click on our already created textures folder and select Add –> existing item..

from the folder list that pops up we browse to..

C:\Softimage\Softimage_Mod_Tool_7.5\Addons\XNAGSE\Data\XNA_SAMPLES\FX

selectAllshaders

 

for safety and to make sure everything is need I select ALL and add them to my textures folder..

I also manually copy all of the folders to the XSI folder inside of content of the main project to make sure XSI can see and use these..

image

Next we will go back into the Mod Tool and assign a shader to our TopHat model.. I am going to choose the standard phong shader..

from the browser we opened earlier I can simply click on the file name of the shader (phong.fx) and drag and drop onto one of the meshs. I will need to do it for the trunk and the brim of the hat..

dragndrop

To verify that we have added the shader to our mesh we can go into the scene explorer and verify that they are there and in the right places by clicking on the SELECT scene button ..

shaderverify

the phong shader has been applied to the trunk and the hat Brim meshes.

after we have dragged and dropped the texture and verified it’s there we can turn on the DirectX9 Real-time shader view by clicking on the view option drop down menu in the upper right corner and selecting DirectX9..

Warning Note: Using a DirectX10 only shader and viewing in DirectX10 will require a DirectX10 card and may not be backwards compatible..

image

If the view doesn’t show up and we get an error it’s usually because we haven’t assigned the proper FX shader to the textures.. As you can see in this view the TopHat object still isn’t much to look at, as everything is set for it’s default values..

By selecting either the Trunk or the Brim mesh inside the view, we can then go in and make changes to color etc. We can even set the method to skinning, which I will cover in a later tutorial..

image

Adding your own shaders

It is possible to add your own shaders into both your XNA Game Studio project and Map them in the Mod Tool. You just need two files yourself to do this an .FX “wrapper” file and the .HLSL shader file itself.. However realize some XNA targets don’t support custom shaders, or to be more precise only specific shaders..

Note: there are a few differences as I noted earlier in the type of shaders and texturing that Windows Phone and X-Box 360 can support. If you are starting the project as a PC game then you need to set the project properties in Visual Studio 2010/XNA Game Studio 4 as follows..

image

If you are coding first for a Windows Game it’s okay to set for “HiDef”, if you need to write just for the X-Box 360 or the Windows Phone 7 then you should use the “Reach” profile. Know that certain features and limits based on the X-box and Windows Phone will be observed and if your models don’t have the right number of vertexes for instance you will get errors with you content and have to go back and rework your 3d content models..

 

 

The wrapper looks something like this (it’s just a text file that can be opened).

Here is the base template for the FX file…  This is the minimal information required for every shader in the Mod Tool. Notice that it includes both static and skinned methods.

Template.FX

   1: #include <xsi_include9.hlsl> 
   2:  
   3: //**********************************************************************
   4: // Tweakables
   5: //**********************************************************************
   6:  
   7: float4 ColorParameter
   8: <
   9:     string SasUiControl = "ColorPicker";
  10:     string SasUiLabel =  "Color";    
  11: > = {1.0f, 1.0f, 1.0f, 1.0f};
  12:  
  13: //**********************************************************************
  14: // Runtime bound
  15: //**********************************************************************
  16: // lights
  17: #include <xsi_lightlist9.hlsl>
  18:  
  19:  
  20:  
  21: //**********************************************************************
  22: // Vertex Shaders
  23: //**********************************************************************
  24:  
  25: #include <xsi_defaultvs.hlsl>
  26:  
  27:  
  28: //**********************************************************************
  29: // Pixel Shaders
  30: //**********************************************************************
  31:  
  32: float4 PS
  33: (
  34:     XSI_VertexToPixel IN
  35: ) : COLOR
  36: {
  37:     return ColorParameter;
  38: }
  39:  
  40: //**********************************************************************
  41: // Techniques
  42: //**********************************************************************
  43:  
  44:  
  45: technique Static
  46: {
  47:     pass p0
  48:     {        
  49:         VertexShader = compile vs_2_0 VSStatic();
  50:         PixelShader = compile ps_2_0 PS();
  51:     }
  52: }
  53:  
  54: technique Skinned
  55: {
  56:     pass p0
  57:     {        
  58:         VertexShader = compile vs_2_0 VSSkinned();
  59:         PixelShader = compile ps_2_0 PS();
  60:     }
  61: }
  62:  

If you want to look at the Phong.FX file you will notice it fills in quite a bit more information about the techniques etc..

Here is the phong shader FX file we just applied..

   1: #include <xsi_include9.hlsl> 
   2:  
   3: //**********************************************************************
   4: // Tweakables
   5: //**********************************************************************
   6:  
   7: float3 AmbientColor
   8: <
   9:     string SasUiControl = "ColorPicker";
  10:     string SasUiLabel =  "Ambient";    
  11: > = {0.3f, 0.3f, 0.3f};
  12:  
  13: float3 DiffuseColor
  14: <
  15:     string SasUiControl = "ColorPicker";
  16:     string SasUiLabel =  "Diffuse";    
  17: > = {0.7f, 0.7f, 0.7f};
  18:  
  19: float3 SpecularColor
  20: <
  21:     string SasUiControl = "ColorPicker";
  22:     string SasUiLabel =  "Specular";    
  23: > = {1.0f, 1.0f, 1.0f};
  24:  
  25: float SpecularPower
  26: <
  27:     string SasUiControl = "Slider";
  28:     string SasUiLabel = "Specular Power";
  29:     float SasUiMin = 1;
  30:     float SasUiMax = 200;    
  31: > = 20.0f;
  32:  
  33: texture2D AmbientMap
  34: <
  35:     string ResourceName = "default_ambocc_map.png";
  36:     string ResourceType = "2D";
  37: >;
  38:  
  39: texture2D AlbedoMap
  40: <
  41:     string ResourceName = "default_surface_map.png";
  42:     string ResourceType = "2D";
  43: >;
  44:  
  45: texture2D NormalMap
  46: <
  47:     string ResourceName = "default_normal_map.png";
  48:     string ResourceType = "2D";
  49: >;
  50:  
  51: sampler2D AmbientSampler = sampler_state
  52: {
  53:     Texture = <AmbientMap>;
  54:     MipFilter = LINEAR; 
  55:     MinFilter = LINEAR;
  56:     MagFilter = LINEAR;    
  57: };
  58:  
  59: sampler2D AlbedoSampler = sampler_state
  60: {
  61:     Texture = <AlbedoMap>;
  62:     MipFilter = LINEAR; 
  63:     MinFilter = LINEAR;
  64:     MagFilter = LINEAR;    
  65: };
  66:  
  67: sampler2D NormalSampler = sampler_state
  68: {
  69:     Texture = <NormalMap>;
  70:     MipFilter = LINEAR; 
  71:     MinFilter = LINEAR;
  72:     MagFilter = LINEAR;    
  73: };
  74:  
  75: //**********************************************************************
  76: // Runtime bound
  77: //**********************************************************************
  78:  
  79:  
  80: float4 sieye
  81: <
  82:     string SasBindAddress = "Sas.Camera.Position"; 
  83: >;
  84:  
  85:  
  86: // lights
  87: #include <xsi_lightlist9.hlsl> 
  88:  
  89:  
  90: //**********************************************************************
  91: // Vertex Shaders
  92: //**********************************************************************
  93:  
  94: #include <xsi_defaultvs.hlsl>
  95:  
  96:  
  97: //**********************************************************************
  98: // Pixel Shaders
  99: //**********************************************************************
 100:  
 101: float4 Phong_2
 102: (
 103:     XSI_VertexToPixel IN
 104: ) : COLOR
 105: {
 106:     #include<xsi_lightdef9.hlsl>
 107:  
 108:     float3 globalpos = IN.texcoord4;    
 109:     float3x3 TangentToWorldSpace;
 110:     
 111:     float3 lightcolor = 0.0f;
 112:     
 113:     //*************************************************
 114:     // sample our textures
 115:     //*************************************************
 116:     float3 normaltex = tex2D(NormalSampler, IN.texcoord0) * 2 - 1;
 117:     float3 ambienttex = tex2D(AmbientSampler, IN.texcoord0);
 118:     float3 albedotex = tex2D(AlbedoSampler, IN.texcoord0);
 119:     
 120:     AmbientColor = AmbientColor * ambienttex;
 121:     DiffuseColor = DiffuseColor * albedotex;
 122:     
 123:     TangentToWorldSpace[0] = IN.texcoord5.xyz;
 124:     TangentToWorldSpace[1] = IN.texcoord6.xyz;    
 125:     TangentToWorldSpace[2] = IN.texcoord7.xyz;
 126:     
 127:     //*************************************************
 128:     // convert normal in world space
 129:     //*************************************************
 130:     float3 normal = normalize(mul(normaltex,TangentToWorldSpace));
 131:     
 132:     //*************************************************
 133:     // eye to vertex    
 134:     //*************************************************
 135:     float3 eyetovert = normalize(sieye.xyz - globalpos);
 136:     
 137:     //*************************************************
 138:     // light up
 139:     //*************************************************
 140:     
 141:     float3 ts_lightdir;
 142:     float3 ts_hvec;
 143:         
 144:     int loop;
 145:     for(loop = 0; loop < NUM_LIGHTS; loop++)
 146:     {
 147:     
 148:         // light direction 
 149:         ts_lightdir = LightPos[loop].xyz - globalpos;
 150:         
 151:         float lightdistance = length(ts_lightdir);
 152:         ts_lightdir = normalize(ts_lightdir);
 153:     
 154:         // half vector
 155:         ts_hvec = normalize(eyetovert + ts_lightdir);
 156:     
 157:         float3 currentcolor =  LightCol[loop] * (
 158:             (DiffuseColor * clamp(dot(normal, ts_lightdir), 0, 1)) +    // diffuse
 159:             (SpecularColor * LightCol[loop] * pow(clamp(dot(normal, ts_hvec),0,1), SpecularPower)));    // specular
 160:             
 161:         lightcolor += currentcolor;
 162:     }    
 163:     
 164:     
 165:     float4 result;
 166:     result.xyz = AmbientColor + lightcolor ;    
 167:     result.w = 1;
 168:  
 169:  
 170:     return result;
 171: }
 172:  
 173: //**********************************************************************
 174: // Techniques
 175: //**********************************************************************
 176:  
 177:  
 178: technique Static
 179: {
 180:     pass p0
 181:     {        
 182:         VertexShader = compile vs_2_0 VSStatic();
 183:         PixelShader = compile ps_2_0 Phong_2();
 184:     }
 185: }
 186:  
 187: technique Skinned
 188: {
 189:     pass p0
 190:     {        
 191:         VertexShader = compile vs_2_0 VSSkinned();
 192:         PixelShader = compile ps_2_0 Phong_2();
 193:     }
 194: }
 195:  

Next we should look at the HLSL file  that is included (or referred to) in the shader phong shader file above file..

 

   1: //************************************************************
   2: // standard include file for XSI DirectX 9 HLSL shaders
   3: //************************************************************
   4:  
   5: //************************************************************
   6: // Application to vertex data
   7: //************************************************************
   8: struct XSI_AppToVertex
   9: {
  10:     float4 position : POSITION;
  11:     float4 normal : NORMAL;
  12:     float4 color0 : COLOR0;
  13:     float4 color1 : COLOR1;
  14:     float4 texcoord0 : TEXCOORD0;
  15:     float4 texcoord1 : TEXCOORD1;
  16:     float4 texcoord2 : TEXCOORD2;
  17:     float4 texcoord3 : TEXCOORD3;
  18:     float4 texcoord4 : TEXCOORD4;
  19:     float4 texcoord5 : TEXCOORD5;
  20:     float4 texcoord6 : TEXCOORD6;
  21:     float4 texcoord7 : TEXCOORD7;
  22:     float4 BoneIndices : BLENDINDICES0;
  23:     float4 BoneWeights : BLENDWEIGHT0;    
  24: };
  25:  
  26: //************************************************************
  27: // Vertex to pixel data
  28: //************************************************************
  29: struct XSI_VertexToPixel
  30: {
  31:     float4 position : POSITION;
  32:     float4 color0 : COLOR0;
  33:     float4 color1 : COLOR1;
  34:     float4 texcoord0 : TEXCOORD0;
  35:     float4 texcoord1 : TEXCOORD1;
  36:     float4 texcoord2 : TEXCOORD2;
  37:     float4 texcoord3 : TEXCOORD3;
  38:     float4 texcoord4 : TEXCOORD4;
  39:     float4 texcoord5 : TEXCOORD5;
  40:     float4 texcoord6 : TEXCOORD6;
  41:     float4 texcoord7 : TEXCOORD7;
  42: };

 

There are many ways to get shader files of all types on the internet, anything from Toon Shaders, to glass, metals, etc.. I recommend if you want to experiment with creating your own there are two great ones available that won’t require much coding on your part...

FX Composer from NVIDIA

ATI Render Monkey from AMD

You might also check out NVIDIA’s HLSL shader library..

http://developer.download.nvidia.com/shaderlibrary/webpages/hlsl_shaders.html

Here is the same example with virtually the same code and model running first as a PC XNA GAME Application

 


 

And again our sample running on Windows Phone 7

 

This runs great on the X-Box 360, but it’s a little difficult for me to do a screen capture at the moment. Let me just say, writing code once and having the same “connected experience” on all three places is really fun..