Shaders HLSL Question About Sampling and Float Summing


Hi all,

I've been messing around with HLSL and ran into some issues with sampling. Before I describe it all I already know how to get my test shader to do what I want it to do, but I'm extremely confused as to why it doesn't work when I try to do it a different way and would really like to know why as it will fill in some clearly missing gaps I have on how sampling works.

I have two textures that are each on their own texture page. One is just a blue rectangle, the other is just a red rectangle. And I want to take a sample from each, add the color values together, and get a purple rectangle. However, when I do this I get only the blue rectangle. And what's weird about this is that if I return only the float4 that was used to store the sample from the blue rectangle then I get exactly that; the blue rectangle. Same for the red one. So each float4 used to store the sample seems to be getting the correct color. But when adding the two float4's together it will not work. Shader code below.

struct PixelShaderInput {
    float4 vPosition : SV_POSITION;
    float4 vColor     : COLOR0;
    float2 vTexcoord : TEXCOORD0;

//declare the texture object.
Texture2D testTex2;

//declare the samplerstates
SamplerState testSample2;
SamplerState testSample3;

float4 main(PixelShaderInput INPUT) : SV_TARGET {
    //declare the float4's
    float4 BaseCol2 = 0;
    float4 BaseCol3 = 0;
    float4 BaseCol4 = 0;
    //do the samples of the two different textures
    BaseCol2 = testTex2.Sample(testSample2, INPUT.vTexcoord);
    BaseCol3 = testTex2.Sample(testSample3, INPUT.vTexcoord);
    //add the two floats (which ends up not working)
    BaseCol4 = BaseCol2 + BaseCol3;
    //return INPUT.vColor * BaseCol2; <-- if uncommented, this line returns the blue rectangle as expected
    //return INPUT.vColor * BaseCol3; <-- if uncommented, this line returns the red rectangle as expected
    return INPUT.vColor * BaseCol4; // <-- doesn't return the purple blended rectangle as expected, but rather the blue one.
I already know that if I declare a second texture object to use for taking the second sample, then the two float4's will sum together to make the desired purple rectangle, but I really need to know why it doesn't work as it's written now. Can anyone help?


This is just a guess, and probably not the right answer, but could it be because you are adding the alpha components together?
I'm afraid I'm not sure what you mean exactly? That when the two float4s are added together it's only adding their alphas and not the colors? Or did you mean something else?


It's adding everything RGBA. I'm wondering if adding the A could be causing strange results with whatever blending mode you're using.
I see. I changed the relevant code to what you see below, same result. Blue rectangle only.

BaseCol4.rgb = BaseCol2.rgb + BaseCol3.rgb;
BaseCol4.a = 1;


Have you tried using a different shader ide to see if the issue is with the code or with gms? Maybe try SHADERed, it's free. Debugging a shader in gms is a pain so I never recommend it.


Have you tried using a different shader ide to see if the issue is with the code or with gms? Maybe try SHADERed, it's free. Debugging a shader in gms is a pain so I never recommend it.
Oh, I didn't know about things like that. I'll try doing that, thanks!


Ok. I think maybe I've figured it out.
When declaring only one texture object to use for sampling, it gets stored in register 0 of the GPU, and can then only sample from whichever sampler gets assigned to register 0 first. So when using two SamplerStates, one of those SamplerStates gets assigned to register 0, and one gets assigned to register1. With the one getting assigned to register 1 not really usable, the texture object was actually sampling twice from the SamplerState in register 0.

The explanation relies on the assumption that a texture object in register 0 CAN NOT sample from a SamplerState that resides in a different register, but this does explain the problem and lines up with other testing I've done. So this seems like it's solved.