Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  3. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Scriptable render loop with single pass forward lighting

Discussion in 'Graphics Experimental Previews' started by misharg, May 31, 2017.

  1. misharg


    May 30, 2017
    Hello, is there a way use scriptable render loop to use forward lighting with the 4 closest point lights per objects like in the current rendering in Unity? For instance with 4 lights per object:
    Screen Shot 2017-06-01 at 3.41.26 PM.png

    Instead of being limited to a number of lights globally like the Basic/Lightweight scriptable render pipeline? For instance 4 global lights:
    Screen Shot 2017-06-01 at 3.55.25 PM.png

    Specifically, I'm looking into implementing single pass forward lighting using the scriptable render loop for low end mobile devices (i.e. IPhone 5). Unity's built in render pipeline sets shader properties (unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, unity_4LightAtten0, unity_LightColor) and keywords (VERTEXLIGHT_ON) per object based on the closest lights for that object.

    However I'm having trouble finding something similar for the current scriptable render loop examples. BasicPipeline & LightweightPipeline both set lighting data globally which causes performance and graphics issues (computing lighting for lights that are too far and being limited to 4 lights in the scene vs 4 lights per object). HDRenderPipeline seems to be using compute shaders for deferred lighting but, as far as I can tell, Unity doesn't support compute shaders for low end mobile devices and forward is a better option. Is there something I missed in the RenderPipelines that would help me?

    Alternatively, is this data related to LightIndices? RenderConfiguration would make sense as a place to enable per object point light properties as it does so for lightprobes, reflectionprobes, lppvs, and lightmaps. RenderConfiguration can also can enable lightIndices so I'm hoping that this is for per object lighting data. CullResults.GetLightIndicesCount also returns a number that depends on the number of objects and point lights in the scene. However if this is setting properties in the shader, what are those properties and how can I access them? The closest thing I could find was CullResults.FillLightIndices(ComputeBuffer computeBuffer) but again, Unity doesn't support compute shaders for low end mobile devices.

    Can you please provide some direction into what to look into?

    Edit: Added a details with pictures
    Last edited: Jun 1, 2017
    forestrf likes this.
  2. phil_lira


    Unity Technologies

    Dec 17, 2014
    Hi misharg,

    You're on the right track. The basic steps to do it are:

    1) Enable RendererConfiguration.ProvideLightIndices flag in DrawRendererSettings. This will tell unity to write the light offset and count for each object on a float4 unity_LightIndicesOffsetAndCount. (x = offset, y = count)
    2) Fill the light index buffer and assign to shader by using the SetGlobalBuffer interface.
    Code (CSharp):
    1. ComputeBuffer lightListIndices = new ComputeBuffer(size, sizeof(uint));
    2. ...
    3. cullResults.FillLightIndices(lightListIndices);
    4. ...
    5. commandBuffer.SetGlobalBuffer("globalLightListIndex", lightListIndices);
    3) Now in your shader declare the required buffer and uniform and use them to index the global light list.
    Code (CSharp):
    1. half4 unity_LightIndicesOffsetAndCount;
    2. StructuredBuffer<uint> globalLightListIndex;
    3. ...
    4. // for the ith light
    5. int globalLightIndex = globalLightListIndex[unity_LightIndicesOffsetAndCount.x + i];
    As off now, as you noted, the only way to fill the light indices is with CullResults.FillLightIndices, which requires a StructuredBuffers/SSBO. I'm adding an option to fill indices for low end devices (ES 2.0).

    I'll update LightweightPipeline (and the Basic one for sample sake) in the next following days.

    Best Regards,
    SKoptev and hippocoder like this.