   [.net] Basic Effects help
  Hi All,Over the last year and a bit I have been writing an Ancients wargame in c sharp and managed direct-x. The original engine is fixed function pipeline only, but recently I have developed an interest in Effects and Shaders.I have tried to use various shader examples from nVidia, one or two of them kind of work, but the others don't. I know this is down to dodgy coding on my part :)Could someone just check my understanding on effect use:1. Create an effect and load it.2. Load any textures that might be required by an effect (on class instantiation).3. Set the technique.4. Set the relevant effect parameters via SetValue - including textures, matrices, and other assorted values.5. Call Effect.Begin to get the number of passes.6. Loop through the passes, setting effect.BeginPass(i) each time.7. Do standard mesh rendering. ie mesh.DrawSubset(0);8. End the pass with effect.EndPass then iterate to the next pass.9. After all passes are finished call effect.End()Now when I do this I tend to get matt looking meshes - normally in a light blue color, regardless of the effect being used. I'm sure I'm missing a trick here and that there is something else I need to do.I know that my models are compatible because I exported one to .x format and ran it in the excellent nVidia DXSAS demo where it works fine!Any help would be much appreciated.RobPhttp://AncientArmies.co.uk   
  A quick update.I found one thing wrong. My vertex formats were not matching those expected by the shader. I fixed this and the displayed models now at least appear in the right place and in the right shape.The problem is the color. Regardless of which shader effect I choose to use, including my own super simple one which just performs the relevant positional transforms then changes the output color to green - the result is always the same - A cyan colored unit.The colouration is completely uniform as if the normals were screwed up or as if there are no real lighting calcs being performed.Given that the vertex part of the shaders seems to work its got to be something pixel shader related. However, it can't be the effects or my system because the effects work under FX Composer.Is there something I need to do in the main code to tie up the output of the pixel shader to the screen?Will post more when I discover new information. When this is over I'm going to publish a very simple guide for interfacing with shaders! :)RobPhttp://AncientArmies.co.uk   ;Quote:1. Create an effect and load it.2. Load any textures that might be required by an effect (on class instantiation)....From a quick glance, this looks fine (apart from getting your vertex format right, which you experienced later).Quote:I'm sure I'm missing a trick here and that there is something else I need to doIt's all about render states (alpha, zbuffer,...). You either set them prior to effect.Begin() or have them coded in HLSL (not sure if all states can be coded in HLSL though).Provide the code of your setup, drawing and shaders and show us a screen-shot, so we can help concretely.;  Here's my code :)The shader itself looks like this:/************* UN-TWEAKABLES **************/float4x4 WorldITXf : WorldInverseTranspose< string UIWidget="None"; >;float4x4 WvpXf: WorldViewProjection< string UIWidget="None"; >;float4x4 WorldXf   : World< string UIWidget="None"; >;float4x4 ViewIXf   : ViewInverse< string UIWidget="None"; >;/************* DATA STRUCTS **************//* data from application vertex buffer */struct appdata {float3 Position: POSITION;float3 Normal    : NORMAL;float4 Color : COLOR0;};/* data passed from vertex shader to pixel shader */struct vertexOutput {float4 HPosition: POSITION;float4 Color : COLOR0;};/*********** vertex shader ******/vertexOutput simpleVS(appdata IN) {vertexOutput OUT = (vertexOutput)0;float4 Po = float4(IN.Position.xyz, 1);OUT.HPosition = mul(Po, WvpXf);OUT.Color = IN.Color;return OUT;}/********* pixel shader ********/float4 simplePS(vertexOutput IN) : COLOR {//float4 color = float4(1.0, 0, 0, 1.0);IN.Color = float4(1.0, 0, 0, 1.0);return IN.Color;}/*************/technique main{pass p0{VertexShader = compile vs_2_a simpleVS();PixelShader = compile ps_2_a simplePS();ZEnable = true;ZWriteEnable = true;CullMode=None; }}/***************************** eof ***/The above effect is pretty simple, just performs the transforms - which it does - then colours everything matt red - this works in Fx Composer but not in my app. In fact all the effects I have tried result in good vertex transforms but a cyan coloured object as seen below:It seems that I always get a cyan block regardless of the effect I choose.In terms of source code, I create the following vertex definition:  m_Velements = new VertexElement[]  { new VertexElement(0, 0, DeclarationType.Float3,DeclarationMethod.Default,DeclarationUsage.Position, 0),new VertexElement(0, 12, DeclarationType.Float4,DeclarationMethod.Default,DeclarationUsage.Normal, 0),    new VertexElement(0, 28, DeclarationType.Float2,DeclarationMethod.Default,DeclarationUsage.TextureCoordinate, 0),   new VertexElement(0, 36, DeclarationType.Color,   DeclarationMethod.Default,   DeclarationUsage.Color, 0),   VertexElement.VertexDeclarationEnd  };  m_Vd = new VertexDeclaration(IonianSurface.device, m_Velements);For the drawing code I have:if (isVisible){  if (m_UseShadows)  {    generateShadowVolumes();  }  IonianSurface.device.VertexDeclaration = m_Vd;   m_WorldMatrix = (Matrix.RotationZ(m_Yaw) * Matrix.RotationX(m_Pitch) * Matrix.RotationY(m_Roll) * Matrix.Scaling(1f, 1f, 1f)) * Matrix.Translation((float)m_X, (float)m_Y, 0.0f);  IonianSurface.device.Transform.World = m_WorldMatrix;  IonianSurface.device.Transform.View = IonianSurface.camera.viewMatrix;  IonianSurface.device.Transform.Projection = IonianSurface.projectionMatrix;  if (m_RecalcModel)  {    initUnitVertexBuffer();    populateVd();    m_RecalcModel = false;  }  Matrix all = m_WorldMatrix;  all.Multiply(IonianSurface.camera.viewMatrix);  all.Multiply(IonianSurface.projectionMatrix);  Matrix invView = IonianSurface.camera.viewMatrix;  invView.Invert();   Matrix invWorldT = m_WorldMatrix;  invWorld.Invert();  invWorld.Transpose(invWorld);  m_Effect.Technique = "main";  m_Effect.SetValue("WorldITXf", invWorldT);  m_Effect.SetValue("WvpXf", all);  m_Effect.SetValue("WorldXf", m_WorldMatrix);  m_Effect.SetValue("ViewIXf", invView);    int passes = m_Effect.Begin(0);  for (int i = 0; i < passes; i++)  {    m_Effect.BeginPass(i);    renderUnit();   m_Effect.EndPass();  }  m_Effect.End();The call to renderunit has been altered internally so that it just cycles through the mesh's subsets and calls mesh.DrawSubset(n);I haven't used handles for the shader stuff yet as I just want to get it working first :)The whole of the above is called from my main rendering loop which includes the BeginScene, EndScene and device.Present calls. The main loop in my graphics engine normally makes three passes to accomodate volumetric shadows and reflections for the water, but for the purposes of testing shaders I have temporarily disabled this.I have also compared a working run in DxSaS vs my code in PIX and everything seems to be in order, with the exception that DxSaS seems to use render targets for its main rendering? - I only use them for rendering the reflective scene to texture - but this is disabled whilst I'm playing with shaders.When things are running through the fixed function pipeline everything appears fine and dandy. I decided to try to adopt shaders because they let one work at the pixel level which could have lots of advantages!I'm sure this is something simple I have missed, but so far I'm not seeing it! :)RegardsRobPhttp://AncientArmies.co.uk   ;Quote:It's all about render states (alpha, zbuffer,...). You either set them prior to effect.Begin() or have them coded in HLSL (not sure if all states can be coded in HLSL though).There has been some more progress. It seems that one of the shader effects included with nVidia's Dxsas demo actually works! This one is quite a complex shader and produces:The shader effect in question is called BumpLocalLight.fx.Looking at its code it appears to have a lot of renderstate flags over multiple passes - I guess some of these settings are allowing output in my game. Though this doesn't explain why the DxSas app can import one of my models and correctly apply all shaders to it. I have tried looking at the above DxSas to find out what they are doing, but they are making big use of semantics to automatically use the effects files with no specific hardcoding - this makes it difficult to see what they are really doing.RobPhttp://AncientArmies.co.uk   ;Quote:I'm sure this is something simple I have missed, but so far I'm not seeing it! :)I agree. So far I can't see anything conceptually going wrong either (yet). I just realized once it's a good idea to set ALL (*) renderstates prior to drawing, since you never know how they were set before your current draw call (other drawing routines of your app), or what the defaults were at startup.(*) well, at least all the ones you are going to change in your app. DirectX provides a recording mechanism to ease that, by the way.So make sure you explicitly disabled FFP functionality:- disable lighting- disable all texture stages- disable z-test (by the way: if you enable it, make sure zfunc is set, too)- disable alpha and fog (if still enabled)The suspicious "cyan" Color is (225, 255, 255), maybe you can find that value in your code (or any state).Set a breakpoint prior to your drawing and have a look at the render states, maybe you detect something suspicious (or even dump them so we can have a look at it, too).And since your familiar with PIX: You should be able to debug your shaders (if compiled with the appropriate flags), so you can see what's actually happening.Edit: PIX lets you dump render-states to a HTML-File. Maybe you can PIX DxSaS and see the difference.And: Did you manage to enable the debug runtime of DirectX ? These are always handy - honestly, this was one of the reason I switched to SlimDX, since I never managed to enable them on MDX :(Hope that helpsunbirdPS: I doubt this is the cause of your problem, but why do you define normals with a float4 ? Is the mesh defined this way ?[Edited by - unbird on May 28, 2010 12:07:43 AM];  Hi,Yes the mesh is defined with those floats.I have now found another puzzling piece of the puzzle (starting to get to learn PIX). In the screenshot below I created two basic effects, both transform the unit to screen space then one colours it red, the other yellow:The interesting thing is that in the drawing event, the shaders are both outputing exactly what they are supposed to be outputting - red and yellow respectively. However, the framebuffer seems to ignore this and resolutely stays at cyan!Now I have been looking through my code for Cyan and indeed in the engine a cyan fog is setup by default. I thought it could be this and disabled it, however, this has made no difference.I guess on the plus side, my effect's vertex and pixel shaders are working, its that the frame buffer refuses to acknowledge their outputs. The only thing this can be is as already mentioned, some kind of renderstate issue, but what?RobPhttp://AncientArmies.co.uk   ;  Thanks for that dump, maybe this helps.One thing catches my eye. The color is ignored, but the alpha actually matches (1.0 and 0.0 respectively). Though I don't know why you got a framebuffer with alpha. But anyway, if thats not just coincidence, smells like your D3DRS_COLORWRITEENABLE renderstate is only passing the alpha (D3DCOLORWRITEENABLE_ALPHA) instead of all channels (D3DCOLORWRITEENABLE_RED| D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | COLORWRITEENABLE_ALPHA).If it's still not that: I'm shooting in the dark from here. Can you dump the the states in PIX like mentioned, please ? Events->ContextMenu->View Device (the device at the draw call) then context menu on any state view to save all states. This will give a big HTML-file (400k) so you probably need to provide a download.