Lux – an open source physically based shading framework

hi there,

after having published this topic to the shader lab thread and getting nice feedback so far i think it is time to officially release Lux – an open source physically based shading framework.

Why physically based Shading?
First of all physically based shading will give you much more convincing results than traditional lambert or blinnphong shading: No more fights with washed out specular highlights or boring dark areas: everything is shiny!
Second: psb will help you to get much more constant and predictable results under varying lighting conditions: Author once, use everywhere!

Why open source?
There are already some commercial solutions out there available at the asset store, but none of those is free, some even break other shaders. So it might be rather difficult for the community to develop and improve unity’s rendering capabilities. But that is the whole idea behind this framework.
And i hope that there will be a tons of shaders out there supporting Lux soon.

So any feedback, tips and tricks are highly appriciated.
And in case you find any bug just let me know.

Lars

Latest version: 0.07 (3/10/2014)

Test the webplayer (version 0.04)
http://bit.ly/1dAiHxN
Download the latest package (version 0.07)
http://bit.ly/1gmApq1

How does it work?
The framework is mainly based on the work of Sebastién Lagarde and Dimitar Lazarov:

http://blog.selfshadow.com/publicati…_slides_v2.pdf

It supports forward and deferred lighting, lightmaps and lightprobes and handles gamma and linear lighting – although linear lighting is more than a key to physically based shading.

The ingredients

Direct lighting

  • Specular: Blinn-Phong or Cook-Torrance (GGX Trowbridge Reitz)
  • Visibility: Schlick-Smith or Smith
  • Fresnel: Schlick-Fresnel approximation (deferred lighting only supports faked fresnel for direct specular lighting).

Ambient lighting

  • Diffuse Cubemap IBL
  • Specular Cubemap IBL (gloss values stored in mip chain) with fresnel term based on roughness and specular color
    Both cubemaps can be sampled in gamma and linear space. Support for RGB or RGBM (HDR) cubemaps.
  • Spherical Harmonics in case you disabled “Diffuse Cubemap IBL”
  • Ambient Occlusion controlled by texture input

The implementation

Deferred rendering
To make the shader work in deferred rendering i had to hack the "Internal-PrePassLighting“ shader, as i could not find another way yet to get the dotNL and especially the dot(h, lightDir) product. That is not as elegant as i would like to have it.
And as i had to „compress“ the spec value in the "Internal-PrePassLighting“ shader (log2) and decompress it in the lighting prepass function (exp2) in order to avoid wrong shaded spots in the center of the highlights, built in shaders will be broken (too less specular) when using deferred lighting. So i highly recommend to rebuilt all needed shaders using the Lux lighting functions – which is not that big deal i hope.

Ambient IBL
I did not spent much time on this part of the framework and it is pretty much straight forward using common rbgm decoding and a roughness based fresnel term on the specular distribution.
In case you disable ambient diffuse IBL the shaders will fall back to unity’s built in spherical harmonics.

Inputs
I have chosen an approach suggested by sebastién lagarde and only have a few parameters to feed the shader right now:
http://seblagarde.wordpress.com/2011…lighting-mode/

  • Diffuse color as texture rgb
  • Specular color as texture rgb
  • Roughness (alpha in specular color)
  • Normal map
  • Diffuse and specular ambient cube (most of the time passed as global textures by script)

And in case you miss parameters like metalness: Lux supports a metalness workflow since version 0.07.
There is only one singe shader right now supporting this workflow but it is really easy to change all existing shaders. I guess more shaders natively supporting metalness will follow.

Changelog
version 0.07
Terrain detail shaders
All errors fixed for dx9 and dx11.
Terrain shaders
Possible division by zero fixed.
Lux Internal-PrePassLighting shader
doubled “max(0, dotNL)” removed.
LuxLightingAmbient.cginc
“o.Emission = 0.0;” added to make SH lighting work with the Lux diffuse shaders (Lux diffuse shader or the terrain detial shaders e.g.)
Metalness Shader
added
Dualforward lightmaps
docu entry added – so easily find out how to enable dualforward lightmaps in forward lighting
Deferred lighting
Disabling specular ambient lighting won’t let the faked fresnel go crazy in deferred lighting mode anymore
Treecreatorleaves shader
fixed

