Search Unity

_ObjectSpaceLightPos ?

Discussion in 'Shaders' started by Omar Rojo, May 23, 2007.

  1. Omar Rojo

    Omar Rojo

    Joined:
    Jan 4, 2007
    Posts:
    494
    Code (csharp):
    1. oVertex = mul (glstate.matrix.mvp, vertex);
    2.  
    3. float3 P = vertex.xyz;
    4. float3 N = normal.xyz;
    5.  
    6. float3 ambient = _PPLAmbient.rgb;
    7.  
    8. float3 light = normalize (_ObjectSpaceLightPos [0].xyz - P);
    9. float diffuseLight = max (dot (N, light), 0.0);
    10.  
    11. float3 diffuse = _Color.rgb * glstate.light [0].diffuse.rgb * diffuseLight;
    12.  
    13. float3 view = normalize (_ObjectSpaceCameraPos.xyz - P);
    14. float3 halfangle = normalize (light + view);
    15. float specularLight = pow (max (dot (N, halfangle), 0), 1.0);
    16.  
    17. if ( diffuseLight <= 0 )
    18.     specularLight = 0;
    19.                    
    20. float3 specular = _Color.rgb * glstate.light [0].diffuse.rgb * specularLight;
    Im calculating the ambient, diffuse and specular right ?

    Well, it appears that ambient and specular is right, but diffuse.. the diffuseLight variable is always 0, is has something to do with the _ObjectSpaceLightPos [0] in the calculation.. i think this variable is holding the positions of the lights in the object space but it seems that this value is the same no matter where i place the light! please help!

    .ORG
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    The Cg code is right. What's wrong is the shader that is around Cg code, I guess :)

    A quick fix: add this inside the Pass:
    Code (csharp):
    1. Tags { "LightMode" = "Pixel" }
    The long story:

    Why without adding anything you get strange results? Because if the shader is not explicitly pixel-lit, Unity assumes it is vertex-lit. This way people can write small shaders to do some things with textures, and they will just work with lights, etc. In your shader's case - how should it work when there are two lights in the scene? Three? The code is only written to deal with a single light (and it only supports point lights in your shader, not directional or spot ones).

    Hence writing pixel-lit shaders is just more complicated. The LightMode=Pixel tag tells Unity to draw that pass for each pixel-lit light. To support more than one pixel light, you'll also want to add this inside SubShader block
    Code (csharp):
    1. Blend AppSrcAdd AppDstAdd
    Now the shader will support more than one pixel light. The lights will just add illumination. Of course, the shader still won't support the case where no lights are shining on the object (it will display nothing), or when there are vertex-lit lights. Or when there are spot/directional lights, or point lights with attenuation, or lights with cookies.

    Scary!

    I'd suggest reading Unity's rendering pipeline and Attenuation and cookies for pixel lights in the docs. Also take a look at the source of builtin shaders.
     
  3. Omar Rojo

    Omar Rojo

    Joined:
    Jan 4, 2007
    Posts:
    494
    Very scary indeed !

    Well Aras, im just learning, and im learning a lot and your help is very important to me right now. I have realized and understood everything you said. And all three links you posted, are my top priority on my desktop for about 1 month now..

    It's just im learning Cg and ShaderLab at the same time, and also Unity.. and also MAC OS.. It's all a new world to me here in my new job.

    Thanks for the clarifications! very appreciated! the ShaderLab documentation is printed right beside of me ;D

    .ORG
     
  4. Omar Rojo

    Omar Rojo

    Joined:
    Jan 4, 2007
    Posts:
    494
    That makes me think.. how do you differentiate a spot light from a point light ?, i have checked the built-in Shaders but i can't find the "if"


    .ORG
     
  5. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    There's no "if". Doing if's inside shaders most often is not what you want (because conditional expressions are expensive - in most cases both branches are executed, and then the result is selected depending on the comparison... that's because most of the hardware can't really do branches).

    What we do is create multiple shaders behind the scenes. Currently each pixel-lit shader is actually compiled into 5 separate shaders, to support different light types, attenuation, cookies etc.

    So you write some macros in the shader, that get expanded into different things based on light type the shader is compiled for. You can see the macros themselves in AutoLight.cginc (in Unity.app/Contents/CGIncludes).