Game Development Community

Solid Line Around Objects Silhouette

by Greg G · in Torque 3D Professional · 06/02/2009 (3:40 pm) · 55 replies

Basically, I want a solid line drawn around an objects silhouette when it is selected. I found an example of an outline shader in render monkey but it uses a "screen space quad" and I'm not exactly sure how replicate this in Torque3D or if I should just be using the PostFX system to render the pixels on the screen.

Some guidance on this would be appreciated.
#21
06/07/2009 (4:01 am)
Ah, I get you now. So for that, probably the best way would be to render each model, using a color *unique* to that one model, to a single texture. Then apply a Sobel edge detection shader to that texture.

Example:
img26.imageshack.us/img26/355/sobeloutline.jpg

The backface technique, where you render the same model twice, but larger with a solid black color and flipped normals the first time, while easy to implement, doesn't look very good in my opinion. Especially on complex models.
#22
06/07/2009 (4:52 am)
That's exactly what i'm after. Now, this could potentially be on EVERY object in the entire scene, its not going to be a common situation but at the same time I don't want my frame rate to take a massive hit either. Is the "back face culling technique" going to be much more efficient than the sobel shader?

It seams like the sobel shader would be significantly less efficient.

Really that's my deciding factor between the two because we could implement either. I just want to make sure that its as optimized as possible since its going to be part of our selection system and I don't want it lagging down the engine.
#23
06/07/2009 (5:08 am)
If it could potentially be on every object in the scene, I would go Sobel. Considering the backface culling technique effectively doubles the amount of polygons you need to render, I don't think it will be leaps and bounds more efficient than the Sobel technique, for one model atleast.

Sobel is also not affected by scene complexity, so it would *definitely* be better for a large volume of models than backface culling.

It also gives nicer looking results, which is why most cel-shaded games these days use a post image-processing shader as opposed to a second render of the model colored black. Fat Princess is one such game that comes to mind.
#24
06/07/2009 (5:13 am)
Great, do you have any advice on how to get the first render target texture where the models are each a different texture? Is there some kind of name for that or something? If not that's fine I will talk with my programmer at work tomorrow now that I know exactly what we have to do but if you have any good tips to help get me started that would be great.

Thanks so much for your help I learned a ton!
#25
06/07/2009 (5:19 am)
It's basically like Tom said earlier (he explained it in a bit more detail)

Setup a render target, and render every model that is selected to that render target in a flat color (no lighting, etc.). Make sure the color is unique to that model. Then pass that render target to the shader so it can process it and generate the outlines. Then you just need to multiply the RGB values of the scene with the edge coloring, so the black areas (outlines) will show up but the white areas won't.
#26
06/10/2009 (11:33 am)
So I have been trying to get a basic version RenderPrePassMgr that will only render objects with a certain ID.

The problem I am having is that I can't figure out how to pass the SimObject ID along with the mesh. Tom said:

Quote:Add a SimObjectId to MeshRenderInst and set it from TSMesh when it creates and submits the render instance. This allows us to identify the mesh being rendered.

I added the a variable to store SimObjectId in MeshRenderInst, but I don't think I can set it in TSMesh because I no longer have the object ID since TSMesh only deals with meshes and not "objects".

So I then thought I would need to go back to a point where I had access to both the mesh and the ID like TSStatic.

Since a single object can have multiple meshes I suppose I will need to add the ID to each mesh in an object, but this is where I am stuck. I can't figure out how to loop through the meshes to add the ID.

If anyone has a suggestion on how to do this please let me know.
#27
06/10/2009 (1:35 pm)
Quote:
Since a single object can have multiple meshes I suppose I will need to add the ID to each mesh in an object, but this is where I am stuck.

I'm doing the same thing right now, let me help you there. Just make sure you share the code if you get there first. ;)

What I did was I passed object pointers instead of ids to avoid all the hassle with object and ghost ids.

So, first, in shapebase when you create a new TSShapeInstance in ShapeBase::onNewDataBlock, add this to the TSShapeInstance constructor as a third parameter.

