HLSL 3 Can a Pixel Shader be declared alone?

江枫思渺然 提交于 2019-12-01 21:11:25

The problem is that the built-in SpriteBatch shader is 2.0. If you specify a pixel shader only, SpriteBatch still uses its built-in vertex shader. Hence the version mismatch.

The solution, then, is to also specify a vertex shader yourself. Fortunately Microsoft provides the source to XNA's built-in shaders. All it involves is a matrix transformation. Here's the code, modified so you can use it directly:

float4x4 MatrixTransform;

void SpriteVertexShader(inout float4 color    : COLOR0,
                        inout float2 texCoord : TEXCOORD0,
                        inout float4 position : SV_Position)
{
    position = mul(position, MatrixTransform);
}

And then - because SpriteBatch won't set it for you - setting your effect's MatrixTransform correctly. It's a simple projection of "client" space (source from this blog post). Here's the code:

Matrix projection = Matrix.CreateOrthographicOffCenter(0, 
        GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, 1);
Matrix halfPixelOffset = Matrix.CreateTranslation(-0.5f, -0.5f, 0);
effect.Parameters["MatrixTransform"].SetValue(halfPixelOffset * projection);

You can try the simple examples here. The greyscale shader is a very good example to understand how a minimal pixel shader works.

Basically, you create a Effect under your content project like this one:

sampler s0;

float4 PixelShaderFunction(float2 coords: TEXCOORD0) : COLOR0
{
    // B/N
    //float4 color = tex2D(s0, coords);
    //color.gb = color.r;

    // Transparent
    float4 color = tex2D(s0, coords);
    return color;
}

technique Technique1
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

You also need to:

  1. Create an Effect object and load its content.

    ambienceEffect = Content.Load("Effects/Ambient");

  2. Call your SpriteBatch.Begin() method passing the Effect object you want to use

    spriteBatch.Begin( SpriteSortMode.FrontToBack, BlendState.AlphaBlend, null, null, null, ambienceEffect, camera2d.GetTransformation());

  3. Inside the SpriteBatch.Begin() - SpriteBatch.End() block, you must call the Technique inside the Effect

    ambienceEffect.CurrentTechnique.Passes[0].Apply();

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!