Jump to content
  • Advertisement
Sign in to follow this  
dave09cbank

How to apply blur effect over region of texture using directx11

This topic is 737 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to apply a blur effect on a sub region of texture shown by white boxes in the image below.

The white boxes are objects drawn which just draw a quad filled with a color.

 

The effect is not to be applied to entire texture.

 

[attachment=32545:Capture_Drawing.PNG]

 

How could this be achieved ? Any suggestions ?

 

Thanks.

 

Note: Using DirectX11 via SharpDx and C#

 

EDIT:

 

1. Setting video frame shader resource:

var srv = new ShaderResourceView(DxDevice, textureToUpdate);
DxDevice.ImmediateContext.PixelShader.SetShaderResource(0, srv);
srv.Dispose(); 

2. Code to draw primitives: (Called in a loop for each object including the image texture)

DxDevice.ImmediateContext.InputAssembler.InputLayout = m_shaderData.InputLayoutConfig;
DxDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;

DxDevice.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(m_displayQuadvertices, VertexPositionColor.SizeInBytes, 0)); 
DxDevice.ImmediateContext.VertexShader.Set(m_shaderData.VertexShaderConfig);
DxDevice.ImmediateContext.PixelShader.Set(m_shaderData.PixelShaderConfig);

DxDevice.ImmediateContext.Draw(4, 0);
DxDevice.ImmediateContext.Flush();

3. Invalidating: (D3DImage control)

m_imgSource.InvalidateD3DImage(invalidateRectArea); // to invalidate the area of back buffer for rendering 

As for the video frame which is decoded and then gets mapped to the texture by setting the shader resource onthe pixel shader.

 

Calling the code order:

call code block 1

loop
{
call code block 2
}

call code block 3
Edited by dave09cbank

Share this post


Link to post
Share on other sites
Advertisement

Not sure if there's some fancy solution for this but the easiest that comes to mind is provide a texture that has the same size as the image you want to blur that acts as a mask (completely black and the parts you want to have blurred white). Afterwards in your blur shader you can use a simple if/else branch to either blur or not blur those pixels.

Share this post


Link to post
Share on other sites

thanks for the reply @lipsryme.

 

At the moment i draw my texture and then draw the color filled quad using another draw call.

 

Hence i'm not quite sure as to how this would work.

 

Could you elaborate more ... 

 

Note: iv included my draw calls above as part of my post.

Share this post


Link to post
Share on other sites

Are you happy with the blurred areas having sharp edges?

 

Those boxes are just quads? If so this should be quite easy (a little more tricky if it is a mask texture). Your actual image is just a texture so draw that first. Then draw your quads, make sure the quads have appropriate texture coordinates such that if you drew them textured (with the background image) they would show the exact part of the image they cover. When you draw those quads you just draw them with a blur shader which samples from your main image/background.

 

If you don't want sharp edges then you are going to have to use a mask as lipsryme suggests. The mask could be a texture, color it all black then white in the areas you want blurred. Blur the mask itself (so you get smooth edges between black and white). Have two textures, the normal image and a blurred version (the entire area is blurred) and in a shader you do something like:

color = normalImage*(1-blurMask) + blurredImage*blurMask

 

I don't know a great deal about blurring but I recall some needing multiple passes so I think the easiest option is to blur the entire image and merge either using a mask or draw it normal and draw only blurred parts on top by drawing some quads textured with the blurred texture. Possibly not the most optimal solution though.

 

I've attached an image to illustrate though I've flipped the values from what I have above so you can see the actual mask is the left one and the right is just it's inverse.

Share this post


Link to post
Share on other sites

@Nanoha thanks for the reply.

 

 

Yes i'm happy with the blurred areas having sharp edges.

Yes the boxes are just quads at the moment as a later point they will be polygon as well (not important at this time).

 

I draw my image as a texture in my first draw call and then the quads on top of it. As for textured coordinates would it be the same as the entire texture (0,0 to width, height of texture) as my co-ordinates are in screen space or would it need to be the co-ordinates of the quad where i wish to draw the blur effect on.

 

At this point the masking technique seems quite confusing to me thus would require a bit more of reading on my part.

 

As for the first solution you mentioned where to use a textured quad for blurred quad. For this quad would i reuse the same texture which i use for the background ?

 

Could you also provide a sample code or pseudo code which would really be helpful in understanding a bit more.

 

Thanks.

Share this post


Link to post
Share on other sites
Yes the boxes are just quads at the moment as a later point they will be polygon as well (not important at this time).

That's good, this method should happily expand to polygons no problem

 

As for textured coordinates would it be the same as the entire texture (0,0 to width, height of texture)

The texture coordinates would be different. It won't be too difficult to work them out. If your background takes up the entire screen such that texture coordinates (0, 0) is (0, 0) in screen space and (1, 1) is (width, height) then you can do some simple conversion to work out the texture coordinates for the quad's vertices since you know their location.

 

Off the top of my head it would be:

u = x/width;

v = y/height;

Where u/v are the texture coordinates and x/y are the position of the quad's vertices.

 

The simplest method I can think of given what you have said (though not necessarily the most performance optimal) would be this:

Use the background image to create a new texture which is just a blurred version of the original image. 

Render the original image to fill the screen.

Draw each of your quads/shapes using the blurred texture (on top of the image you just rendered).

 

As long as you setup the texture coordinates for each shape correctly it should work out.

 

DX11 Gaussian blur: http://www.rastertek.com/dx11tut36.html

Edited by Nanoha

Share this post


Link to post
Share on other sites

thanks for the explanation and sample code @Nanoha.

 

Now as my i'm using screen space coordinates, so getting the texture points shouldn't b difficult.

 

I seem to understand things a better now.

 

In addition to this could i just perform the blur operation in the pixel shader (of course using the original image) and setting the aplha value ? would this be a good approach as compared to creating a blurred texture image ? or are we referring to the same process here ?

 

In the mean time I will give this a try and post here my finding.

 

Thanks.

Share this post


Link to post
Share on other sites

In addition to this could i just perform the blur operation in the pixel shader (of course using the original image) and setting the aplha value ? would this be a good approach as compared to creating a blurred texture image ? or are we referring to the same process here ?

 

It depends on the blur you decide to use. You could do it as you describe but that might end up being the slower approach. When creating the blurred version you can easily half the texture resolution and in fact that helps with the blur and it cuts the work down to a quarter from that alone. To be clear you will be creating the blurred texture by using a pixel shader, you don't have to do that on the cpu.

 

First thing you should do is get a blurred texture then worry about getting only parts of the image blurred.

Share this post


Link to post
Share on other sites

i was actually planing to perform blur on entire texture and displaying the entire blurred texture without using the sub region of the texture which in order words is exactly what you suggested.

 

I will now give this a try.

 

Thanks for your suggestion. Much appreciated.

Share this post


Link to post
Share on other sites

Ok iv managed to get my texture perform blur and several other effects.

 

To make things progress i just performed the blur or other effects on my background texture which seemed to work perfectly and as expected as described in my effects.

Texture2D ShaderTexture : register(t0);
SamplerState Sampler : register (s0);

Texture2D EffectShaderTexture : register(t1);
SamplerState EffectSampler
{
	Filter = MIN_MAG_MIP_LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
};

cbuffer PerObject : register(b0)
{
	float4x4 ViewProjection;
	float4x4 World;
};

// ------------------------------------------------------
// A shader that accepts Position and Color
// ------------------------------------------------------

struct ColorVS_IN
{
	float4 Position : SV_Position;
	float4 ColorRGBA : COLOR;
};

struct ColorPS_IN
{
	float4 Position : SV_Position;
	float4 ColorRGBA : COLOR;
};

ColorPS_IN ColorVS(ColorVS_IN input)
{
	ColorPS_IN output = (ColorPS_IN)0;

	float4 transformedPosition = mul(input.Position, World);
	transformedPosition = mul(transformedPosition, ViewProjection);
	output.Position = transformedPosition;
	output.ColorRGBA = input.ColorRGBA;
	return output;
}

float4 ColorPS(ColorPS_IN input) : SV_Target
{
	return input.ColorRGBA;
}


// ------------------------------------------------------
// A shader that accepts Position and Texture
// ------------------------------------------------------

struct VertexShaderInput
{
	float4 Position : SV_Position;
	float2 TextureUV : TEXCOORD0;
};

struct VertexShaderOutput
{
	float4 Position : SV_Position;
	float2 TextureUV : TEXCOORD0;
};

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

	float4 transformedPosition = mul(input.Position, World);
	transformedPosition = mul(transformedPosition, ViewProjection);
	output.Position = transformedPosition;
	output.TextureUV = input.TextureUV;

	return output;
}

float4 PSMain(VertexShaderOutput input) : SV_Target
{
	return ShaderTexture.Sample(Sampler, input.TextureUV);
}

// ------------------------------------------------------
// A shader that accepts Position and Texture (shader effects)
// ------------------------------------------------------

// original blur effect
float4 PSMainBlurEffect(VertexShaderOutput input) : SV_Target
{
	float fBlurAmont = 0.25;
	float Center = 0.5;
	float4 rgbaValue = 0;
	input.TextureUV -= Center;

	for (int i = 0; i < 15; i++)
	{
		float scale = 1.0 + fBlurAmont * (i / 14.0);
		rgbaValue += EffectShaderTexture.Sample(EffectSampler, input.TextureUV * scale + Center);
	}

	rgbaValue /= 15;
	return rgbaValue;
}

// Gray scale effect
float4 PSMainGrayScaleEffect(VertexShaderOutput input) : SV_Target
{
	float4 rgbaValue = EffectShaderTexture.Sample(EffectSampler, input.TextureUV);

	rgbaValue = dot(rgbaValue, float3(0.3, 0.59, 0.11));
	return rgbaValue;
}