Those constructors call buildInstanceData, so you will need to add that SceneObject * parameter there as well (I used shapeOwnerObject)

This is where you can set mesh ownership. Below the forceHidden assignment, I added the following:

// >>>
		if (shapeOwnerObject) {
			for (U32 j=0;j<obj->numMeshes;j++) {
				TSMesh * cmesh = objInst->getMesh(j);
				if (cmesh)
					cmesh->setMeshOwner(shapeOwnerObject);
			}
		}
		// <<<

As you see, I declared setMeshOwner, but also getMeshOwner and a SceneObject pointer to store the mesh owner in TSMesh. I will use this to show the current selection, so I don't need to be able to show multiple objects, but it would definitely be more useful to handle an array of allowed objects there.

I hope that helps a bit. And I hope I'm not messing things up too much, hehe.

Edit: On another note, I am becoming sure that I'm messing up. I shouldn't pass something through mesh to get stuff to MeshRenderInst. I'll see where that leads me, this is new territory for me. :)
#28
06/10/2009 (3:38 pm)
Thanks a bunch. I'll try and have a go at this later in the day. It does seam like there might be a more direct way of doing this...
#29
07/04/2009 (1:36 am)
@Konrad, as far as i see from the code, mesh is shared by all the tsShapeInstance which look the same, but meshRenderInst is unique, maybe you can use a renderInst owner rather than a mesh owner.
#30
07/04/2009 (4:57 am)
@Huan: Yes, you are right. I've taken a different approach which works with your idea. I'm still not done, but I am now able to identify the instance that needs to be put into my own renderbin.

I'm porting my every change to Beta 3 now. Soon I'll get back to this when I'm done and make it a resource asap.
#31
07/04/2009 (7:54 am)
It is going to be a big one, Konrad. Can't wait to see...
#32
07/04/2009 (9:00 pm)
@Konrad - that's great! I need this also - I need to render a red highlight around items that are "selected". I even think this should be integrated into stock T3D, and added to the world editor. (which should then drop the bounding boxes completely and select by a straight raycast).
#33
07/05/2009 (5:28 am)
@Jaimi: the selection already uses mesh raycasts. You can easily confirm this when using the material editor in the PureLIGHT demos, which have several overlapped models which would be hell to select with plain bounding boxes.
#34
07/05/2009 (8:25 am)
@Manoel: Well, then I'm seeing some selection goofiness with DTS shapes. :)
#35
07/07/2009 (7:31 am)
Hey guys,

I'm trying to make the outline selection thing work, but something changed in Beta 3 that causes Matt's outline postfx to not render correctly for me. Can someone please give me a hint as to what change might be causing this?

Thanks in advance.
#36
07/08/2009 (2:51 am)
Yes, i tried in beta3, it didn't render correctly for me either, but runs perfectly in beta2.

And another problem, all postfx shaders do not work in Basic Lighing mode, both in beta2 and beta3.

By the way, the forum's pagination seems also doesn't work correctly, the last thread in page 1 is 07/07/2009 (2:17 pm), and the first thread in page 2 says it was 07/07/2009 (3:34 am), so nearly half day's threads gone. I came to this thread by search. you guys have the same experiences? Or it's just my explorer's cache problem.

edit: Any method to add one thread to my watching list?
#37
07/08/2009 (6:27 am)
Quote:edit: Any method to add one thread to my watching list?

check the "Notify me of any replies" checkbox at the top of the thread
#38
07/08/2009 (6:19 pm)
That's useful, thanks Jaimi.

My post will make this thread visible again, hehe.

Edit: Everyone see post #35.
#39
07/10/2009 (6:14 pm)
@Konrad, I don't know if you find what's the problem, in case you didn't, a simple fix should be enough.

In edgeDetectP.hlsl, change this line
prepassUncondition( tex2D(prepassBuffer, uv) );
to
prepassUncondition( prepassBuffer, uv );

That's it.
#40
07/12/2009 (8:09 am)
@Huan: many thanks, I'll give that a try!