Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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
2
Question by Connormcp777 · Jul 26, 2018 at 06:14 AM · lighting2d sprites

BlendOp Max in a shader cuts sprites to half-opacity

Hey!

I'm making a 2D game that requires light. I created torches that use point lights and a sprites/diffuse shader for all the sprites' material.

... Or the USED to use a diffuse shader. The problem with this system is that if two lights are near each other, their intensities COMBINE. The resulting super-bright light washed out all the features of my objects! So I made this new shader:

Code (CSharp):

 Shader "Sprites/No-Overlap-Diffuse"
 {
     Properties
     {
         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
         _Color ("Tint", Color) = (1,1,1,1)
         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
         [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
         [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
     }
  
     SubShader
     {
         Tags
         {
             "RenderType" = "Opaque"
             "Queue"="Transparent"
             "IgnoreProjector"="True"
             "RenderType"="Transparent"
             "PreviewType"="Plane"
             "CanUseSpriteAtlas"="True"
         }
  
         Cull Off
         Lighting Off
         ZWrite Off
         Blend One OneMinusSrcAlpha
         BlendOp Max
  
         CGPROGRAM
         #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing
         #pragma multi_compile _ PIXELSNAP_ON
         #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
         #include "UnitySprites.cginc"
  
         struct Input
         {
             float2 uv_MainTex;
             fixed4 color;
         };
  
         void vert (inout appdata_full v, out Input o)
         {
             v.vertex = UnityFlipSprite(v.vertex, _Flip);
  
             UNITY_INITIALIZE_OUTPUT(Input, o);
             o.color = v.color * _Color * _RendererColor;
         }
  
         void surf (Input IN, inout SurfaceOutput o)
         {
             fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color;
             o.Albedo = c.rgb * c.a;
             o.Alpha = c.a;
         }
         ENDCG
     }
  
 Fallback "Transparent/VertexLit"
 }

This heavily borrows from the actual sprites/diffuse source code I got from the Unity Archives. The only caveat is that I added the BlendOp max command.

While this did get rid of the overlapping lights problem (=D), it added a NEW problem, which is that it turns all my sprites into GHOSTS! Every pixel on the object gets an opacity directly related to how dark the pixel is: The color white is perfectly solid, but black is completely transparent, while everything else falls somewhere in between.

alt text

What is happening!?

what-a-mess.png (399.8 kB)
what-a-mess.png (399.8 kB)
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

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Monstetcat · Aug 21, 2018 at 04:35 AM

Hey, im making a 2D pixel game with unity. I'd like to let player be able to set light by themselves. But when i tring to make this Function i met the same problem there. The lights will overlap!!!! This problem confused me for a really long time, so im start study about UnityShder. Now im glad to share what i learned. here is my shader:

 Shader "Custom/PerPixelShader" {
     Properties {
         _Diffuse ("Diffuse", Color) = (1,1,1,1)
         _MainTex("Texture",2D) = "white"{}
         _Cutoff("Alpha Cutoff",Range(0,1)) = 0.5
 
     }
     SubShader {
         Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
         //ZWrite Off
         Pass
         {
             Tags{"LightMode" = "ForwardBase"}
 
             CGPROGRAM 
             #pragma vertex vert
             #pragma fragment frag
             #pragma multi_compile_fwdbase
             #pragma target 3.0 
             #include "UnityCG.cginc" 
             #include "Lighting.cginc" 
 
             //fixed4 _Diffuse;
              
  
             struct appdata 
             {
                 float4 vertex : POSITION;
                 float3 normal : NORMAL;
                 float2 uv : TEXCOORD0;
             };
 
             struct v2f
             {
                 float4 vertex : SV_POSITION;
                 float3 worldNormal : TEXCOORD0;
                 float3 worldPos : TEXCOORD1;
                 float2 uv : TEXCOORD2;
             };
 
             sampler2D _MainTex;
             float4 _MainTex_ST;
             fixed _Cutoff;
  
             v2f vert (appdata v)
             {
                 v2f o;
                 o.vertex = UnityObjectToClipPos(v.vertex);
  
                 o.worldNormal = UnityObjectToWorldNormal(v.normal);
                 o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                 o.uv = TRANSFORM_TEX(v.uv,_MainTex);
 
                 return o;
             }
  
  
             fixed4 frag (v2f i) : SV_Target
             {
                 
 
                 fixed3 worldNormal = normalize(i.worldNormal);
 
                 fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
 
                 fixed4 albedo = tex2D(_MainTex,i.uv);
 
                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo.rgb;
 
                 clip (albedo.a - _Cutoff);//透明度 
                  
                 fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
 
                 //fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
                 //fixed3 halfDir = normalize(worldLightDir+viewDir);
 
                 //fixed3 color = ambient + diffuse;
 
                 return fixed4(ambient+diffuse,1.0);
             } 
             ENDCG    
         }
 
         Pass
         {
             Tags{"LightMode" = "ForwardAdd"}
 
             BlendOp Max
 
 
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             #pragma multi_compile_fwdadd
             #pragma target 3.0 
             #include "UnityCG.cginc" 
             #include "Lighting.cginc" 
             #include "AutoLight.cginc"
 
             struct appdata 
             {
                 float4 vertex : POSITION;
                 float3 normal : NORMAL;
                 float2 uv : TEXCOORD0;
             };
 
             struct v2f
             {
                 float4 vertex : SV_POSITION;
                 float3 worldNormal : TEXCOORD0;
                 float3 worldPos : TEXCOORD1;
                 float2 uv : TEXCOORD2;
             };
 
             sampler2D _MainTex;
             float4 _MainTex_ST;
             fixed _Cutoff;
 
  
             v2f vert (appdata v)
             {
                 v2f o;
                 o.vertex = UnityObjectToClipPos(v.vertex);
  
                 o.worldNormal = UnityObjectToWorldNormal(v.normal);
                 o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                 o.uv = TRANSFORM_TEX(v.uv,_MainTex);
 
                 return o;
             }
  
  
             fixed4 frag (v2f i) : SV_Target
             {
                 
 
                 fixed3 worldNormal = normalize(i.worldNormal);
                 
                  
             #ifdef USING_DIRECTINAL_LIGHT
                 fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
                 
             #else
                 fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
                 
             #endif
 
                 fixed4 albedo = tex2D(_MainTex,i.uv);
 
                 //fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo.rgb;
 
                 clip (albedo.a - _Cutoff);//透明度 
                  
                 fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
 
                 //fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
                 //fixed3 halfDir = normalize(worldLightDir+viewDir); 
 
                 //fixed3 specular = _LightColor0.rgb * pow(saturate(dot(worldNormal,halfDir)),255);
 
                 //fixed3 color = ambient + diffuse;
 
                 #ifdef USING_DIRECTIONAL_LIGHT
                     fixed atten = 1.0;
                 #else
                     #if defined (POINT)
                         float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
                         fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
 
                     #elif defined (SPOT)
                         float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
                         fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
                         
                     #else
                         fixed atten = 1.0;
                     #endif
                 #endif
 
                 return fixed4(diffuse*atten,1.0);
             } 
             ENDCG    
         }
     }
 
     
     FallBack "Sprite/Diffuse"
 }

Unity's surface shader can't manualy deal with fwdadd pass(maybe just because i not found the correct way to change it), so i use the Vertx/Fragment Shader,and i change the fwdadd Pass's blendmode. But here is some problem still confuse me.

1. I personally recommend use Spot light, although point light has much better effect on 2dgame(the center is brighter than outline),if you use point light there will be a black gap between two point light. I don't know how to figure this out. If someone know what cause this pls tell me thanks =D.

2. You must change the all light mode to Important mode(per pixel). If you need to put light more than 4 in a single scene, u need to change the quality setting and modify the pixel light count to your needed count; But there also be quality problem here, i have tested that on PC you can put 30+ light in a single scene, based on PC's hardware level. But on mobile device you can only put at most 8 light. Now im looking for a new method to achieve what i really want effect and can run perfectly on mobile device.

3. There should be only one directlight in a single scene, the light mode should be important (perpixellight), and the intensity should be 0.85f(1 will be too bright).

4. Be careful about sorting layer and Z pos.

Comment
Add comment · 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
0

Answer by Connormcp777 · Aug 25, 2018 at 06:29 PM

You are a miracle worker! It works perfectly!

This problem has given me so many headaches. Thank you!

Comment
Add comment · 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

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

118 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Dynamic spritemask from worldpoints? 0 Answers

Normal map on 2D sprite screwed it up.,Applying material with normal map on 2D sprite screwed it up. 2 Answers

I'm experiencing a weird effect with my 2D light. Any fix? 1 Answer

Normal map partially visible through another sprite,2D Normal map causing partial transparency 2 Answers

is there a way to preventing 2D light from passing through sprites, if the light is behind vs front sprite ? 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