I'm creating an image editor for Windows Phone 8 / Windows 8 using SharpDX api and trying to apply a custom effect (SharpDX.Toolkit.Graphics.Effect) to a WriteableBitmap.
The effect itself is applied, but the result looks strange. Seems to me that the texture was reduced and inverted.
The code to apply the effect is written below.
private void ApplyEffect()
{
GraphicsDevice graphicsDevice = GraphicsDevice.New();
RenderTarget2D renderTarget = RenderTarget2D.New( graphicsDevice, _originalBitmap.PixelWidth, _originalBitmap.PixelHeight, PixelFormat.B8G8R8A8.UNorm );
Texture2D texture = Texture2D.New( graphicsDevice, _originalBitmap.PixelWidth, _originalBitmap.PixelHeight, PixelFormat.B8G8R8A8.UNorm );
texture.SetData<int>( _originalBitmap.Pixels );
Effect effect = new Effect( graphicsDevice, SimpleEffectTest.Effects.Invert.EffectBytecode );
graphicsDevice.SetRenderTargets( renderTarget );
SpriteBatch spriteBatch = new SpriteBatch( graphicsDevice );
spriteBatch.Begin( SpriteSortMode.Deferred, effect );
spriteBatch.Draw( texture, Vector2.Zero, Color.White );
spriteBatch.End();
renderTarget.GetData<int>( _resultBitmap.Pixels );
}
Do you know what I'm doing wrong here?
SimpleEffectTest project
Best regards,
Pieter Voloshyn
---- UPDATE ----
After many tests I finally found what I did wrong. I changed the main pixel shader function parameters.
From
float4 PS(
float4 pos : SV_POSITION,
float4 posScene : SCENE_POSITION,
float2 texCoord : TEXCOORD0
) : SV_TARGET0
To
float4 PS(
float4 color : COLOR0,
float2 texCoord : TEXCOORD0
) : SV_Target
Thanks!
Related
I think I am very stupid because I can't figure out what causes the issue in this simplest case.
Project type is Windows OpenGL (on Android the issue also persists).
Here is the shader:
//----------------------------------------------------------------------------
float4 PSTest (float2 TexCoords : TEXCOORD0) : COLOR0
{
float4 color = float4 (1, 0, 0, 1);
return color;
}
//----------------------------------------------------------------------------
Technique Test
{
pass Test
{
PixelShader = compile ps_2_0 PSTest();
}
}
It works fine if I draw it to the screen with the Texture (128x128):
Shader.CurrentTechnique = Shader.Techniques["Test"];
GraphicsDevice.SetRenderTarget (null);
GraphicsDevice.Clear (Color.White);
Batch.Begin (SpriteSortMode.Immediate, BlendState.Opaque,
SamplerState.PointClamp, DepthStencilState.None, null, Shader);
Batch.Draw (Texture, Vector2.Zero, Color.White);
Batch.End();
Now I decide to draw it into render target Output created by code:
new RenderTarget2D (GraphicsDevice, 256, 256, false,
SurfaceFormat.Color, DepthFormat.None);
Draw code:
// Render into Output
Shader.CurrentTechnique = Shader.Techniques["Test"];
GraphicsDevice.SetRenderTarget (Output);
GraphicsDevice.Clear (Color.DimGray);
Batch.Begin (SpriteSortMode.Immediate, BlendState.Opaque,
SamplerState.PointClamp, DepthStencilState.None, null, Shader);
Batch.Draw (Texture, Vector2.Zero, Color.White);
Batch.End();
// Draw Output
GraphicsDevice.SetRenderTarget (null);
GraphicsDevice.Clear (Color.White);
Batch.Begin();
Batch.Draw (Output, Vector2.Zero, Color.White);
Batch.End();
But the result is totally absurd:
I have tried different simplest shaders, SurfaceFormat.HdrBlendable, texture sizes - but nothing helps.
Also I have tried to draw Texture (filled with violet) into render target without shader (then to the screen) and it works fine.
It seems like I have missed some basics thing about shaders in XNA but I can't figure out what it is.
Here is the solution: https://monogame.codeplex.com/discussions/530086. The reason is in the shader's input parameters.
The sample
If you watch the code, I'm interested in refraction.fx, and in void DrawRefractGlacier(GameTime gameTime) function. Here you can notice that the function uses a texture to render water distortion on an image (waterfall.jpg as "distorter image", and glacier.jpg as distorted image).
If you read inside refraction.fx, at the beginning it says:
// Effect uses a scrolling displacement texture to offset the position of the main
// texture. Depending on the contents of the displacement texture, this can give a
// wide range of refraction, rippling, warping, and swirling type effects.
It seems that would be easy to achieve another effect by changing the image. I tried that with an image like this:
I want to achieve the effect of distorting everything around as a rotating whirl, or a spiral. How can I do that?
Some simple sequential screen of how it looks with my texture:
Refraction shader:
// Effect uses a scrolling displacement texture to offset the position of the main
// texture. Depending on the contents of the displacement texture, this can give a
// wide range of refraction, rippling, warping, and swirling type effects.
float2 DisplacementScroll;
float2 angle;
sampler TextureSampler : register(s0);
sampler DisplacementSampler : register(s1);
float2x2 RotationMatrix(float rotation)
{
float c = cos(rotation);
float s = sin(rotation);
return float2x2(c, -s, s ,c);
}
float4 main(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
float2 rotated_texcoord = texCoord;
rotated_texcoord -= float2(0.25, 0.25);
rotated_texcoord = mul(rotated_texcoord, RotationMatrix(angle));
rotated_texcoord += float2(0.25, 0.25);
float2 DispScroll = DisplacementScroll;
// Look up the displacement amount.
float2 displacement = tex2D(DisplacementSampler, DispScroll+ texCoord / 3);
// Offset the main texture coordinates.
texCoord += displacement * 0.2 - 0.15;
// Look up into the main texture.
return tex2D(TextureSampler, texCoord) * color;
}
technique Refraction
{
pass Pass1
{
PixelShader = compile ps_2_0 main();
}
}
Its draw call:
void DrawRefractGlacier(GameTime gameTime)
{
// Set an effect parameter to make the
// displacement texture scroll in a giant circle.
refractionEffect.Parameters["DisplacementScroll"].SetValue(
MoveInCircle(gameTime, 0.2f));
// Set the displacement texture.
graphics.GraphicsDevice.Textures[1] = waterfallTexture;
// Begin the sprite batch.
spriteBatch.Begin(0, null, null, null, null, refractionEffect);
// Because the effect will displace the texture coordinates before
// sampling the main texture, the coordinates could sometimes go right
// off the edges of the texture, which looks ugly. To prevent this, we
// adjust our sprite source region to leave a little border around the
// edge of the texture. The displacement effect will then just move the
// texture coordinates into this border region, without ever hitting
// the edge of the texture.
Rectangle croppedGlacier = new Rectangle(32, 32,
glacierTexture.Width - 64,
glacierTexture.Height - 64);
spriteBatch.Draw(glacierTexture,
GraphicsDevice.Viewport.Bounds,
croppedGlacier,
Color.White);
// End the sprite batch.
spriteBatch.End();
}
i got 2 dynamic texture ,and want add second texture color to first texture color But just where first texture color alpha is not 0
something like inverse transparncey
i add two pic link to show what is my mean:
TO
just collisions part must add two texture pixel color
ty for your help
Maybe using BlendState.Additive wil be enough for you.
or maybe it can be achieved with a custom BlendState.. but I have not experience with this...
or you can make a shader, you should note that you have to quads:
Quad with a rag doll. (Qrd)
Quad with a circle. (Qc)
you draw Qc over Qrd...
so you have to traduce the texture coordinates that you get in the pixel shader that owns to Qc to texture cordinates at Qrd space...
then you sample the color from Qrd texture,
and if alpha is near zero you clip the pixel...
else you return the sample from Qrc texture
just did it , works great
sampler circleSampler : register(s1);
sampler playerSampler : register(s0);
float4 main(float4 color : COLOR0 ,float2 texCoord : TEXCOORD0):COLOR0
{
float4 output = float4(1,1,1,1);
float4 CircColor = tex2D(circleSampler,texCoord);
float4 playerColor = tex2D(playerSampler,texCoord);
if (CircColor.a ==0)
{
output = playerColor;
}
else
{
output = CircColor* playerColor;
}
output.a = playerColor.a;
return output;
}
technique Technique1
{
pass Pass1
{
PixelShader = compile ps_2_0 main();
}
}
anyway ty for ur time
I have a custom template, and I want to somehow take the output of ContentPresenter (imagine it as a bitmap), now strip RGB from that bitmap (so only alpha channel remains), and then set RGB on every pixel to white (preserve alpha channel). So how would you do that?
I'd use a PixelShader + Effect on the ContentPresenter if it needs to be a 'live' effect.
See the Shazzam tool to easily create the sources for the effect and the PixelShader.
sampler2D Texture1Sampler : register(S0);
//-----------------
// Pixel Shader
//-----------------
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D( Texture1Sampler, uv );
float4 alphaMaskColor = float4(color.a,color.a,color.a,color.a); //Pre-multiplied Alpha in WPF
return alphaMaskColor;
}
Trying to make a glow effect in xna but it doesn't show the glow or any change at all. Also my back color is purple instead of black and I can't change that either :
GraphicsDevice.Clear(Color.Black);
GraphicsDevice.SetRenderTarget(bulletRenderTarget);
spriteBatch.Begin();
foreach (Bullet bullet in bulletList)
{
Texture2D bulletTexture = textures[bullet.bulletType];
spriteBatch.Draw(
bulletTexture,
new Rectangle(
(int)bullet.position.X,
(int)bullet.position.Y,
bulletTexture.Width,
bulletTexture.Height
),
null,
Color.White,
MathHelper.ToRadians(bullet.angle),
new Vector2(
bulletTexture.Width / 2,
bulletTexture.Height / 2
),
SpriteEffects.None,
0
);
}
spriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.Black);
postProcessEffect.CurrentTechnique = postProcessEffect.Techniques["Blur"];
spriteBatch.Begin();
spriteBatch.Draw(
bulletRenderTarget,
new Vector2(0, 0),
Color.White
);
GraphicsDevice.BlendState = BlendState.Additive;
foreach (EffectPass pass in postProcessEffect.CurrentTechnique.Passes)
{
pass.Apply();
spriteBatch.Draw(
bulletRenderTarget,
new Vector2(0,0),
Color.White
);
}
DrawHud();
foreach (BaseEntity entity in entityList)
{
entity.Draw(gameTime);
}
spriteBatch.End();
I'm only trying to get the bullets to glow.
shader :
float BlurDistance = 0.002f;
sampler ColorMapSampler : register(s1);
float4 PixelShaderFunction(float2 Tex: TEXCOORD0) : COLOR
{
float4 Color;
// Get the texel from ColorMapSampler using a modified texture coordinate. This
// gets the texels at the neighbour texels and adds it to Color.
Color = tex2D( ColorMapSampler, float2(Tex.x+BlurDistance, Tex.y+BlurDistance));
Color += tex2D( ColorMapSampler, float2(Tex.x-BlurDistance, Tex.y-BlurDistance));
Color += tex2D( ColorMapSampler, float2(Tex.x+BlurDistance, Tex.y-BlurDistance));
Color += tex2D( ColorMapSampler, float2(Tex.x-BlurDistance, Tex.y+BlurDistance));
// We need to devide the color with the amount of times we added
// a color to it, in this case 4, to get the avg. color
Color = Color / 4;
// returned the blurred color
return Color;
}
technique Blur
{
pass Pass1
{
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
The reason it's purple is because you have
GraphicsDevice.Clear(Color.Black);
GraphicsDevice.SetRenderTarget(bulletRenderTarget);
which should be the other way around, so changing that into
GraphicsDevice.SetRenderTarget(bulletRenderTarget);
GraphicsDevice.Clear(Color.Black);
fixes the purple problem, to fix the shader change the following in the fx file
sampler ColorMapSampler : register(s0);
And change your spriteBatch.Begin() into
spriteBatch.Begin(SpriteSortMode.Immediate, null);
Some extra info:
the s0 points to the first texture on the graphics device, which is the one that supplied by spriteBatch.Draw, if you want to use s1 you'd have to set it on the GraphicsDevice first by using:
GraphicsDevice.Textures[1] = bulletRenderTarget;
the SpriteSortMode.Immediate just forces the spriteBatch.Draw to draw the sprite immediately, if you don't set it it'll create a batch and draw them all at once, but this will be to late because it needs to be drawn when the EffectPass is being applied.
As for the blur you could lower the value of BlurDistance, but you'd have to try, you can also look up how to do a bloom shader, usually gives a nice effect too.