Has anyone been able to Glow/stencil effect in C#?

RichTufty

05-04-2007 14:09:08

Hi

There is a really cool bit of code in this topic to make objects glow / stencil effect, but I can't seem to convert it to C# as i can't seem to correspond the Ogre object model with the Mogre one.

http://www.ogre3d.org/phpBB2/viewtopic.php?t=27477

e.g. their class inherits from...
Ogre::RenderQueueListener
... but i can't find that in Mogre, only...
Mogre.RenderQueue
Are they the same thing? Only it uses a load of constants which i can't find in Mogre.

Has anyone done this already? Is it possible to do in C#/Mogre?

tufty

lancore89

05-04-2007 14:26:25

You have to do this with delegates and events in C#.

Example:
mSceneManager.RenderQueueStarted += new RenderQueueListener.RenderQueueStartedHandler(RenderQueueStarted);

void RenderQueueStarted(byte queueGroupId, string invocation, out bool skipThisInvocation)
{
...
}


This Wiki-Page will help you: http://www.ogre3d.org/wiki/index.php/OGRE_to_MOGRE

RichTufty

23-04-2007 17:03:39

Thanks lancore89, that got me started. I have now converted the whole demo to C# and it works!! If anyone is interested in the code let me know!

lancore89

24-04-2007 22:01:29

I would be interested :D

And I think others too, maybe you can post this in the Wiki?

RichTufty

25-04-2007 14:20:12

What's the best way for me to do that? I've never added anything to the Wiki before!

Bekas

25-04-2007 17:34:30

