Just a quick shader question

Started by
5 comments, last by MJP 11 years, 7 months ago
Okay... So I have a specular shader working nicely and I'm quite happy with the results. Now for a little added realism, I'd like to add some sort of "lens flare" effect based upon the specular shader. In other words, when a good amount of shine is reflecting off the surface of a mesh, I'd like to have that shine slightly "glow" off it's surface and possibly toward the camera a bit. I don't think I'm looking for deferred shading, since my project is a simple model viewer and requires no background geometry. Just a simple black or gray background works fine for my purposes. How would I go about this? Which additional concepts should I consider implementing? What is the first thing I should research? Here is my current shader:

[source lang="cpp"]float4x4 WorldViewProjection : WORLDVIEWPROJECTION;
float4x4 World : WORLD;
float4x3 WorldInverseTranspose : WORLDINVERSETRANSPOSE;
float3 afLightColor[2];
float3 afLightDir[5];
float3 vCameraPos : CAMERAPOSITION;

struct VS_INPUT
{
float3 Position : POSITION;
float3 Normal : NORMAL;
};

struct VS_OUTPUT
{
float4 Position : POSITION;
float3 ViewDir : TEXCOORD0;
float3 Normal : TEXCOORD1;
};

VS_OUTPUT DefaultVShader(VS_INPUT IN)
{
VS_OUTPUT Out;
float3 objPos = IN.Position;
Out.Position = mul( float4(objPos, 1.0f), WorldViewProjection );
float3 WorldPos = mul( float4(objPos, 1.0f), World );
Out.ViewDir = vCameraPos - WorldPos;
Out.Normal = mul( IN.Normal, WorldInverseTranspose );
return Out;
}

float4 DefaultPShaderSpecular(VS_OUTPUT IN) : COLOR
{
float4 OUT = float4(0.0f, 0.0f, 0.0f, 1.0f);
float3 Normal = normalize(IN.Normal);
float3 ViewDir = normalize(IN.ViewDir);
{
float L1 = dot( Normal, afLightDir[0] ) * 0.5f + 0.5f;
float3 Reflect = reflect( Normal, afLightDir[0] );
float fHalfLambert = L1 * L1;
OUT.rgb += afLightColor[0] * (fHalfLambert + saturate( fHalfLambert * 4.0f ) * pow( dot(Reflect, ViewDir), 9 ));
}
return OUT;
}

technique DefaultFXSpecular
{
pass p0
{
CullMode=none;
PixelShader = compile ps_3_0 DefaultPShaderSpecular();
VertexShader = compile vs_3_0 DefaultVShader();
}
};[/source]
Advertisement
So I believe what I'm going for is a simple bloom effect, based upon the overall amount of light being reflected off a given surface. I assume I would need to first calculate the overall amount of light being reflected, then use the output of that to check if it exceeds a certain threshold within the bloom effect. But how would I calculate the overall amount of light being reflected from a surface? Or is there a better way?
You can't glow outside of the geometry you are rendering, in a straightforward way (pixel shader is only run for pixels on actual geometry). If you want the glow to extend beyond the borders of the geometry, then you need some other geometry to be there.

One approach is to render the entire scene to a texture, and then render a full-screen quad to compose it into the final scene - this gives you a chance to affect the whole screen (typical for effects like Bloom).

Another (albeit probably more complicated) approach would be to generate extra 'fins' extending outside your geometry (using a geometry shader), and render the glow there (common for rendering Fur).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Ok, but how would I calculate the scalar value of the effect?
Take for example, with the light shining down from the top:

Fig. 1
Front view, dark top surface (No specular or bloom):
3BUhh.png

Fig 2.
A bit more perspective, some specular (Full bloom on top surface, medium effect on side, minimal on front):
bMBc9.png

How would I know how much light is actually being reflected?
And is it possible to affect only certain areas, or would it have to affect the entire view?
Or alternatively, could I make the bloom effect only affect colors with bright hues?

How would I know how much light is actually being reflected?


The amount of light reflected is the value of the pixel you drew.

Bloom is often used in conjunction with an HDR render target, since then while doing your post-process full-screen pass, you can know how far beyond "complete white" you were (to determine the amount of bloom).

You can't glow outside of the geometry you are rendering, in a straightforward way (pixel shader is only run for pixels on actual geometry).

You could scatter blur to an Unordered Access View from within a Pixel Shader. Although, I wouldn't recommend doing it that way biggrin.png
Back in the old days before HDR, it was common to store some "glow" value in either the alpha channel or a separate render target. This value could be derived from some specific glow texture, or you could use the results of your specular lighting, or something along those lines. You can also just use a threshold or lower exposure to get your bloom source with LDR rendering, but in general you'll usually end up with more things blooming than you'd like. With HDR things are more natural since you can naturally express really bright light sources and bright surfaces.

This topic is closed to new replies.

Advertisement