4

I am really stuck on this one. My HLSL for rendering point sprites with texture coordinates for a sprite sheet works fine on all ATI cards but not on any NVIDIA cards. On NVIDIA cards the passed texture coordinates map to the whole sprite sheet rather than a portion of it. Strange but it works fine on ATI cards. Am I missing something unique to ATI cards?

Here is my shader

struct VS_INPUT
{
        float4 Position   : POSITION;
        float4 Color      : COLOR;
        float4 Texture    : TEXCOORD0;
    //float1 Psize    : PSIZE0;
};


struct VS_OUTPUT
{
        float4 Position   : POSITION;
        float4 Color      : COLOR;
        float2 Texture    : TEXCOORD0;
        float2 Texture_zw : TEXCOORD1;
    float1 Psize      : PSIZE;
};



float4x4 WorldViewProj;
texture Tex <string name = "sprite_coin_test.dds";>;
sampler2D s_2D;
float offset_x=0.0;
float offset_y=0.0;


sampler S0 = sampler_state
{
    Texture = (Tex);
    MinFilter = ANISOTROPIC; //LINEAR;
    MagFilter = ANISOTROPIC; //LINEAR;
    MipFilter = LINEAR;
};


VS_OUTPUT vs_main( in VS_INPUT In )
{
    VS_OUTPUT Out=(VS_OUTPUT)0;                      //create an output vertex

    Out.Position = mul(In.Position, WorldViewProj);  //apply vertex transformation
    Out.Texture  = In.Texture;
        Out.Texture_zw = float2(In.Texture.z, In.Texture.w);
        Out.Color    = In.Color;
    //Out.Psize    = In.Psize;
    Out.Psize=(Out.Position.z)*10.0;
        return Out;                         //return output vertex
}

float4 PS_Particle_main(float2 vPos: TEXCOORD0, float2 text_zw: TEXCOORD1) : COLOR 
{   
        vPos.x*=offset_x;
        vPos.y*=offset_y;

        vPos += float2(text_zw[0], text_zw[1]);    

        return tex2D(s_2D, vPos);
}

technique RenderVS
{   
    pass p0   
    {       
        AlphaBlendEnable        = true;     
        AlphaTestEnable     = false;        
        SrcBlend            = SRCALPHA;     
        DestBlend           = INVSRCALPHA;  

        POINTSPRITEENABLE       = true;     
        POINTSCALEENABLE        = true;
              POINTSIZE_MIN     = 1.0f;     
        POINTSIZE_MAX       = 400.0f;           
                    POINTSCALE_A        = 1.0f;
        POINTSCALE_B        = 1.0f;
        POINTSCALE_C        = 1.0f;
        ZWRITEENABLE        = false;

        Sampler[0]      = (S0);


        VertexShader = compile vs_1_1 vs_main();
        PixelShader = compile ps_2_0 PS_Particle_main();        

    }
}
ste
  • 41
  • 2

1 Answers1

1

I had the same problem for a while and it costed me a lot of time. I have not found any documentation about this problematic, but with testing on ATI and NVIDIA devices I found the difference. With pointsprites ATI works all fine, it interpolates the texturecoordinates properly into TEXCOORD0. In contrast NVIDIA does nearly the same, but they write the texturecoordinates in all fields with a TEXCOORD-interpolator. So all information which you pass by texturecoordinates to the pixelshader will be overwritten. I solved this by using a COLOR-interpolator instead of a TEXCOORD-interpolator. Very strange, but it works fine for me :) In your case it would be:

struct VS_OUTPUT
{
    float4 Position   : POSITION;
    float4 Color      : COLOR0;
    float2 Texture    : TEXCOORD0;
    float2 Texture_zw : COLOR1;
    float1 Psize      : PSIZE;
};
Gnietschow
  • 3,070
  • 1
  • 18
  • 28
  • This same behavior seems to apply to Intel GPUs as well. At least on the HD 4000 which I've tested personally. The COLOR interpolator work-around works on these devices as well. – eodabash Jul 19 '14 at 16:26