// Negative effect
float4 PSMainNegativeEffect(VertexShaderOutput input) : SV_Target
{
	float4 rgbaValue = EffectShaderTexture.Sample(EffectSampler, input.TextureUV);

	rgbaValue = 1 - rgbaValue;
	return rgbaValue;
}

// Pixelated effect
float4 PSMainPixelatedEffect(VertexShaderOutput input) : SV_Target
{
	float2 brickCounts = { 50, 50 }; //
	float2 brickSize = 1.0 / brickCounts;

	// Offset every other row of bricks
	float2 offsetuv = input.TextureUV;
	bool oddRow = floor(input.TextureUV.y / brickSize.y) % 2.0 >= 1.0;
	if (oddRow)
	{
		input.TextureUV.x += brickSize.x / 2.0;
	}

	float2 brickNum = floor(input.TextureUV / brickSize);
	float2 centerOfBrick = brickNum * brickSize + brickSize / 2;
	float4 color = EffectShaderTexture.Sample(EffectSampler, centerOfBrick);

	return color;
}

// Bloom effect 
float4 AdjustSaturation(float4 color, float saturation)
{
	float grey = dot(color, float3(0.3, 0.59, 0.11));

	// formula for lerp below taken from msdn
	//return lerp(grey, color, saturation);
	// x + s(y-x) <=== (x,y,s)
	return (grey + (saturation * (color - grey)));
}

float4 PSMainBloomEffect(VertexShaderOutput input) : SV_Target
{
	float BloomIntensity = 9; // 0 to 10
	float BaseIntensity = 1; // 0 to 10
	float BloomSaturation = 7; // 0 to 10
	float BaseSaturation = 1;  // 0 to 10

	float BloomThreshold = 0.25f;

	float4 base = EffectShaderTexture.Sample(EffectSampler, input.TextureUV);
	float4 bloom = saturate((base - BloomThreshold) / (1 - BloomThreshold));

	// Adjust color saturation and intensity.
	bloom = AdjustSaturation(bloom, BloomSaturation) * BloomIntensity;
	base = AdjustSaturation(base, BaseSaturation) * BaseIntensity;

	// Darken down the base image in areas where there is a lot of bloom,
	// to prevent things looking excessively burned-out.
	base *= (1 - saturate(bloom));

	// Combine the two images.
	return base + bloom;
}


// NightVision effect 
float4 PSMainNightVisionEffect(VertexShaderOutput input) : SV_Target
{
	float elapsedTime = 1;
	float luminanceThreshold = 0.1;
	float colorAmplification = 4;

	float2 uv;
	uv.x = 0.4*sin(elapsedTime*50.0);
	uv.y = 0.4*cos(elapsedTime*50.0);
	float3 n = EffectShaderTexture.Sample(EffectSampler, (input.TextureUV*3.5) + uv).rgb;
	float3 c = EffectShaderTexture.Sample(EffectSampler, input.TextureUV + n.xy*0.005).rgb;

	float lum = dot(float3(0.30, 0.59, 0.11), c);
	if (lum < luminanceThreshold)
		c *= colorAmplification;

	float3 visionColor = float3(0.1, 0.95, 0.2);
	return  float4((c + (n*0.2)) * visionColor ,1);
}


// Pinch effect
float4 PSMainPinchEffect(VertexShaderOutput input) : SV_Target
{
	float CenterX = 0.5;
	float CenterY = 0.5;
	float Radius = 0.75;
	float Amount = 5;

	float2 center = { CenterX, CenterY };
	float2 displace = center - input.TextureUV;
	float range = saturate(1 - (length(displace) / (abs(-sin(Radius * 8) * Radius) + 0.00000001F)));

	return EffectShaderTexture.Sample(EffectSampler, input.TextureUV + displace * range * Amount);
}

// Swirl effect
float4 PSMainSwirlEffect(VertexShaderOutput input) : SV_Target
{
	float2 center = 0.5;
	float spiralStrength = 10;
	float2 angleFrequency = { 1, 1 };

	float2 dir = input.TextureUV - center;
	float l = length(dir);
	float angle = atan2(dir.y, dir.x);

	float newAng = angle + spiralStrength * l;
	float xAmt = cos(angleFrequency.x * newAng) * l;
	float yAmt = sin(angleFrequency.y * newAng) * l;

	float2 newCoord = center + float2(xAmt, yAmt);

	return EffectShaderTexture.Sample(EffectSampler, newCoord);
}

However the problem i now face is when trying to perform the effects within a sub region using a quad.

 

It seems my effect's texture is displayed to the entire target display area(displayed below) that is covered by the background texture, even though my sub-region quads have their location + size set to the  correct parameters.

 

[attachment=32596:pixelated_quad.PNG]

 

Can't seems to figure it out why its behavior is different to when drawing a quad that just fills with a color (shown in original post) ?

 

Any suggestion ?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!