version 0.061
Lighting
blinn phong: visibility term now is more robust (by adding saturate)
cook torrance: sign corrected, no more magical numer needed to make deferred match forward
Terrain shader
normal blending enhanced
Detail shader
normal bending corrected

version 0.06
version 0.06 is a major update because it introduces a Cook Torrence based approach as second lighting model next to Blinn Phong.
In order to make it possible to switch between these models I had to rewrite some parts of the framework. i took this chance to make the naming a bit more flexible and descriptive:
“LuxLightingPhong.cginc” changed to “LuxLightingDirect.cginc”
“LuxIBL.cginc” changed to “LuxLightingAmbient.cginc”

Surface Shaders the name of the Lux lighting function changed to “LuxDirect”:
#pragma surface surf LuxDirect noambient
the name of the direct lighting functions include changed:
#include “LuxCore/LuxLightingDirect.cginc”
A new pragma makes it possible to switch between the lighting models:
#pragma multi_compile LUX_LIGHTING_BP LUX_LIGHTING_CT
Writing to o.Specular has changed to a function call:
o.Specular = LuxAdjustSpecular(spec_albedo.a);

Minor changes and fixes

  • VertexBlend shaders added
  • Lux ambient lighting: if “diffuse cube IBL” is disabled the shader won’t add ambient lighting based spherical harmonics in case the object is lightmapped.
  • tree creator redertex shaders fixed but this will be an ongoing process…
  • terrain shader first pass: fixed for cook torrence using complex blending for detail normal

version 0.05
Example shaders !!! important !!!
writing to o.DeferredFresnel changed to:
o.DeferredFresnel = exp2(-OneOnLN2_x6 * max(0, dot(o.Normal, normalize(IN.viewDir) ))); as it could cause some lighting artifacts on dx9 / dx11. now it is even a bit faster, You should do so in all your individual shaders too.
Ambient Lighting (LuxIBL.cginc)
spec ambient IBL changed from spec_albeo.rgb and spec_albedo.a to o.SpecularColor and o.Specular – just to make it more flexible
Lighting (LuxLightingPhong.cginc)
optimized “Final Composition” (forward lighting)
Tree creator shaders added
version 0.046
Ambient Lighting (LuxIBL.cginc)

  • Fixed errors from version 0.045.
    Shaders may declare “#define NORMAL_IS_WORLDNORMAL” to skip the calculation of the worldnormal and speed up rendering.
    Used e.g. by the terrain grass shaders as here normal equals worldnormal.
    Lux terrain shaders
  • Improved normal blending between different shader passes.
    Added a the possibility to use a second normal map on detail texture number 3 to hide tiling artifacts on high frequent and bumpy textures such as rock.
    Lux grass and vertex lit shaders added

version 0.045
Ambient Lighting(LuxIBL.cginc)

  • Due to a bug in unity terrain materials i had to make the “#ifdef DIFFCUBE_ON” a bit more complex.
    Now diffuse ambient IBL can be activated per material using the material inspector or globally for shaders in which the keyword “USE_GLOBAL_DIFFIBL_SETTINGS” is enabled.
    Sorry for that mess.
    Lighting (LuxLightingPhong.cginc)
  • color output.alpha is reduced to: c.a = s.Alpha;
    as long as anybody can tell me what the rest sould be good for i will keep it this simple.
    Lux terrain shaders added
    Documentation added
    DontnodGraphicChartForBlinnMicrofacet look up chart added
    version 0.044
    shader folder structure refactored
    -“Resources” is now subfloder of “LuxCore”
    ambient lighting (LuxIBL.cginc)
  • specular ambient lighting: added alternativ fresnel calculation which would give you only colorized specular reflections to match skyshop (deactivated by default, you will have to edit the cginc)
    example shaders
  • advanced detail shader added
  • parallax mapping shader added
  • material test shader: small fix

version 0.043
ambient lighting (LuxIBL.cginc)

  • specular ambient lighting fixed
    example shaders
  • material test shader added which lets you adjust roughness and specularColor within unity

