HLSL question.

I'm just wondering why this pixel shader works fine...

PS_OUTPUT RenderScenePS( VS_OUTPUT In, uniform bool bTexture )

{

PS_OUTPUT Output;

// Lookup mesh texture and modulate it with diffuse

if( bTexture )

{

float4 meshRGB = tex2D(MeshTextureSampler, In.TextureUV);

Output.RGBColor =meshRGB * In.Diffuse;

}

else

Output.RGBColor = In.Diffuse;

return Output;

}

... but this one crashes

PS_OUTPUT RenderScenePS( VS_OUTPUT In,

uniform bool bTexture )

{

PS_OUTPUT Output;

// Lookup mesh texture and modulate it with diffuse

if( bTexture )

{

float4 meshRGB = tex2D(MeshTextureSampler, In.TextureUV);

float4 secondRGB = tex2D(SecondTextureSampler, In.TextureUV);

float r = 0.5f* meshRGB.r + 0.5f * secondRGB.r;

float g = 0.5f* meshRGB.g + 0.5f * secondRGB.g;

float b = 0.5f* meshRGB.b + 0.5f * secondRGB.b;

float a = 0.5f* meshRGB.a + 0.5f * secondRGB.a;

float4 RGBA = float4(r,g,b,a);

Output.RGBColor = RGBA * In.Diffuse;

}

else

Output.RGBColor = In.Diffuse;

return Output;

}

There is nothing wrong with the second texture sampler as I can get that to work fine as well. The line that is causing the problem is

Output.RGBColor = RGBA * In.Diffuse;

Any help would be appreciated.



Answer this question

HLSL question.

  • Netmaker

    It worked! Thanks again for the help Ralph.


  • umanwizard

    I believe I know the problem. But first I want to give you a little tip. Nearly every loading function has an overloaded version that can give you an error message as string. If your fx file could not loaded you should check this error message.

    But now back to your shader. The problem is that you use the ps_1_1 profile. If you use this profile you cannot use the same texture coordinate to read from two textures. You need to add a second one to the VS_OUTPUT struct:

    struct VS_OUTPUT

    {

    float4 Position : POSITION; // vertex position

    float2 TextureUV1 : TEXCOORD0; // vertex texture coords

    float2 TextureUV2 : TEXCOORD1; // vertex texture coords

    float4 Diffuse : COLOR0; // vertex diffuse color (note that COLOR0 is clamped from 0..1)

    };

    Update the vertex shader code that it writes the second coordinate:

    if( bTexture )

    {

    Output.TextureUV1 = vTexCoord0;

    Output.TextureUV2 = vTexCoord0;

    }

    else

    {

    Output.TextureUV1 = 0;

    Output.TextureUV2 = 0;

    }

    Update the pixel shader that it use the second coordinate:

    float4 meshRGB = tex2D(MeshTextureSampler, In.TextureUV1);

    float4 secondRGB = tex2D(SecondTextureSampler, In.TextureUV2);

    After this you will face a final problem. The compiler is not smart engough to optimize this within the instruction limit of ps 1.1:

    float r = 0.5f* meshRGB.r + 0.5f * secondRGB.r;

    float g = 0.5f* meshRGB.g + 0.5f * secondRGB.g;

    float b = 0.5f* meshRGB.b + 0.5f * secondRGB.b;

    float a = 0.5f* meshRGB.a + 0.5f * secondRGB.a;

    float4 RGBA = float4(r,g,b,a);

    Replace it with this code:

    float4 RGBA = 0.5f* meshRGB + 0.5f * secondRGB;

    HLSL supports the multiplication from a vector and a scalar. You don’t need to do it for every color channel by your own.

    The reason why it works if you replace the line is simple. In both cases you will only use one texture and the second one is removed during optimization.



  • StevenDH

    Yes, using ps_1_4 or higher should work fine with only one coordinate. But it will limited the amount of hardware this shader will work. To be more specific it will not longer run on GeForce3, GeForce4 TI, Xabre and Parhelia if you move to 1.4.



  • mech3

    Thanks alot Ralph. I'll give this a try and report back to you. I really appreciate the detail of the help.

    Are you suggeting that later profiles are capable of using just the one texture coordinate

    Cheers.


  • kogkog

    Fx files are not checked during the compilation of your C# code. They are checked during loading (the FromFile call). In the case something is wrong with this file you will get an exception. If you don’t handle it your program will “crash”. You should add some exception handling (try; catch) around your D3D code at least at places were you load external data.

     

    The profile is selected as part of the compile “instruction” in your fx file.

     

    technique RenderSceneWithTexture1Light

    {

        pass P0

        {          

            VertexShader = compile vs_1_1 RenderSceneVS( 1, true, true );

            PixelShader   = compile ps_1_1 RenderScenePS( true ); // trivial pixel shader (could use FF instead if desired)

        }

    }

     

    In this example from BasicHLSL it use the vs_1_1 profile for the vertex shader and ps_1_1 for the pixel shader. Do you use the same profiles in your fx file

     

    Edit: You say that you have modified the BasicHLSL sample. Have you add the second sampler you use in your code to the fx file < xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

     

    Something like this:

     

    texture g_SecondTexture;

     

    sampler SecondTextureSampler =

    sampler_state

    {

        Texture = <g_SecondTexture>;

        MipFilter = LINEAR;

        MinFilter = LINEAR;

        MagFilter = LINEAR;

    };

     



  • UmaMohan

    Can you please give some more details

    -What do you mean with crash Doesn’t compile Wrong results

    -Which profile do you use for this shader



  • johnfi

    Thanks for responding Ralph. First I'll just state that I'm very new to HLSL. It compiles ok. I'm compiling it as an effect file using a modification of the basicHLSL sample. It always seems to compile regardless of mistakes I might make, I'm not sure if there's a compiler setting or something that I'm missing. I don't get any of the checking on my fx file that goes on with normal .cs files; I'm not sure if this is normal or not.

    By Crash I mean that I get a message that reads:

    -217467259 (E_FAIL) at microsoft.DirectX.Direct3d.Effect.FromFile(..etc...)....

    I always get something like this if I've written something daft in my fx file, since, like I said it always compiles regardless.

    I'm not quite sure what you mean by the last part of your post but I've used the basicHLSL code except for the changes to the pixel shader. I'm playing around trying to learn, seeing if I can mix two textures together.

    I hope this clarifies the situation.


  • Benjy

    Yes I'm using vs_1_1 and ps_1_1.

    It runs as expected if I replace the line

    Output.RGBColor = RGBA * In.Diffuse;

    with

    Output.RGBColor = meshRGB * In.Diffuse;

    or

    Output.RGBColor = secondRGB * In.Diffuse;

    What I don't understand is that RGBA is also a float4 just like meshRGB or secondRGB so why won't it accept this

    My idea was to combine the color values of the two textures and then output that instead of the color of just one of the textures.


  • HLSL question.