5

I think I've solved implementation of rendering borders/outlines over meshes in Three.js, a technique many games use for highlighting objects/characters.

Diablo 1 and 3 for example
Diablo 3

Here are details and demo of my solution.

Now what remains to be done are animated meshes (for characters etc). The problem is, skinned mesh is animated with a vertex shader and I also used a shader to scale (displace) the mesh out along the normals. It might be pretty straight-forward but unfortunately my math skills are pretty much non-existent.


The problem

So to have the meshes scaled up AND animated in the shader, here are the two equations that I think need to be merged:

From the skinning shader:

mvPosition = modelViewMatrix * skinned
gl_Position = projectionMatrix * mvPosition

From the displacement shader:

mvPosition = modelViewMatrix * vec4( position + normal * offset, 1.0 )
gl_Position = projectionMatrix * mvPosition

Demo

Updated (with GoodGuy's equation): Here is the full code and demo on jsfiddle (javascript).
Here you can find the shader code itself (glsl).

The inner figure is regular skinned animation, the outline is the new equation which doesn't quite fit yet.

Community
  • 1
  • 1
Eskel
  • 795
  • 1
  • 8
  • 21
  • mvPosition = modelViewMatrix * (skinned + vec4( position + normal * offset, 1.0 )); seems to be fine to me, doesn't it? – GuyGood Apr 23 '14 at 15:02
  • @GuyGood It seems so :) You're awesome, thanks a ton! I was already looking for a freelancer to help me out. :D I'll test it and post the results. – Eskel Apr 23 '14 at 15:20
  • @GuyGood On closer examination, it seems the animation seems scaled down, like the range of motion is somehow diminished. You can see it when you set the offset value to zero. Any idea how to fix it? I'll update the example. – Eskel Apr 23 '14 at 15:32
  • well, i just hacked this in, the problem is that the walk animation and the difference between scaled and non-scaled is hard to see.... ;) So i already thought that this is not it :( Sorry. – GuyGood Apr 23 '14 at 15:42
  • hmm, after thinking about it, well i mean when the mesh gets thicker, the movement will get visibly dimished after all? I cant see any difference when I set the value to zero, sorry. Was just a quick idea, would have to think about the math going on ... O:-) – GuyGood Apr 23 '14 at 16:00
  • @GuyGood Here you can see the difference: http://jsfiddle.net/Eskel/RFbfJ/3/ – Eskel Apr 23 '14 at 16:03
  • @GuyGood Well thanks for trying, it was a really good shot. I think I'm a lot closer then before so I'm really grateful. :) – Eskel Apr 23 '14 at 16:05
  • 1
    Is this what you are looking for? http://jsfiddle.net/RFbfJ/4/ – WestLangley Apr 23 '14 at 16:15
  • @WestLangley Oh my god, yes, that's it! You are my hero! :) Thanks a lot. Please post it as an answer, so I can flag it. – Eskel Apr 23 '14 at 16:17
  • It is not technically correct, though. The normals need to be updated, too. See if you can research how that is done in your case. It should be `skinned.xyz + new_normal * offset` – WestLangley Apr 23 '14 at 16:23
  • 1
    http://jsfiddle.net/Nv7Up/ – GuyGood Apr 23 '14 at 16:24
  • Oh Sorry, Westlangley was faster, although my approach is a different one. I just added the scaled vertices in before the skinning happens... Anyway, cool :) – GuyGood Apr 23 '14 at 16:25
  • You're both incredible :) I wish I could credit you both, for the solution. Is it possible? Also do you think it has a place in the library? Something like an optional shader maybe, with this demo included. Or is the use case too specific? – Eskel Apr 23 '14 at 16:29
  • I would be interested in why the normals need to be updated, too. If @WestLangley can elaborate a short bit, would be nice. edit: no need for credit, WestLangley was the faster one who can even explain the math he is doing, lol :D – GuyGood Apr 23 '14 at 16:30
  • @GuyGood I think that is a valid approach, too, as long as the matrix transforms do not involve non-uniform scaling.... The skinning is a linear operator, after all, so you are effectively updating the normals. – WestLangley Apr 23 '14 at 16:32
  • @GuyGood I guess in a case when you want to have to work with the outline normals in some way, maybe with a fragment shader? (Which fortunately I don't need.) Anyway, please post the answer, you were first and submited your own complete solution. – Eskel Apr 23 '14 at 16:35
  • @GuyGood If the character raises his arm straight up, the normals need to point in a completely different direction. Normals have to be transformed, too. Eskel Can you do an experiment where the character is more animated? – WestLangley Apr 23 '14 at 16:36
  • @WestLangley Sure, it will take me some time, but I'll post a more animated example. Thanks for the explanation. – Eskel Apr 23 '14 at 16:41
  • After some thought, for what Eskel is trying to do, @GuyGood's solution is fine. However, in the future, if you are concerned about shading, and you are modifying vertices, then you need to be careful to properly modify the normals, too. http://www.opengl.org/wiki/Skeletal_Animation – WestLangley Apr 23 '14 at 16:54
  • @WestLangley I'm the worst animator ever :D (Not very accustomed to blender anyway) But here you go: http://jsfiddle.net/Eskel/Nv7Up/1/ I think it works just fine. He's a bit twitchy, but hey, the outline stays right on spot. Again thanks a lot for the solution and learning material. Please post some of those links as a solution, so I can give you some karma and move on. :) – Eskel Apr 23 '14 at 17:36
  • That's OK. You can post and accept your own answer. :-) – WestLangley Apr 23 '14 at 18:39
  • At least, cool you did not need to hire a freelancer for some "easy" shader stuf :D and glad it works. Looking forward to more questions ;) As i noticed you did not decide on the highlighting of objects using the emissive value of the material and instead use more passes. Looks cool, looking forward to some nice results with your game :) – GuyGood Apr 23 '14 at 20:24
  • @GuyGood Thanks :) I'm still deciding on the name and setting, but meanwhile you can find it [here](http://www.mrammor.com) and few months old demo [here](http://alpha.mrammor.com), it soon gonna get update with UI and multiplayer features. Also the outline problem isn't really solved yet, WestLangley made me realize another problem. Please take a look [here](http://stackoverflow.com/questions/23183507/outline-object-normal-scale-stencil-mask-three-js/23198184#comment35604642_23198184). – Eskel Apr 24 '14 at 10:13
  • If you're interested I'd love if you would get involved. It's fun and there are tons of challenges involved. :) Contact is on my profile here. – Eskel Apr 24 '14 at 10:21

1 Answers1

4

Thanks to WestLangley and GuyGood, here is the solution:

http://jsfiddle.net/Nv7Up/

mvPosition = modelViewMatrix * (vec4( skinned.xyz + normal * offset, 1.0 ))

One technical problem might be that normals are not updated. For details, read through the discussion thread below the original post.

Update for r73: http://jsfiddle.net/frh2d84d/4/

Eskel
  • 795
  • 1
  • 8
  • 21