version 0.042
ambient lighting (LuxIBL.cginc)- Spherical Harmonics added: In case you deactivate “diffuse Cube IBL” in the material inspector the shader falls back to unity’s SH lighting. Use this function if you want to make the shader react to lightprobes or speed up rendering.
This makes the old Lux Lightprobes Shader obsolet (so i have removed it from the package)

  • Ambient Occlusion added: now you may add an Ambient Occlusion texture which controls diffuse and specular ambient lighting
    forward lighting
  • late dotNL to get rid of most artifacts on backsides and speed up rendering
    surface shaders
  • o.DeferredFresnel is only written #if defined(UNITY_PASS_PREPASSFINAL) to speed up forward rendering.
    see e.g.: “Lux Bumped Specular.shader”
  • sampler for ambient occlusion added
  • sampler for diff Cube IBL and spec Cube IBL won’t be declared unless you activate diffuse and specular IBL lighting
  • #pragma multi_compile LUX_AO_OFF LUX_AO_ON” added to let you control the use o ambient occlusion via the material inspector

version 0.041
Forward lighting

  • fixed for dx11

version 0.04
deferred lighting

  • internal prepass lighting shader fixed for dx11

version 0.03
deferred lighting

  • faked fresnel added based on n_dot_v (direct specular lighting)

version 0.02
deferred lighting

  • refactored
  • visibility term added
  • fresnel fixed (direct lighting): fresnel according only to ONE directional light, light position has to be passed by script. see: “Lux Bumped Specular” shader
    forward lighting
  • refactored
  • visibility term fixed
    lightmaps
  • lighting fixed when using lightmaps or lightprobes

version 0.01
initial release

2 Likes

This is super impressive. Thanks for sharing it. Can I ask why is the version number so low on it. 0.02 seems a bit harsh for something that seems pretty feature complete. What features do you have planned for version 1 ? Also would it be possible to add refraction to this on transparent shaders like the glass shader in unity has or a density option or something like that or does the phisically based nature of them make that more tricky ?

hi ian,

thanks for your answer.
the version number is so low because i still have to find a way to integrate correct fresnel into deferred shading ( now it is just calculated according to your main light position) and work on other features such as ao which is not that big deal.
it would like this to be(come) an open source framework so i a bit of depend on the feedback of the community. the more i get the faster there will be a stable version i would call 1.0.
i haven’t thought about refrection yet because it will be relayed on “grabpass” and is mainly a forward feature only (transparent). right now i am much more focused on deferred lighting and giving you a rock solid and flexible solution for that.
and as it is open source: refrection could be done by someone else… :wink:

lars

Hi Larsbertam1,

thanks a lot for sharing, is a really interesting opportunity for the community.
My shader programming skills aren’t good enought until now, but I will try to improve fast. :slight_smile:

Cheers
Kenshin

hi there,

the last version of lux shipped with a “correct” fresnel for just ONE directional light when using deferred lighting.
i am still working on a correct fresnel for all lights in deferred lighting but meanwhile i have finished a version using some kind of “faked fresnel” – well: it is not that bad and at least as good as skyshop’s fresnel – that work with all kind of lights and does not need any input by script.

so get this version here:
http://bit.ly/1b4jir6

lars

I’ve not tried it yet but i will try to soon, this is a very generous and good idea, i hope some of the community do come along and contribute, i don’t have the shader skills to add anything sadly

thank you.
and in fact there is some help from and discussion with the community. unfortunately it is mostly bound to personal contacts.

but if you would like to help there are also other things to do not only shaders like a nice and handy cubemap tool…

lars

what kind of tool that should be…?

maybe you can also add some other points as todo-list somewhere ?
and use github?

that tool would let you create convoluted diffuse cubemaps and mip mapped specular cubemaps containing the different reflections according to the roughness of the material in a mip chain. right now you can only create those cubemaps when either using skyshop (commercial on the asset store) or cubemapgen from ati (free but win only and not integrated into unity).
a very good starting point might be this video:
http://www.youtube.com/watch?v=vwjNc9FS_WI
it is the talk by nicolas (co founder of unity) at unite 2013 and he shows a complete cubemap solution including some code.

next to that any help on the shader side of course i highly appreciated: finding bugs, doing some more optimizations.

