Giter Club home page Giter Club logo

unity-fake-character-shadows's Introduction

Fake Character Shadows

Implementing multiple lighting shadows in a pixel shader without relying on shadow maps for shadow effects.

Fake.Shadows.mp4

Demo (Available on Web, Mobile and MetaQuest - Powered by Spatial Creator Toolkit)

https://www.spatial.io/s/Fake-Character-Shadows-65ed3e7bd6afc7e93521bf59

Problem of Shadow Mapping

Shadow Mapping, a common technique in realtime-graphics provides an accurate method for implementing shadows, but it comes with clear limiations.

In the art concept above, if there is no strong main light and multiple light sources need to be utilized, the effectiveness of Shadow Mapping diminishes significantly. In the absence of a primary light, the Shadow Mapping techniques becomes less effective and results in unnecessary shadow map computations.

Alternative Approach


(Images from Polycount.wiki http://wiki.polycount.com/wiki/Decal)

Considering past experiences with Blob Shadows in casual games for web and mobile devices where precise shadows are not always necessary and approximations are acceptable, I started exploring a simple idea applied in the pixel shader of background objects. Starting from this concept, I initiated the shader sketch.

(shader sketch 1)

fakeShadows.mp4

(shader sketch 2)

FakeShadows22.mp4

Implementation

Shader

Below is the shader code that calculates the shadow approximately. As you can see it's very simple and very approximate. Even though they are applied per light, it's still very light.

half CalcFakeShadowPerLight(half4 light, half3 playerPos, half playerRad, half3 posToPlayer, half3 posWS)
{
    // Calc dot
    half3 playerToLight = normalize(light.xyz - playerPos);
    half d = dot(posToPlayer, playerToLight);
    float r = 1 - playerRad;
    d = saturate((d - r) / (1 - r)); // remap range: r~1 -> 0~1

    // Attenuation
    half distLightToPos = distance(posWS, light.xyz);
    half atten = 1 - saturate(distLightToPos / (light.w + epsilon)); // Apply light radius
    atten = atten * atten; // Inverse Square Law

    // Adjust attenuation and reverse
    return 1 - saturate(d * atten);
}

Breakdown

  1. First dot playerToLight and PositionToPlayer.

  2. Adjust it with player radius.

  3. Calculate attenuation using distance.

  4. dot * attenuation

  5. One minus the result

Runtime Script

Needs to fetch lighting information such as light position and radius.

Utilizes Unity Physics.OverlapSphere (considered more optimal than any of C# script approach). FakeShadowsManager.cs#L61 Also uses global shader variables to avoid accessing all meshes and materials of the environment. FakeShadowsManager.cs#L85-L87

Results

Fake.Shadows.mp4

Works reasonably well. This shadow is applied in a game (which will be shared soon), and the game can run on 10-year-old mobile devices without serious heat issues

Advantages

Very low draw call overhead by not using shadow maps.

Disadvantages

Increased pixel computation load. In my experience, the impact on performance from the load of a single pixel complexity is low. On contrary, more load is generated from drawing more pixels with alpha-blending as surfaces overlap.

Improvement Ideas

  • Basically it's point shadows so this can be improved by utilizing capsule shadow.
  • For a simple process, the environment shader uses ShaderGraph, which is limited to modify lighting. So fake shadow is applied to Albedo and AmbientOcclusion which is not accurate way to calculate shadows. To have more accurate lighting, it will need to be applied to lightmap sample result.
  • If you have any improvement ideas, please share them in the Issues section.

unity-fake-character-shadows's People

Contributors

wonkee-kim avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.