What's the best way for me to do that? I've never added anything to the Wiki before!
First, you should create an account on the main Ogre forums (if you don't already have one). You will use it to login for the wiki too.

For the glow effect, I'd suggest adding an entry at http://www.ogre3d.org/wiki/index.php/Mo ... #_Snippets

kubatp

22-11-2009 21:18:55

Hi,
does anyone has a C# code for this?
THank you Pavel

smiley80

23-11-2009 20:04:19


private const byte RENDER_QUEUE_FULL_GLOW_ALPHA_GLOW = (byte)RenderQueueGroupID.RENDER_QUEUE_MAIN + 3;
private const byte RENDER_QUEUE_FULL_GLOW_GLOW = (byte)RenderQueueGroupID.RENDER_QUEUE_MAIN + 4;
private const byte RENDER_QUEUE_OUTLINE_GLOW_GLOWS = (byte)RenderQueueGroupID.RENDER_QUEUE_MAIN + 2;
private const byte LAST_STENCIL_OP_RENDER_QUEUE = RENDER_QUEUE_FULL_GLOW_GLOW;
private const byte RENDER_QUEUE_OUTLINE_GLOW_OBJECTS = (byte)RenderQueueGroupID.RENDER_QUEUE_MAIN + 1;
private const int STENCIL_VALUE_FOR_FULL_GLOW = 2;
private const int STENCIL_VALUE_FOR_OUTLINE_GLOW = 1;
private const uint STENCIL_FULL_MASK = 0xFFFFFFFF;

private void RenderQueueEnded(byte queueGroupId, string invocation, out bool skipThisInvocation)
{
skipThisInvocation = false;
if (queueGroupId == LAST_STENCIL_OP_RENDER_QUEUE)
{
RenderSystem rendersys = Root.Singleton.RenderSystem;
rendersys.SetStencilCheckEnabled(false);
rendersys.SetStencilBufferParams();
}
}

private void RenderQueueStarted(byte queueGroupId, string invocation, out bool skipThisInvocation)
{
skipThisInvocation = false;
RenderSystem rendersys = Root.Singleton.RenderSystem;

if (queueGroupId == RENDER_QUEUE_OUTLINE_GLOW_OBJECTS) // outline glow object
{
rendersys.ClearFrameBuffer((uint)FrameBufferType.FBT_STENCIL);
rendersys.SetStencilCheckEnabled(true);
rendersys.SetStencilBufferParams(CompareFunction.CMPF_ALWAYS_PASS,
STENCIL_VALUE_FOR_OUTLINE_GLOW,
STENCIL_FULL_MASK,
StencilOperation.SOP_KEEP,
StencilOperation.SOP_KEEP,
StencilOperation.SOP_REPLACE,
false);
}

if (queueGroupId == RENDER_QUEUE_OUTLINE_GLOW_GLOWS) // outline glow
{
rendersys.SetStencilCheckEnabled(true);
rendersys.SetStencilBufferParams(CompareFunction.CMPF_NOT_EQUAL,
STENCIL_VALUE_FOR_OUTLINE_GLOW,
STENCIL_FULL_MASK,
StencilOperation.SOP_KEEP,
StencilOperation.SOP_KEEP,
StencilOperation.SOP_REPLACE,
false);
}

if (queueGroupId == RENDER_QUEUE_FULL_GLOW_ALPHA_GLOW) // full glow - alpha glow
{
rendersys.SetStencilCheckEnabled(true);
rendersys.SetStencilBufferParams(CompareFunction.CMPF_ALWAYS_PASS,
STENCIL_VALUE_FOR_FULL_GLOW,
STENCIL_FULL_MASK,
StencilOperation.SOP_KEEP,
StencilOperation.SOP_KEEP,
StencilOperation.SOP_REPLACE,
false);
}

if (queueGroupId == RENDER_QUEUE_FULL_GLOW_GLOW) // full glow - glow
{
rendersys.SetStencilCheckEnabled(true);
rendersys.SetStencilBufferParams(CompareFunction.CMPF_EQUAL,
STENCIL_VALUE_FOR_FULL_GLOW,
STENCIL_FULL_MASK,
StencilOperation.SOP_KEEP,
StencilOperation.SOP_KEEP,
StencilOperation.SOP_ZERO,
false);
}
}


and the demo scene:
sceneMgr.RenderQueueEnded += this.RenderQueueEnded;
sceneMgr.RenderQueueStarted += this.RenderQueueStarted;

// outline glow entity
Entity outlineGlowEntity = sceneMgr.CreateEntity("outlineGlow", "ogrehead.mesh");
outlineGlowEntity.RenderQueueGroup = RENDER_QUEUE_OUTLINE_GLOW_OBJECTS;
sceneMgr.RootSceneNode.CreateChildSceneNode().AttachObject(outlineGlowEntity);

// outline glow entity actual glow
Entity actualOutlineGlowEntity = outlineGlowEntity.Clone(outlineGlowEntity.Name + "_glow");
actualOutlineGlowEntity.RenderQueueGroup = RENDER_QUEUE_OUTLINE_GLOW_GLOWS;
actualOutlineGlowEntity.SetMaterialName("cg/glow");
SceneNode actualOutlineGlowNode = outlineGlowEntity.ParentSceneNode.CreateChildSceneNode("outlineGlowNode");
actualOutlineGlowNode.AttachObject(actualOutlineGlowEntity);

// normal entity
Entity normalOgreEntity = sceneMgr.CreateEntity("normalOgreEntity", "ogrehead.mesh");
SceneNode normalOgreNode = sceneMgr.RootSceneNode.CreateChildSceneNode();
normalOgreNode.AttachObject(normalOgreEntity);
normalOgreNode.SetPosition(80, 0, 0);

// full glow entity
Entity fullGlowEntity = sceneMgr.CreateEntity("fullGlowEntity", "ogrehead.mesh");
SceneNode fullGlowNode = sceneMgr.RootSceneNode.CreateChildSceneNode();
fullGlowNode.AttachObject(fullGlowEntity);
fullGlowNode.SetPosition(-80, 0, 0);

// full glow alpha glow
Entity alphaFullGlowEntity = fullGlowEntity.Clone(fullGlowEntity.Name + "_alphaGlow");
alphaFullGlowEntity.RenderQueueGroup = RENDER_QUEUE_FULL_GLOW_ALPHA_GLOW;
alphaFullGlowEntity.SetMaterialName("cg/alpha_glow");
SceneNode alphaFullGlowNode = fullGlowEntity.ParentSceneNode.CreateChildSceneNode("fullGlowAlphaNode");
alphaFullGlowNode.AttachObject(alphaFullGlowEntity);

// full glow alpha glow
Entity glowFullGlowEntity = fullGlowEntity.Clone(fullGlowEntity.Name + "_glow");
glowFullGlowEntity.RenderQueueGroup = RENDER_QUEUE_FULL_GLOW_GLOW;
glowFullGlowEntity.SetMaterialName("cg/no_depth_check_glow");
SceneNode glowFullGlowNode = fullGlowEntity.ParentSceneNode.CreateChildSceneNode("fullGlowGlowNode");
glowFullGlowNode.AttachObject(glowFullGlowEntity);

kubatp

23-11-2009 20:19:44

Hi Smiley,
I have already tried to port it, but when I call the function which should set the material name, it just changes the entity's colour and the whole mesh is white.
I tried it with your code and it's the same. Do I miss something here?

smiley80

23-11-2009 20:31:27

Are there any errors in the log file?
Make sure you have the material script and the shaders (the ones included in the zip file) somewhere where Ogre can find them.

kubatp

23-11-2009 20:43:57

You are right. There is this warning

WARNING: material cg/alpha_glow has no supportable Techniques and will be blank. Explanation:
Pass 0: Vertex program glow_vs_cg cannot be used - compile error.

smiley80

23-11-2009 21:08:24

You need the CgProgramManager plugin.
Copy Plugin_CgProgramManager.dll and cg.dll to your output folder, and add 'Plugin=Plugin_CgProgramManager' to your plugins.cfg.

kubatp

23-11-2009 21:12:06

All this was already done. Any other ideas?

smiley80

23-11-2009 21:39:51

In your log there should be a line, that starts with '* Supported Shader Profiles:'. Which ones does it list?
And does the log mention any details about the compile error?

kubatp

23-11-2009 22:41:38

You are right. There was an exception in the log. The program hasn't been loaded, because of a Typo in the resources.cfg file.

I successfully run full glow, however I would like to use just the outline glow, which doesn't work.
When I "highlight" it, it doesn't change anything, except of the renderqueue (so for example MOIS mouse cursor is behind the entity).

There are no exceptions or errors in the log.

kubatp

26-11-2009 08:22:42

Any ideas?

kubatp

07-12-2009 22:08:19

Hi,
let's say I already created the entity (as entity in code), which should be highlighted. When user clicks on this entity, it calls following code (which should highlight it):

// outline glow entity
Entity outlineGlowEntity = entity.Clone("outlineGlow");
outlineGlowEntity.RenderQueueGroup = RENDER_QUEUE_OUTLINE_GLOW_OBJECTS;
SceneNode outlineGlowEntityNode = entity.ParentSceneNode.CreateChildSceneNode("fullGlowAlphaNode");
outlineGlowEntityNode.AttachObject(outlineGlowEntity);

// outline glow entity actual glow
Entity actualOutlineGlowEntity = entity.Clone(entity.Name + "_glow");
actualOutlineGlowEntity.RenderQueueGroup = RENDER_QUEUE_OUTLINE_GLOW_GLOWS;
actualOutlineGlowEntity.SetMaterialName("cg/glow");
SceneNode actualOutlineGlowNode = outlineGlowEntityNode.ParentSceneNode.CreateChildSceneNode("outlineGlowNode");
actualOutlineGlowNode.AttachObject(actualOutlineGlowEntity);


however this doesn't do anything except of weird changes in the order visibility of entity (I guess it's because of the renderqueuegroup).
What is wrong with this?
THank you Pavel

