Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by nikomikulicic · Apr 24, 2015 at 02:29 PM · shaderlightingshaderlabsurface shader

Switching shader Lighting On/Off from script

Hello everyone!

I'm trying to write a script that would be able to tell a shader whether it should use lighting or not.

I am familiar with possibility to add Lighting On/Off before CGPROGRAM line (as addressed here: http://answers.unity3d.com/questions/234433/shader-light-off-in-cgprogram.html ) but I was wondering if it was possible to toggle it from MonoBehaviour?

I tried adding preprocessor directives like

 SubShader 
 {
     Tags {  "RenderType" = "Opaque" }
      
     #if LIGHTING_ON
     Lighting On
     #else
     Lighting Off
 
     CGPROGRAM
     #pragma surface surf Lambert
     #pragma multi_compile LIGHTING_OFF LIGHTING_ON
     // ...
 }
 

and toggle lighting with material.EnableKeyword but it throws me syntax error. I guess I can't use preprocessor directives before CGPROGRAM line?

Is there something like material.shader.SetLighting(true)? Should I write two different shaders, one with Lighting On and one with Lighting Off and switch between them or is there a better way?

I'm new to shaders so I hope I'm not missing something obvious. Any help is appreciated. Thank you!

EDIT 1: I don't want to do my lighting calculations. I would like to use surface shader with built-in Lambert shading like in my example.

EDIT 2: As @Jessespike suggested, it would be possible to copy-paste Unitys implementation of Lambert lighting model and have it wrapped inside #if LIGHTING_ON - #else preprocessor directives, but would I still be able to use baked lightmaps?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
-1

Answer by Jessespike · Apr 24, 2015 at 03:29 PM

You could write your own property called _Lighting and have that as a condition to do lighting calculations.

In script:

     material.SetFloat("_Lighting", 0f);    // turn off;
     material.SetFloat("_Lighting", 1f);    // turn on;


In shader:

     if (_Lighting != 0f)
     {
         // do light calcuations
     }
Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image nikomikulicic · Apr 24, 2015 at 03:46 PM 0
Share

Thank you for your answer but I think that would be quite inefficient. As I understand, if-else statements are costly in shaders and should be avoided.

Also, if I'm going to make my own lighting calculations, I could wrap that code in preprocessor if-else directives and have it multi compiled. That is actually how I do it now, but I don't want my lighting calculations. I want to use Unitys. I guess I wasn't so clear about that so I'll edit my question.

avatar image Jessespike · Apr 24, 2015 at 05:39 PM 1
Share

Then swapping between two shaders might be the way to go.

Not sure of anything like: material.shader.SetLighting(true)

Bit off track, I understand you don't want to write a custom lighting model, but just as an alternative, you could copy Unity's lambert function and wrap the lighting in pragmas.

           #if LIGHTING_ON
           c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2);
           #else
           c.rgb = s.Albedo;
           #endif


then in a script you can toggle with keywords:

 public $$anonymous$$aterial material;
 bool useLighting = false;

 // Update is called once per frame
 void OnGUI () {
 
     if (GUI.Button(new Rect(0f, 0f, 100f, 100f), "Toggle Lighting"))
     {
         useLighting = !useLighting;
         if (useLighting)
         {
             material.Disable$$anonymous$$eyword("LIGHTING_OFF");
             material.Enable$$anonymous$$eyword("LIGHTING_ON");
         } else {
             material.Disable$$anonymous$$eyword("LIGHTING_ON");
             material.Enable$$anonymous$$eyword("LIGHTING_OFF");
         }
     }
avatar image Eno-Khaon · Apr 24, 2015 at 05:45 PM -1
Share

As a general rule, you can expect an if statement in a shader to always take as long as the longer condition. If the "else" takes three times as long to calculate as the "if" portion, the "if" would still take as long as the "else" would.

avatar image nikomikulicic · Apr 24, 2015 at 07:07 PM 0
Share

@Jessespike That is exactly what I'm doing right now :) , but I think that would leave me without option of baking light. As far as I'm aware, Unity uses lightmaps inside its implementation of lighting models (such as Lambert). I think I'd rather have 2 shaders than copy/paste whole implementation of lighting with lightmaps and everything. (That is if Unity really does use lightmaps inside lighting implementation. Not sure about that) I think I'll edit my question once more. Thanks.

@$$anonymous$$o $$anonymous$$haon Can you provide a link for further reading on this "if-else" topic? I was of opinion that both "if" and "else" are both executed and then one of those discarded. Since vertex/pixel shaders run for all vertices/pixels in parallel, I thought that every vertex/pixel has to run the same code. If one pixel satisfies "if" condition, and one pixel doesn't, both "if" and "else" have to be executed. Don't know what if none of them satisfy "if" condition. Can you provide more info?

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Surface Shaders have Slight Trasparency. Why? 0 Answers

Converting Fixed Function Shader to Surface Shader 2 Answers

[ShaderGraph] How can I prevent lights overlapping in intensity? 0 Answers

How do I keep an object lit when a light moves past it? 0 Answers

Semitransparent shader not visible in front of objects 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges