Search code examples
c#hlslmanaged-directxdirectx-9glow

Simple HLSL glow/blur effect in DirectX9


I have been struggling for days to find any resources to help me write a simple glow/blur shader using High Level Shader Language and DirectX 9 Managed Libraries.

All I need to do is have an array of CustomVertex.TransformedColored vertices drawn as simple lines and then blurred/glowed by the HLSL effect.

I have searched the internet for about three days now with some results, but I just cannot find a really good tutorial or example. I have a basic understanding of HLSL but I do not understand it enough to figure out how to write this shader (I have read the HLSL chapter in 3 DirectX books as well).

Here is some (abridged) code:

CustomVertex.TransformedColored[] glowVertices = new CustomVertex.TransformedColored[4];
glowVertices[0] = new CustomVertex.TransformedColored(random.Next(this.render.Width), random.Next(this.render.Height), 1, 1, Color.Cyan.ToArgb());
glowVertices[1] = new CustomVertex.TransformedColored(random.Next(this.render.Width), random.Next(this.render.Height), 1, 1, Color.Blue.ToArgb());
glowVertices[2] = new CustomVertex.TransformedColored(random.Next(this.render.Width), random.Next(this.render.Height), 1, 1, Color.Cyan.ToArgb());
glowVertices[3] = new CustomVertex.TransformedColored(random.Next(this.render.Width), random.Next(this.render.Height), 1, 1, Color.Blue.ToArgb());

this.device.BeginScene();
int passes = this.glowEffect.Begin(0);
for (int i = 0; i < passes; i++)
 {
     this.glowEffect.BeginPass(i);
     this.device.DrawUserPrimitives(PrimitiveType.LineStrip, glowVertices.Length - 1, glowVertices);
     this.glowEffect.EndPass();
 }
 this.glowEffect.End();
 this.device.EndScene();

I guess I'm not so much looking for help on a specific part of HLSL, given the number of questions and amount of code I would have to post I'm really just looking for some help finding resources!


Solution

  • The immediate problem I see with your code is that you're applying a shader to the lines themselves. Pixel shaders don't really work that way. You can't interact with any of the pixels around the pixel being shaded. All you get is registers (position, colour, texture coordinate, etc) and samplers (textures) for that one pixel that is being output.

    To work around this, the basic process of doing a blur effect (such as for glow or bloom) is to draw the scene you want to blur to a render target. Then use that render target as a texture on a full-screen quad that you draw with a blur shader. A simple blur shader takes takes multiple samples from that texture - each with a slightly offset texture coordinate. The result is a blurred image of the texture.

    Usually you repeat this process (now rendering the render-target-on-a-full-screen-quad to another render target), doing one blur horizontally and one vertically, to get the most blurring with the fewest number of samples.

    I recommend looking at the XNA Bloom Sample. There is more extensive documentation on the process in there. While the API is XNA, not DirectX, they are fairly similar and they both use HLSL.