Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: WinMain on October 27, 2014, 05:24:13 AM

Title: How to apply a shader effect on one sprite?
Post by: WinMain on October 27, 2014, 05:24:13 AM
I know how to apply the shader on a material,but I just want to apply a effect on one sprite in atlas.It's there some way to do this?
Title: Re: How to apply a shader effect on one sprite?
Post by: dilshod on October 27, 2014, 10:50:40 AM
Here is my version of how it could be done. i'm going to use this in my current project.

UIShaderSprite.cs:
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class UIShaderSprite : UISprite {
  6.         Material mMaterial;
  7.         [HideInInspector][SerializeField] Shader mShader;
  8.  
  9.         // cache materials
  10.         static Dictionary<int, Dictionary<int, Material>> atlasMaterials = new Dictionary<int, Dictionary<int, Material>>();
  11.  
  12.         public override Material material {
  13.                 get {
  14.                         if (mShader != null) {
  15.                                 if (mMaterial == null || mChanged) {
  16.                                         Dictionary<int, Material> shaderMaterials;
  17.                                         if (!atlasMaterials.TryGetValue(atlas.GetInstanceID(), out shaderMaterials))
  18.                                                 atlasMaterials[atlas.GetInstanceID()] = shaderMaterials = new Dictionary<int, Material>();
  19.  
  20.                                         if (!shaderMaterials.TryGetValue(mShader.GetInstanceID(), out mMaterial) || mMaterial == null)
  21.                                                 shaderMaterials[mShader.GetInstanceID()] = mMaterial = new Material(base.material) {shader = mShader};
  22.                                 }
  23.                                 return mMaterial;
  24.                         }
  25.                         return base.material;
  26.                 }
  27.         }
  28. }
  29.  

Editor/UIShaderSpriteInspector.cs:
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections;
  4.  
  5. [CanEditMultipleObjects]
  6. [CustomEditor(typeof(UIShaderSprite), true)]
  7. public class UIShaderSpriteInspector : UISpriteInspector {
  8.  
  9.         protected override bool ShouldDrawProperties() {
  10.                 NGUIEditorTools.DrawProperty("Shader", serializedObject, "mShader", GUILayout.MinWidth(20f));
  11.                 return base.ShouldDrawProperties();
  12.         }
  13. }
  14.  
Title: Re: How to apply a shader effect on one sprite?
Post by: WinMain on October 27, 2014, 10:48:55 PM
Here is my version of how it could be done. i'm going to use this in my current project.

UIShaderSprite.cs:
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class UIShaderSprite : UISprite {
  6.         Material mMaterial;
  7.         [HideInInspector][SerializeField] Shader mShader;
  8.  
  9.         // cache materials
  10.         static Dictionary<int, Dictionary<int, Material>> atlasMaterials = new Dictionary<int, Dictionary<int, Material>>();
  11.  
  12.         public override Material material {
  13.                 get {
  14.                         if (mShader != null) {
  15.                                 if (mMaterial == null || mChanged) {
  16.                                         Dictionary<int, Material> shaderMaterials;
  17.                                         if (!atlasMaterials.TryGetValue(atlas.GetInstanceID(), out shaderMaterials))
  18.                                                 atlasMaterials[atlas.GetInstanceID()] = shaderMaterials = new Dictionary<int, Material>();
  19.  
  20.                                         if (!shaderMaterials.TryGetValue(mShader.GetInstanceID(), out mMaterial) || mMaterial == null)
  21.                                                 shaderMaterials[mShader.GetInstanceID()] = mMaterial = new Material(base.material) {shader = mShader};
  22.                                 }
  23.                                 return mMaterial;
  24.                         }
  25.                         return base.material;
  26.                 }
  27.         }
  28. }
  29.  

Editor/UIShaderSpriteInspector.cs:
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections;
  4.  
  5. [CanEditMultipleObjects]
  6. [CustomEditor(typeof(UIShaderSprite), true)]
  7. public class UIShaderSpriteInspector : UISpriteInspector {
  8.  
  9.         protected override bool ShouldDrawProperties() {
  10.                 NGUIEditorTools.DrawProperty("Shader", serializedObject, "mShader", GUILayout.MinWidth(20f));
  11.                 return base.ShouldDrawProperties();
  12.         }
  13. }
  14.  
Thank you for your idea.But I have one question is,whether this way will make the drawcall rise?Becase if there are too many sprites in atlas,there will be too many materials.
Title: Re: How to apply a shader effect on one sprite?
Post by: dilshod on October 28, 2014, 01:38:40 AM
Nope, i'm not creating new material for each sprite, i'm creating new material for each shader and atlas, that's why there is a cache for materials.
If you put hundreds of different sprites with same shader and same atlas in one depth, they will add only one (or two) draw call.
Title: Re: How to apply a shader effect on one sprite?
Post by: WinMain on November 04, 2014, 04:53:39 AM
thanks for your solution dilshod.
Title: Re: How to apply a shader effect on one sprite?
Post by: kimsama on December 11, 2014, 03:22:55 AM
See UIShaderSprite for the working copy of this thread.

You can find it on the following github repository:

https://github.com/kimsama/Unity-NGUIExtension

As my experiments, it needs to call panel.RebuildAllDrawCalls() to correctly apply a new shader which is differenct to what NGUI applies in UIDrawCall.UpdateMaterial() call.
Title: Re: How to apply a shader effect on one sprite?
Post by: WinMain on January 05, 2015, 11:27:01 PM
See UIShaderSprite for the working copy of this thread.

You can find it on the following github repository:

https://github.com/kimsama/Unity-NGUIExtension

As my experiments, it needs to call panel.RebuildAllDrawCalls() to correctly apply a new shader which is differenct to what NGUI applies in UIDrawCall.UpdateMaterial() call.
Awesome,Thank you so much.