kubatp

15-12-2009 10:04:01

Does anyone has functional example MOGRE project with this effect please?

kubatp

24-12-2009 20:52:06

Can anybody help me here please?

smiley80

26-12-2009 11:48:14

Tried your code with the ogre head mesh, and it works correctly.

kubatp

26-12-2009 22:42:08

I tried it and the result is, that when the ogrehead is the only standalone element, it works correctly.
There are problems when there are other elements in front of the ogrehead, with the Miyagi controls and the mouse cursor as well.
The description is:

- all the miyagi controls are "behind" the glowing ogrehead, the transparent Miyagi panels are no longer transparent and the transparent part are displayed as black
- part of ogremesh, which should be "behind" another manualobject (and really is, when the glowing is not used) is actually displayed
- mouse cursor is behind the ogrehead and not transparent as well (you can see not just the arrow but the black rectangle around as well).

Where is the problem?

smiley80

27-12-2009 02:42:35

The problem lies in the RenderQueueEnded method:

private void RenderQueueEnded(byte queueGroupId, string invocation, out bool skipThisInvocation)
{
skipThisInvocation = false;
if (queueGroupId == LAST_STENCIL_OP_RENDER_QUEUE)
{
RenderSystem rendersys = Root.Singleton.RenderSystem;
rendersys.SetStencilCheckEnabled(false);
rendersys.SetStencilBufferParams();
}
}

