0

I'm new to building graphics engines and kinda stumped on a particular issue.

I have an issue getting pixel shaders to work using the same set of parameters for both. Causing me to have to create 2 different techniques for each method. If I try to use the same parameters for both, one of them will just return nothing.

My goal is to only use one set of parameters for the shader, eliminating the sprite specific version of each technique I use.

Here is what I currently have to do:

HLSL Pixel Shader

Texture2D Texture : register(t0);
SamplerState TextureSampler : register(s0);
Texture2D TextureAlpha;

cbuffer ProjectionMatrix : register(b0)
{
    row_major float4x4 MatrixTransform : packoffset(c0);
};

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

//Method required for using DrawQuad
float4 PS(
    float2 tex : TEXCOORD0
    ) : SV_TARGET
{
    float3 tcolor = Texture.Sample(TextureSampler, tex).rgb * TextureAlpha.Sample(TextureSampler, tex).a;
    float alpha = TextureAlpha.Sample(TextureSampler, tex).a * Texture.Sample(TextureSampler, tex);

    return float4(tcolor, alpha);
}

//Method required for using in SpriteBatches
float4 PSSprite(
    float4 color    : COLOR0,
    float2 tex : TEXCOORD0
    ) : SV_TARGET
{
    return PS(tex);
}

technique MaskSprite
{
    pass
    {
        Profile = 9.3;
        //Sprite's also require the VS to be set as well.
        VertexShader = compile vs_4_0_level_9_1 VS();
        PixelShader = compile ps_4_0_level_9_1 PSSprite();
    }
}

technique Mask
{
    pass
    {
        Profile = 9.3;
        PixelShader = compile ps_4_0_level_9_1 PS();
    }
}

LoadContent() Code

protected override void LoadContent()
{
    //...  
      
    //render target to mask
    var backDesc = GraphicsDevice.BackBuffer.Description;
    renderTargetMask = ToDisposeContent(RenderTarget2D.New(GraphicsDevice, backDesc.Width, backDesc.Height, 1, backDesc.Format));

    //sprite batch initialization
    spriteBatch = ToDisposeContent(new SpriteBatch(GraphicsDevice));

    //load in fx and textures 
    ballsTexture = Content.Load<Texture2D>("Balls");
    alphaMapTexture= Content.Load<Texture2D>("AlphaMap");
    maskEffect = Content.Load<Effect>("Mask");

    //...
}

SpriteBatch Code

protected override void Draw(GameTime gameTime)
{
    //...
    maskEffect.CurrentTechnique = bloomEffect.Techniques["MaskSprite"];
    maskEffect.Parameters["Destination"].SetResource(alphaMapTexture); //Texture2D

    spriteBatch.Begin(
                    SpriteSortMode.Deferred, 
                    GraphicsDevice.BlendStates.NonPremultiplied, 
                    null, null, null, maskEffect);

    spriteBatch.Draw(
                    ballsTexture, //Texture2D
                    new Vector2(10, 10),
                    new Rectangle(0, 0, ballsDestTexture.Width, ballsDestTexture.Height),
                    Color.White,
                    0.0f,
                    new Vector2(0, 0),
                    Vector2.One,
                    SpriteEffects.None,
                    0f);
    
    spriteBatch.End();
    //...
}

Draw Quad Code

protected override void Draw(GameTime gameTime)
{
    //Draw stuff to renderTargetMask

    //...
    maskEffect.CurrentTechnique = maskEffect.Techniques["Mask"];
    maskEffect.Parameters["Texture"].SetResource(renderTargetMask);
    maskEffect.Parameters["TextureAlpha"].SetResource(ballsDestTexture);
    maskEffect.Parameters["TextureSampler"]
            .SetResource(GraphicsDevice.SamplerStates.PointClamp);
    var pQuad = new PrimitiveQuad(GraphicsDevice);
    pQuad.Draw(maskEffect.CurrentTechnique.Passes[0]);
    //...
}
Community
  • 1
  • 1
corylulu
  • 3,449
  • 1
  • 19
  • 35
  • Why don't you use the same technique for both? `Mask` with `PS` would be sufficient. The vertex declaration can have more attributes than are actually used by the shader. – Nico Schertler Jun 03 '14 at 21:51
  • Oh, I guess I didn't mention why I was having to do this. If I use either `Mask` in the SpriteBatch or `MaskSprite` in the DrawQuad, nothing shows up. Just returns nothing. – corylulu Jun 03 '14 at 21:54
  • Strange. Are there any error messages? Which version of DX do you use? – Nico Schertler Jun 03 '14 at 21:59
  • Oh, I also just realized the Sprite batch requires both the VS and PS. (I edit the code to reflect that) It's using DX11 using the SharpDX Toolkit – corylulu Jun 03 '14 at 22:03
  • In DX11 you have to create an input layout for each vertex type and effect pass you use. So here you would need two input layouts. One for the normal vertex (with just the tex coords) and one for the sprite batch vertex (with additional color). Both input layouts work on the `Mask` technique. Is this something you have done or is this handled by SharpDX internally (haven't done much with SharpDX yet)? If it's handled internally, this might be something that is not considered. – Nico Schertler Jun 03 '14 at 22:06
  • I have just screwed around with this until I got something working and ended up with this. No idea what I'm actually doing. But yeah, I wrote the shader (if that's what you're asking), it wasn't something premade in a SharpDX example. I don't know why neither of them will work with each others techniques though. I was hoping there was some way I could check for parameters in the technique's pass and adjust accordingly, or simple modify my code so that the color parameter was included in both. – corylulu Jun 03 '14 at 22:14
  • Oh, and no, there is no exception thrown. That only occurs if I don't have a VS included with the sprite technique. – corylulu Jun 03 '14 at 22:19
  • So do you set an input layout somewhere? This is necessary to draw something. I was asking if you do it explicitly or if SharpDX handles that for you. – Nico Schertler Jun 03 '14 at 22:30
  • No, I guess I'm wondering how I would go about doing that... I assume its on the code side rather than within the shader... Currently, a majority of this stuff is a little voodoo-ish to me... – corylulu Jun 03 '14 at 23:42
  • Yes, on the code side. Create an [InputLayout](http://sharpdx.org/documentation/api/m-sharpdx-direct3d11-inputlayout--ctor-1) providing the shader byte code and set it in `DeviceContext.InputAssembler.InputLayout`. – Nico Schertler Jun 04 '14 at 07:43
  • I ended up downloading the source to figure out what was going on and found where it was setting the InputLayout for the PrimitiveQuad, but even when changing it to include the color parameter, it still did not work. Tried the other way around as well with no success. Here is the source: https://github.com/sharpdx/SharpDX/blob/36e5bd9c4c8dd9beb6af7a6718293483b6376664/Source/Toolkit/SharpDX.Toolkit.Graphics/PrimitiveQuad.cs – corylulu Jun 04 '14 at 21:32

0 Answers0