Search Unity

Spherical Harmonic Debug Shader

Discussion in 'Shaders' started by alleycatsphinx, Oct 25, 2012.

  1. alleycatsphinx

    alleycatsphinx

    Joined:
    Jan 25, 2012
    Posts:
    57
    Curious about spherical harmonics? This might help! Save this script as a shader and apply it to a high poly sphere at the origin. For bonus points, uncomment the line that uses the color as the vertex position to see the shape of the harmonic.

    Feel free to come up with awesome stuff once you're done.

    Shader "Spherical Harmonic" {
    Properties {
    _SHAr ("First Order Harmonic", Vector) = (0.0,0.0,0.0,0.0)
    _SHAg ("First Order Harmonic", Vector) = (0.0,0.0,0.0,0.0)
    _SHAb ("First Order Harmonic", Vector) = (0.0,0.0,0.0,0.0)

    _SHBr ("Second Order Harmonic", Vector) = (0.0,0.0,0.0,0.0)
    _SHBg ("Second Order Harmonic", Vector) = (0.0,0.0,0.0,0.0)
    _SHBb ("Second Order Harmonic", Vector) = (0.0,0.0,0.0,0.0)

    _SHC ("Third OrderHarmonic", Vector) = (0.0,0.0,0.0,0.0)
    _A ("Alpha", Float) = 0.5
    }

    SubShader {
    Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    Blend SrcAlpha OneMinusSrcAlpha
    Cull Off
    Lighting Off
    ZWrite On

    Pass{
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #pragma exclude_renderers
    #pragma target 2.0

    #include "UnityCG.cginc"
    #include "Lighting.cginc"

    uniform float4 _SHAr;
    uniform float4 _SHAg;
    uniform float4 _SHAb;

    uniform float4 _SHBr;
    uniform float4 _SHBg;
    uniform float4 _SHBb;

    uniform float4 _SHC;

    uniform float _A;


    struct appdata_t {
    float4 vertex : POSITION;
    fixed4 color : COLOR;
    float3 normal : TEXCOORD0;
    float4 tangent : TEXCOORD1;
    };

    struct v2f {
    float4 pos : SV_POSITION;
    fixed4 color : COLOR;
    };

    v2f vert (appdata_t v)
    {
    v2f o;

    UNITY_DIRBASIS;

    //This is the spherical harmonic lookup, it takes in the world normal and spits out the appropriate value in that direction
    //It comes from appendix 10 of Peter Pike Sloan's paper "Stupid Spherical Harmonic Tricks"
    //It's a bit more complex than the simpliest transform so it can be more efficient
    //http://www.ppsloan.org/publications/StupidSH36.pdf

    //It takes 12 coefficients (the numbers in the _SHA,_SHB and _SHC vectors) multiplies them against eachother to construct the harmonic
    //Each coefficient represents a cosine wave (which in turn are used to describe the sphere, axis by axis)
    //Each level _SHA - _SHB etc divides the sphere into two sub spheres, and each contains more detail (higher frequency data) about the final wave/sphere

    //It can be thought of as sound
    //Each seperate frequency is a different pitch, and the final sound is all these pieces blended together

    float4 wN = v.vertex; //Here I'm using the vertex position since this is for a sphere around the origin
    //It's very similar to a fourier transform, but across the surface of a sphere
    half3 x1, x2, x3;

    // Linear + constant polynomial terms
    x1.r = dot(_SHAr,wN);
    x1.g = dot(_SHAg,wN);
    x1.b = dot(_SHAb,wN);

    // 4 of the quadratic polynomials
    half4 vB = wN.xyzz * wN.yzzx;
    x2.r = dot(_SHBr,vB);
    x2.g = dot(_SHBg,vB);
    x2.b = dot(_SHBb,vB);

    // Final quadratic polynomial
    float vC = wN.x*wN.x - wN.y*wN.y;
    x3 = _SHC.rgb * vC;

    float3 shC = x1 + x2 + x3;

    //Setup the vertices
    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

    //the vectors the rgba colors also work as xyzw in space (color is a space, afterall...)
    //i.e. positive and negative red translates verts left and right along the x axis
    //o.pos = mul(UNITY_MATRIX_MVP, float4(shC.rgb, 1.0f)); //Comment this in to see the shape of the spherical harmonic

    //Set the out color
    //o.color = float4(mul(shC, unity_DirBasis), _A); //What was I doing with this?! :O
    o.color = float4(shC, _A);

    return o;
    }

    fixed4 frag (v2f i) : COLOR
    {
    float4 c = float4(1.0f,1.0f,1.0f,1.0f);
    return i.color;
    }
    ENDCG
    }
    }
    }
     
    Last edited: Oct 25, 2012
    IgorAherne and Untrip like this.
  2. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    That's really nice. I admit the colour makes more intuitive sense to me than position, but both are fun to play around with.

    I'm not sure that alpha less than one makes it anything but ugly, though.
     
  3. Lulucifer

    Lulucifer

    Joined:
    Jul 8, 2012
    Posts:
    358
    you guy are wonderful,It will be a great help to me,thanks!
     
  4. alleycatsphinx

    alleycatsphinx

    Joined:
    Jan 25, 2012
    Posts:
    57
    Thanks Lulucifer, and yes, I'll admit that when setting alpha below 0 it really isn't much to look at... =/
     
  5. JecoGames

    JecoGames

    Joined:
    Jan 10, 2013
    Posts:
    135
    Sorry for bumping,I'm only in secondary school(high school in America) and really want to understand spherical harmonics but the majority of explanations just go straight over my head. I know that they are functions on the surface of a sphere but I dont understand the math at all! Any Help would be greatly appreciated.
     
  6. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I can't really make the math simpler than it is right now. It's just not very high school level.

    But I can try to explain how it works a little bit. Lets start with the bouncing bars on music players. They represent the intensity of the sound at different frequencies. Looking at the sound wave directly would not show anything meaningful, but the intensity per frequency reveals the low tones and the high tones. This conversion is called a Fourier transform. Low tones come from a slowly oscillating sound wave and high tones from a quickly oscillating sound wave.

    The math behind spherical harmonics is basically doing the same Fourier transform, but in 2D for a spherical surface. And not with a sound wave, but with light intensity. Low tones in spherical harmonics store the light that is slowly varying. Say the light from the sky. Higher tones in spherical harmonics store the light that is quickly varying like sharp shadows.

    The idea is that you can work with lighting starting with only the lowest frequency from the spherical harmonics. This is the most important part of the visual information. And you can then add layers of higher frequencies to increase the precision. So it's essentially a way to order the lighting information from most important to least important.

    The same concept is for example applied in image and video compression. The most important information is kept as original, but the less important information is dynamically discarded.
     
    IgorAherne, Untrip, Nearo1 and 2 others like this.
  7. JecoGames

    JecoGames

    Joined:
    Jan 10, 2013
    Posts:
    135
    Thanks for that,what course in college will cover maths like this? At the moment I'm probably going to go for computer science as programming is something I really like(hence why I'm here in the first place!)
     
  8. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I've done computer science (on master level) and this was not specifically taught in any of the courses as far as I can remember. I did need to use the Fourier transform once for a practical course when programming an ASIC to do that exact thing of displaying bouncing bars based on a sound wave input. Math is very present in a computer science education. On master level you'll be learning what you've learned in high school every three months when it comes to math. So don't worry about the math. It'll be covered.
     
  9. JecoGames

    JecoGames

    Joined:
    Jan 10, 2013
    Posts:
    135
    Thanks for your help, looks like I'll have to stick to relatively simple shaders if thats the case, thanks again!
     
  10. dreamerflyer

    dreamerflyer

    Joined:
    Jun 11, 2011
    Posts:
    927
    what to use this for?any example? will do this?:
     
  11. JecoGames

    JecoGames

    Joined:
    Jan 10, 2013
    Posts:
    135
    Its used for processing cubemaps so that they represent diffuse illumination, also used for semi-realtime global illumination and also completely real time global illumination.
     
  12. dreamerflyer

    dreamerflyer

    Joined:
    Jun 11, 2011
    Posts:
    927
    how to use this for test direction light ?for example, i want to test shadow effect when lightdir=vector3(1,1,0) .
     
  13. dreamerflyer

    dreamerflyer

    Joined:
    Jun 11, 2011
    Posts:
    927