If there's no object in LAST_STENCIL_OP_RENDER_QUEUE, than it's never called for this RenderQueueGroupID, the if-condition is never true and the stencil check is never disabled.

Change the declaration of LAST_STENCIL_OP_RENDER_QUEUE to:
private const byte LAST_STENCIL_OP_RENDER_QUEUE = RENDER_QUEUE_OUTLINE_GLOW_GLOWS;

kubatp

27-12-2009 15:45:29

Hi Smiley,
you are absolutely right! Thank you!

I have last question regards to this : when I want to "deselect" the object, I execute in loop this code:

SceneNode sn = en.ParentSceneNode;
SceneManager.DestroyEntity(en);
SceneManager.DestroySceneNode(sn);

where en are all the created glow entities.

Unfortunately when it calls Miyagi.Core.GuiManager.Singleton.Update(true) the first time after, it throws "An unhandled exception of type 'System.ExecutionEngineException' occurred in MOIS.dll"

smiley80

27-12-2009 17:03:13

You must detach an entity before you destroy it:

SceneNode sn = en.ParentSceneNode;
sn.DetachObject(en);
SceneManager.DestroyEntity(en);
en.Dispose();

SceneManager.DestroySceneNode(sn);
sn.Dispose();


But I don't know how that can cause an ExecutionEngineException in MOIS.

kubatp

27-12-2009 19:52:17

I did it like you suggest, but unfortunately the exception is still thrown. Here is the whole loop:


List<Entity> entitiesToDestroy = highlightedEntities[entity.Name];
foreach (Entity en in entitiesToDestroy)
{
SceneNode sn = en.ParentSceneNode;
sn.DetachObject(en);
SceneManager.DestroyEntity(en);
en.Dispose();
SceneManager.DestroySceneNode(sn);
sn.Dispose();
}

entitiesToDestroy.Clear();
highlightedEntities.Remove(entity.Name);



where highlightedEntities is a Dictionary with string as a key (it's actually the name of entity which is glowed) and the list of entities which are used for this glow effect.
I know I don't have to call entitiesToDestroy.Clear(), but it was just a hopeless try to remove references, even the references should be removed by GC anyway later.

Do you see something unusal? From the behavior I've found out, that if DestroyEntity is not called, it doesn't throw the exception, so the problem is definitely in the Entity destroying.

kubatp

19-01-2010 15:32:40

Hi,
I have a question which could be more related to the entity (mesh) itself rather than this glow effect, but I ask it here, because this is pretty related topic.

I have used this glow effect for one of my meshes. It works pretty well - it displays the glow effect (let's say in the size 1/15 of the mesh) and everything is fine. I tried to use the exact same code for another mesh but the effect looks differently. The glow is extremely big - it's like many times more far from the entity and with a lot bigger size.
I guess it has to do something with normals, is that correct?
Thank you

kubatp

28-01-2010 10:06:04

I have figured out this issue. In vertex shader simply change "normal" to "normalize(normal)" which will normalize the vector and will be the same for every mesh.

andyhebear1

31-05-2010 13:09:07

good work