0
\$\begingroup\$

I'm currently converting an app from XNA to SharpDx and I'm therefore upgrading my shaders to version 4 (vs_4_0/ps_4_0).

When using this sampler:

SamplerState MySampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    MinFilter = Anisotropic;
    MagFilter = Anisotropic;
    MipFilter = Linear;
    AddressU = Wrap;
    AddressV = Wrap;
};

Like this:

float3 color = DiffuseColor * Texture.Sample(MySampler, input.UV.x);

I get clamping instead of wrapping.

If I write the code like this:

    float3 color = DiffuseColor * Texture.Sample(MySampler,
        float2(frac(input.UV.x),frac(input.UV.y)));

Then I do get proper wrapping - but I'd like to declare that in the sampler insted, so what am I doing wrong?

Full source code:

float4x4 World;
float4x4 View;
float4x4 Projection;
float3 CameraPosition;
float4 ClipPlane;
float3 LightingDirection = float3(-10, 20, 5);

bool DoShadowMapping = false;
float4x4 ShadowViewProjection;
float ShadowMult = 0.3f;
float ShadowBias = 0.001f;
texture2D ShadowMap;
sampler2D shadowSampler = sampler_state {
    texture = <ShadowMap>;
    minfilter = point;
    magfilter = point;
    mipfilter = point;
};

Texture2D Texture;

SamplerState MySampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    MinFilter = Anisotropic; // Minification Filter
    MagFilter = Anisotropic; // Magnification Filter
    MipFilter = Linear; // Mip-mapping
    AddressU = Wrap;
    AddressV = Wrap;
};

float3 DiffuseColor = float3(1, 1, 1);
float3 AmbientColor = float3(0.4, 0.4, 0.4);
float3 LightColor = float3(0.8, 0.8, 0.8);
float SpecularPower = 32;
float3 SpecularColor = float3(1, 1, 1);

struct VertexShaderInput
{
    float4 Position : SV_Position;
    float2 UV : TEXCOORD0;
    float3 Normal : NORMAL0;
};

struct VertexShaderOutput
{
    float4 Position : SV_Position;
    float2 UV : TEXCOORD0;
    float3 Normal : TEXCOORD1;
    float3 ViewDirection : TEXCOORD2;
    float3 WorldPosition : TEXCOORD3;
    float4 ShadowScreenPosition : TEXCOORD4;
    float4 PositionCopy  : TEXCOORD5;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output = (VertexShaderOutput)0;

    float4 worldPosition = mul(input.Position, World);
    float4x4 viewProjection = mul(View, Projection);

    output.WorldPosition = worldPosition;
    output.Position = output.PositionCopy = mul(worldPosition, viewProjection);

    output.UV = input.UV;
    output.Normal = mul(input.Normal, World);
    output.ViewDirection = worldPosition - CameraPosition;
    output.ShadowScreenPosition = mul(worldPosition, ShadowViewProjection);

    return output;
}

float2 sampleShadowMap(float2 UV)
{
    if (UV.x < 0 || UV.x > 1 || UV.y < 0 || UV.y > 1)
        return float2(1, 1);
    return ShadowMap.Sample(MySampler, UV).rg;
}

float4 PixelShaderFunction(VertexShaderOutput input) : SV_Target
{
    // Start with diffuse color
    float3 color = DiffuseColor * Texture.Sample(MySampler, float2(frac(input.UV.x),frac(input.UV.y)));

    // Start with ambient lighting
    float3 lighting = AmbientColor;

    float3 normal = normalize(input.Normal);

    // Add lambertian lighting
    lighting += saturate(dot(-LightingDirection, normal)) * LightColor;

    float3 refl = reflect(-LightingDirection, normal);
    float3 view = normalize(input.ViewDirection);

    // Add specular highlights
    lighting += pow(saturate(dot(refl, view)), SpecularPower) * SpecularColor;

    if (DoShadowMapping)
    {
        float realDepth = input.ShadowScreenPosition.z / input.ShadowScreenPosition.w - ShadowBias;

        if (realDepth < 1)
        {
            // Sample from depth texture
            float2 screenPos = input.ShadowScreenPosition.xy / input.ShadowScreenPosition.w;
            float2 shadowTexCoord = 0.5f * (float2(screenPos.x, -screenPos.y) + 1);

            float2 moments = sampleShadowMap(shadowTexCoord);

            // Check if we're in shadow
            float lit_factor = (realDepth <= moments.x);

            // Variance shadow mapping
            float E_x2 = moments.y;
            float Ex_2 = moments.x * moments.x;
            float variance = min(max(E_x2 - Ex_2, 0.0) + 1.0f / 10000.0f, 1.0);
            float m_d = (moments.x - realDepth);
            float p = variance / (variance + m_d * m_d);

            lighting *= clamp(max(lit_factor, p), ShadowMult, 1.0f);
        }
    }

    // Calculate final color
    float3 output = saturate(lighting) * color;

    return float4(output, 1);
}


