9
\$\begingroup\$

I am trying to create a glittering effect for my realtime shader but I don't know how.

Here is one example, and another example.

enter image description here

What technique can I use to implement this?

\$\endgroup\$
  • \$\begingroup\$ It could be achieved via a Post-process effect, similar to bloom, but applying a pattern(a star texture) to the down-sample phase. This is all just speculation tough. \$\endgroup\$ – akaltar Jan 20 '14 at 14:00
  • 1
    \$\begingroup\$ Wouldn't a normal and specular map let you do this via a texture? \$\endgroup\$ – JohnB Jan 21 '14 at 13:43
  • \$\begingroup\$ I made some test using normal map. But the hard thing is to make them glitter according to view orientation and light orientation. \$\endgroup\$ – MaT Jan 21 '14 at 13:47
10
\$\begingroup\$

Well, when asked to design any shader, we should start by breaking things down to smaller problems. And just as note the glittering effect doesn't actually makes the shader looks good, but the overall lighting and effect, using only one of them won't look as good.

First of all let us state what is not directly part of the shader:

  1. The shadowing is not part of the shader, and it is done via separate shadowing pass.
  2. I assume there is ambient occlusion (especially that this image shown in the question is particularly not using real time renderer but that's an assumption).

Secondly, let's break the actual shader into separate effects:

  1. There is an anisotropic like lighting, this is very essiental to the overall look of the shader. The reason behind this, is that the actual material contains fabrics, these shiny fabrics makes the light reflection have directional bias, making the most amount of reflected light in that certain direction.

enter image description here

enter image description here Note that such fabrics have infinitely many normals, but the technique described here approximates the most significant normal

In order to approximate the most significant normal, one way to do, is to use texture coordinates and calculate tangents of the mesh, and instead of calculating N.L you calculate 1-(N.T).

Full explanation here. And you probably need to implement that in fragment shader rather than the vertex technique they talk about. Other anisotropic models can also apply.

Now for the glittering effect:

This can be done in world space/local texture space, or screen space as a separate pass.

The algorithm I can think off, uses image processing technique (assuming the mesh have texture coords).

  • Generate a high frequency 2D noise on the mesh surface using it's texture coordinates, perlin noise seems a good candidate.
  • Apply a max filter using 3x3 kernel on the noise. This will generate an effect similar to the below image, and the max filter is described here.

enter image description here

Note the above image is just an example of the max filter, and applying it on the noise will give sth similar to a star field.

  • Once you have done this, apply a Gaussian filter with certain deviation on the noise to get star like shape.

enter image description here

Example of Gausian filter applied on max(ed) noise.

  • The final step is to combine this with orginal mesh texture and light. This is best done using an (|) or-ing binary operation with the original mesh texture/color, this will take only the white from the noise and remove any black pixels. Regarding the light (and possibly other specular maps) the best thing to do is to add it or modulate it with your previously combined pixels. You may also need a glow post-processing effect for a better glow.

Note, this technique might need significant optimzation for a real time shader.

\$\endgroup\$
3
\$\begingroup\$

There's an interesting article AMD - Getting Procedural.

It seems that sparkles are harder than I think.
Decent solution: Use 3D position to index 3D noise function, add the view vector, use frac function to further randomize things.

Sparkle:
float specBase = saturate(dot(reflect(-normalize(viewVec), normal),
lightDir));
// Perturb a grid pattern with some noise and with the view-vector
// to let the glittering change with view.
float3 fp = frac(0.7 * pos + 9 * Noise3D( pos * 0.04).r + 0.1 * viewVec);
fp *= (1 - fp);
float glitter = saturate(1 - 7 * (fp.x + fp.y + fp.z));
float sparkle = glitter * pow(specBase, 1.5);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.