Jump to content

Need help for fur rendering


Recommended Posts

Hi everybody !


I'm trying to do a ShaderMaterial that renders fur.

Here is how it looks right now.


It's starting to look good, but I still have some issues with it :

  • Each layer of fur is rendered using an instance of the object. I have some background of making shaders in Unity3D and I like the way we can do multi-pass shaders, is there a way to do the same with babylon or my instance system the only one ?
  • To render smoothly the material needs to be alpha blended, but then it doesn't write the depth. But in this case, I have issue when multiples "fur faces" overlay (try rotating the view in the link to overlap the fur at different distances on the object). I think the solution would be to have alpha blending and alpha cutout enabled at the same time (cutout to write in depth buffer and blending for nice effect) but it seems that if I enable both the alpha cutout is ignored (no "define ALPHATEST" in generated shader)


I still have some work to do on supporting dynamic lights and stuff, but the two issues here are really blocking me.


Also, I've had to add some exceptions in the ShaderMaterial attributes I pass to render the instances like listed here. Let me explain :

The effect needs to work on smartphones, and I've discoverd that on my smartphone (Galaxy Note 2, Android 5.1.1, Firefox) doesn't support GPU instancing. I had to check this using engine.getCaps().instancedArrays != null, and if false pass the uniform "world" instead of the 4 "world[n]" attributes. It was quite a funny thing to find why the shader wasn't working ...  That's the reason why a multi-pass shader would be useful.


If somebody has some answers to my issues, any help would be greatly appreciated!



Link to comment
Share on other sites

Hello #define are not supported by ShaderMaterial.


You have two options here:

- Use differents shaders and then select the right one at runtime

- Create a custom Material (by inheriting from Material). This is more advanced but you will have complete control. You can almost copy/paste code from ShaderMaterial: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/babylon.shaderMaterial.ts 

Link to comment
Share on other sites

Ok option 3 is coming :)


You will be able to do this in the next commit:

	var outMaterial = new BABYLON.ShaderMaterial( name , scene, shaderPath,					{							attributes: matAttributes,							uniforms: matUniforms,							needAlphaTesting : true,							needAlphaBlending: true,							defines: ["#define option1", "#define option2"]					});
Link to comment
Share on other sites

Hi ReMix,


Your shader is awesome. Fur always looks nice!


Have you tried using only alpha cutout meshes for this effect? from a distance, it may look sufficiently nice and not require any headache with alpha blend rendering order. Also, you can try keeping your meshes alpha blended and using the alphaIndex property, see: http://doc.babylonjs.com/tutorials/Transparency_and_How_Meshes_Are_Rendered#alpha-index


There is no such thing as multipass shaders in WebGL (yet). Rendering several meshes requires making several rendering calls, unless you merge all your identical meshes in one big buffer and then, through clever use of attributes and uniforms, define which part of the buffer belongs to which pass, etc.  :o


Hope that helps in any way.

Link to comment
Share on other sites

Thanks for the hints and answers !


I've tried to optimize a bit the effect by moving some of the vertex deformation to javascript by generating a new mesh with the desired amount of fur layers (instead of instances) and offsetting the vertex positions. The layer "index" is stored in the vertex colors.


But now I'm trying to make this work on mobile, and for some reason the demo that you can see here is extremely slow.

I've disabled a bunch of features in the fragment shader (normal map, specular, rim lighting) and moved some calculations from fragment to vertex. Also, no more alpha blending but alpha test instead.


Still, I think I have less then 5 fps (the debug layer on my phone says 0, but I can see it's a bit more though).


I really don't know why it's so slow, any help ?


EDIT : Well, even when displaying the "fur object" with the standard shader it's slow, what could be the cause ?

Link to comment
Share on other sites

My device is a Samsung Galaxy Note 2, a bit old but I think it still has a pretty decent GPU.


The same scene with only the "skin" plane (so, a simple texture plane with standard material) runs smoothly. But as soon as I duplicate the mesh to have the fur layers, the fps drops (but still under 100 vertices and only 2 draw calls).

Here is this test scene, it's the fur scene but with a standard material applied on the layers. It runs at about 5fps on my phone.

Link to comment
Share on other sites

Is it worth trying, rather than looping through the verts for each layer etc, taking the original plane mesh, then using SubMesh functionality, and SubMesh.clone() to build up the layers..  I think submesh is optimised for fast access ( for octree use etc ) so it may be that some small performance gain could be leveraged out of it..

Link to comment
Share on other sites

To be sure I tried generating fake fur layers by instancing my object (a base plane) multiple times (16). And even with the standard material, this simple scene is still extremely slow.

I now have absolutely no idea why it's so slow on mobile, is this normal ?


EDIT : Here is the mentioned scene : 17 planes (original + 1 clone + 15 clone instances ) rendered with default material, and still slow on mobile.



I found the more I have objects in the scene, more the fps drops. Same when duplicating polygons in the fur mesh.

I really don't understand why this is happening, the scene with the red spaceship featured on the babylonjs homepage runs at arount 15fps on my phone, and has more vertices and more objects.


Please great god Deltakosh, help me :( .

Link to comment
Share on other sites

It seems that your mobile is fillrate limited which means that the pixel shader seems to be the limitating factor.


The spaceship works at 15fps because the number of pixel drawn is limited. In your case every layer is almost fullscreen which means that the GPU needs to render 16x480x840 pixels (I have no idea about your true resolution of your phone but you get the point :))

Link to comment
Share on other sites

You seem to be right, I tried placing the camera further, and it runs better. (btw, the resolution is 1280x720)


So I have no other choices than avoiding to see this from too close ? Or draw less layers (but that makes an ugly effect) ?


That's sad :(.


An other option I would have is to draw the fur with only one mesh like on this demo. I've never done a raymarching shader, but it's not impossible. The only thing I'm afraid of is the even this would not help me with perfs, this demo also runs at about 4 fps in fullscreen on my phone :( .

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...