float4 PixelShaderFunctionClipPlane(VertexShaderOutput input) : SV_Target
{
    clip(dot(float4(input.WorldPosition,1), ClipPlane));
    return PixelShaderFunction(input);
}


float4 PixelShaderFunctionDepthMap(VertexShaderOutput input) : SV_Target
{
    // Determine the depth of this vertex / by the far plane distance,
    // limited to [0, 1]
    float depth = clamp(input.PositionCopy.z / input.PositionCopy.w, 0, 1);

    // Return only the depth value
    return float4(depth, depth * depth, 0, 1);
}


technique TechStandard
{
    pass Pass1
    {
        SetGeometryShader(0);
        SetVertexShader(CompileShader(vs_4_0, VertexShaderFunction()));
        SetPixelShader(CompileShader(ps_4_0, PixelShaderFunction()));
    }
}

technique TechClipPlane
{
    pass Pass1
    {
        SetGeometryShader(0);
        SetVertexShader(CompileShader(vs_4_0, VertexShaderFunction()));
        SetPixelShader(CompileShader(ps_4_0, PixelShaderFunctionClipPlane()));
    }
}

technique TechDepthMap
{
    pass Pass1
    {
        SetGeometryShader(0);
        SetVertexShader(CompileShader(vs_4_0, VertexShaderFunction()));
        SetPixelShader(CompileShader(ps_4_0, PixelShaderFunctionDepthMap()));
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ How are you compiling this shader? Note that if you are using inline declaration of SamplerState like this, you need to compile an effect (fx_4_0) and use Effects framework (with pass/techniques). Is it the case? Have you tried a graphics debugger (NSight, PerfStudio, GPA...etc.) to check the sampler state is correctly setup? \$\endgroup\$ – xoofx Aug 1 '14 at 12:06
  • \$\begingroup\$ I compile it by setting the BuildAction property to "ToolkitFxc" in Visual Studio. I have no idea about the debuggers you're reffering to... \$\endgroup\$ – danbystrom Aug 1 '14 at 14:06
2
\$\begingroup\$

Unfortunately, the toolkit doesn't support inline definition of sampler in the shader (as legacy fx does). In order to use a sampler, you need to:

  1. Simply declare a plain sampler state in hlsl: SamplerState MySampler;
  2. Pass a sampler state from C# available in GraphicsDevice.BlendStates (or create your own) and set it on the parameter effect.Parameters["MySampler"]

Try to master a Graphics Debugger (Visual Studio 2012/2013 is also coming an integrated Graphics Debugger, but if you have a NVidia card, prefer using NSight - or any other HW specialized debugger) as you will be able to see exactly what is going on on the GPU, which resource is bound, what is inside your constant buffers, what is on each render target/texture...etc. It is often helping a lot to quickly spot this kind of issues.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks. That would have been hard for me to figure out by myself! Would you say that the the toolkit is a bad move? It just looked like the easiest way, coming from XNA... \$\endgroup\$ – danbystrom Aug 2 '14 at 16:35
  • \$\begingroup\$ The Toolkit gives a feel of XNA, but it is unfortunately not at the level of features/quality of XNA (the toolkit doesn't have a real content pipeline, poor documentation...etc.). But it is still worth using it when you want to quickly prototypes things in Direct3D11 as using raw Direct3D11 is more laborious. \$\endgroup\$ – xoofx Aug 3 '14 at 2:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.