the last public version of lux introduced “faked fresnel” for deferred rendering which is quite nice but not really physically accurate.
right now i am working on a new version (nearly done) which brings “correct” fresnel even to deferred lighting but it is not written as surface shader.
as i had to dig very deep to make it work within the unity rendering pipeline it is pure cg – and a real shader monster.
this shader definitely will break any other deferred shader as i had to make some very major changes to the shared lighting prepass function.
so all shaders will have to be rewritten… any help here would be great as well.

lars

Collected the script pieces from this page,
http://framebunker.com/blog/static-sky-unite-presentation/

but it still has some missing parts/variables, also the shader in this package is bit different still…

(source attached, code has couple FIXME notes, compare with the code in that pdf ^ )

1488116–82911–$cubemapper1.unitypackage (40.9 KB)

hi mgear,

thanks for posting the script but some more words about how to use it would be very helpful :wink:

lars

Its editor script, creates menu item: Test/Cubemapper

First create new cubemap in project window (and enable all those 3 options for it [×]mipmaps, [×]reading, [×] …)

Then start the script, it opens wizard window: assign main camera, target cubemap, press create.

And nothing really happens…since there is something missing :slight_smile:

hi there,

today i was asked by a friend to have a look at skyshop and alloy and compare their functionality to lux.
and although i just had a quick look at the shaders that ship with those packages i try to write a short summary.
it might not be perfect, it might not even be correct so i would appreciate any comments on the following statements:

diffuse
skyshop: lambert
alloy: lambert
lux: lambert

specular
skyshop: normalized blinn phong, spec power 0 - 256
alloy: normalized blinn phong, spec power 4 - 1024
lux: normalized blinn phong, spec power 0.25 - 2048

visibility
skyshop: none
alloy: none as far as i can say – although there is a function whose name makes one believe that there is some kind of visibility term…
lux: schlick-smith

fresnel
skyshop: faked fresnel (in deferred – based on NdotV)
alloy: none (in deferred)
lux: faked fresnel (in deferred – based on NdotV)

am i right?

lars

These shaders look really nice, and are actually perfect for what I am doing. Just a question though, what’s the license on these?

Thanks !

hi there,

i am not into licensing – but i would like it to be open source.
so everybody can use the lux core to write ones own shader, use these in free and commercial projects, give them away for free or even sell those shaders on the asset store.
in order to keep all lux based shaders compatible i think it is best to not “allow” to change the lux core files and publish those. but of course i am open to any improvements and will try to incorporate those into the official release.
so what license would fit best here?
any tip will be appreciated.

lars

Well I am a big fan of MIT / BSD / Png / Zlib type licenses, where basically you say ‘this is the product; you can use it however you want, don’t take credit for making it, don’t blame me for anything that goes wrong.’ (read up on the individual licenses for the specifics).

There is also GPL and L-GPL. I don’t touch anything with GPL that I need to integrate into code. I am cautious about L-GPL because I don’t fully understand it and what it requires me as a user to do, but the advantage to you is that the L-GPL asks anyone that makes changes to submit the changes so everyone can benefit.

It’s up to you to decide at the end of the day, but you should put a license on it if for no other reason then to protect yourself from any damages.

This might help you:
http://oss-watch.ac.uk/resources/licdiff

you are absolutely right.
and publishing lux under a certain license should make thing pretty clear and easy to understand.
so i will have a look at those licenses and pick the right one – hopefully.

lars

after a first glance i would go with MIT or zLIB.
any comments on this?

lars

I think MIT or zLIB could be the best for Lux since it overide internal-prepass, but are you sure you (or anyone that help creating lux) don’t want to be credited? I know that it’s not a must, but maybe there’s some developer that at least want to put the lux author name in the Thank’s To section :smile:.

I like MIT and zlib, they are easy to work with. In regards to the point rea mentioned, it seems there are some variations of MIT where that is the case, but neither the standard MIT license nor the zlib license say you can’t give credit to lars for using his work. The modified BSD license on the other hand does say that you can’t credit lars to promote your work, without permission.

The interesting thing is that zlib has a clause that says, while you don’t have to give credit, you can’t take credit either (“1. The origin of this software must not be misrepresented…”).

Because you want others to work with your work and make shader contributions, it might be easier with the MIT license where the author specifics are less of a sticking point.

Source: