Page 1 of 5

Stencil Glow Demo

Posted: Fri Dec 29, 2006 12:40 am
by Assaf Raman
Stencil Glow Demo
Image

The work described in this post is partially based on code by nebukadnezzar that was posted on this thread: http://www.ogre3d.org/phpBB2/viewtopic.php?t=25321

Thanks nebukadnezzar!

I have created a simple demo to show how to use the stencil to create two types of glow effects.

The main advantage of my glows is that you can apply them to a single object and not the whole scene.

Outline glow effect round a specific entity:
Image

A full body wrap glow effect round a specific entity:
Image

I did not find any other good demo of how to use the stencil in OGRE.

I recommend to add this demo (or similar) to the OGRE demos that come with the OGRE source download.

Here is the exe ready to run:
http://assaframan.googlepages.com/StencilGlow_exe.zip

Here is the code:
http://assaframan.googlepages.com/StencilGlow_src.zip

Here are some more screenshots:
Image
Image
Image
Image


This is my Xmas present to the OGRE community. :D

[EDIT]I updated the downloads with broli's normal fix.[/EDIT]

Posted: Fri Dec 29, 2006 12:52 am
by BRAINLESS
Oh my god, thanks! :D

Posted: Fri Dec 29, 2006 3:05 am
by Jerky
Wow, that could be handy in any type of game. Very cool, thanks!

Posted: Fri Dec 29, 2006 5:13 am
by broli
In your cg or hlsl file try using the normal and multiply it with the rest. And don't multyply your vertex position, something like this...

Code: Select all

cg:

mypos.xyz += size_value * (1.0 + (sin(time * 5.0) + 1.0)  / 5.0 ) * normal;

hlsl:

vec3 Pos = gl_Vertex.xyz +  ( (size_value * (1.0 + (sin(time * 5.0) + 1.0)  / 15.0 ) * normal );
It would clear up that offset issue you currently have since the vertices arn't shifted trough their normals.

Posted: Fri Dec 29, 2006 5:16 am
by Kentamanos
You're saying for instance, that would make the glow around the teeth match up, right?

Posted: Fri Dec 29, 2006 5:23 am
by broli
That's correct.

Posted: Fri Dec 29, 2006 10:38 am
by Assaf Raman
broli: You are right - it is much better with the normal.

I updated the downloads in the first post.

Redownload if you want it.

Here is how it looks now:
Image
Image

Thanks broli!

Posted: Fri Dec 29, 2006 10:41 am
by Kentamanos
Very sweet now...

Nice tip broli, and good work Assaf!

Posted: Fri Dec 29, 2006 3:44 pm
by Ajare
I'm getting a problem with this when I try to turn the effect 'off'. I have a 'select object' function as follows:

Code: Select all

void ActorRepresentation::setHighlighted (bool active)
{
	if (active)
	{
        mEntity->setRenderQueueGroup
                (RENDER_QUEUE_OUTLINE_GLOW_OBJECTS);
		mHiliteEntity = mEntity->clone (mEntity->getName () + "Hilite");
		mHiliteEntity->setRenderQueueGroup (RENDER_QUEUE_OUTLINE_GLOW_GLOWS);
		mHiliteEntity->setMaterialName ("Editor/Glow_CG");
		mNode->attachObject (mHiliteEntity);
	}
	else
	{
		Ogre::SceneManager *scm = Ogre::Root::getSingleton ().getSceneManager ("SceneManager");
		mEntity->setRenderQueueGroup (mDefaultRenderQueueGroup);
		scm->destroyEntity (mHiliteEntity);
		mHiliteEntity = 0;
	}
}
However, when de-highlighted, the original entity (mEntity) is now being rendered with no depth-checking.

Posted: Fri Dec 29, 2006 5:43 pm
by SpannerMan
Wow thats a really cool effect Assaf, I agree this will be very useful for many things.

So if its using the Stencil buffer and shaders, can you tell me what are the minimum hardware requirements for this effect?

Posted: Fri Dec 29, 2006 5:56 pm
by broli
The material file says vertex shader 1.1/pixel shader 2.0.

Posted: Fri Dec 29, 2006 6:08 pm
by Falagard
It would be easy to get it to work with only pixel shader 1.1, and then have a fallback (through code and material) that uses scaling and works with fixed function.

Posted: Fri Dec 29, 2006 6:49 pm
by Assaf Raman
This effect can be done without any shaders.
You can use scale (a modified scale that scales in the direction of the normal) and color change.

I guess it can be modified so it will work on any hardware that supports the stencil buffer.

Posted: Fri Dec 29, 2006 7:52 pm
by Assaf Raman
Ajare: To disable the effect - just detach the glow entity from the node.

For outline glow:

Code: Select all

actualOutlineGlowNode->detachObject(actualOutlineGlowEntity);
For full glow:

Code: Select all

alphaFullGlowNode->detachObject(alphaFullGlowEntity);
glowFullGlowNode->detachObject(glowFullGlowEntity);
To enable the effect re-attach the glow entity.

Posted: Fri Dec 29, 2006 8:33 pm
by jacmoe
What a great present! :D

This looks awesome and seems to be efficient and easy to use. Useful in many situations! Thanks! :)

Posted: Fri Dec 29, 2006 11:11 pm
by broli
Assaf Raman wrote:This effect can be done without any shaders.
You can use scale (a modified scale that scales in the direction of the normal) and color change.
Why would you use the CPU and extra code with some nasty work arounds instead of a simple Ogre material+GPU method that everybody can use out of the box. This goes for alot of things that are made here on these forums.

Posted: Fri Dec 29, 2006 11:54 pm
by Aiursrage2k
Looks great. Are you able to change the color/thickness of the glow?

Posted: Sat Dec 30, 2006 1:44 am
by Assaf Raman
You can very easily – just change it in the shaders. The shaders are very basic shaders and I think you can change them without any knowledge in shaders.

Posted: Sat Dec 30, 2006 10:17 am
by BRAINLESS
Assaf Raman wrote:You can very easily – just change it in the shaders. The shaders are very basic shaders and I think you can change them without any knowledge in shaders.
I agree, I have no knowledge of shaders and was able to change the workings of these 2 :) I ran up to a problem though, which your demo doesn't seem to suffer from. Perhaps that's because the Ogre model is more complex, but if I use a simple box model and this shader there's an obvious seam between the vertices of the glow. It looks a bit odd, so I'm going to try using a scaled scenenode instead.

Posted: Sun Dec 31, 2006 2:39 am
by big_o
Very cool, and very useful, I might be able to find a use for this down the road. :D

[edit] just noticed that it grows and shrinks, evenmore awesome! :)

urmmmm

Posted: Wed Jan 03, 2007 3:04 pm
by Nakiks
or just duplicate the mesh rescale & use another material with scene_blend add for the first head result and for the second just flip normals. Oldest trick in the book, way before shaders

Posted: Wed Jan 03, 2007 4:23 pm
by jintal
BRAINLESS wrote:
Assaf Raman wrote:You can very easily – just change it in the shaders. The shaders are very basic shaders and I think you can change them without any knowledge in shaders.
I agree, I have no knowledge of shaders and was able to change the workings of these 2 :) I ran up to a problem though, which your demo doesn't seem to suffer from. Perhaps that's because the Ogre model is more complex, but if I use a simple box model and this shader there's an obvious seam between the vertices of the glow. It looks a bit odd, so I'm going to try using a scaled scenenode instead.
this problem also occurs with the robot.mesh. seems that the faces are translated a bit outward according to their normals only. so a right angle or close to one would have gaps in the glow.

i dont know how to do cg, anyone care to fix this? :D

Posted: Wed Jan 03, 2007 4:47 pm
by BRAINLESS
I've asked around and apparently that's not possible with vertex shaders. I'm no expert though (this is my first experience with shaders :P) so I may be wrong :)

Posted: Wed Jan 03, 2007 4:48 pm
by Falagard
It's not possible to fix without modifying the original mesh normals. The problem is that at angular seams in the mesh, normals usually point in different directions. This is because when you generate normals for a mesh in a 3d modeller you usually define an angular threshold for "smoothing" the normals - if the threshold is exceeded the normals will point in different directions at seams (otherwise your sharp corners would appear smooth-ish when you render them in Ogre). You could fix this by making an actual copy of the geometry and then smoothing all normals without this threshold, but it probably isn't worth it.

You can't do anything about this in a vertex shader because per vertex the shader doesn't know anything about the surrounding vertices, so you can't change the normal direction in the shader.

If you want to avoid this, you have to use the scale approach, instead of moving the verts out along their normals. You can do the scale inside a shader as well instead of calling setScale on the mesh. Also, you should get the center of the bounding box and pass it to the shader, then get the direction from this position to the vertex position and move the verts out along this vector. If you just pass a scale matrix and use the origin of the mesh, unless the origin is directly in the center of the mesh it will scale out in a less friendly manner.

Posted: Wed Jan 03, 2007 5:03 pm
by BRAINLESS
So which one is better? Either way we'll have to move the vertices out from the center and multiply them by a scale matrix. Using a shader this would have to be done every frame, but that may not be a problem as it's done on the GPU. I don't know if setScale() is done on the GPU, but I expect it isn't... it would be a one-time-only job though.

With my limited experience I'd say option 2 (using setScale rather then a shader) would be more efficient...