Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[SOLVED]Animating a projector cookie (UV anim)

Discussion in 'Scripting' started by Brady, Sep 24, 2009.

  1. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    I'm trying to simulate slowly rolling clouds overhead and the shadows they create below using a projector. Problem is, changing the UV offset doesn't seem to have any effect for projectors. I realize you're "supposed" to use a clamped texture, but I'm just wondering if there's any way to do this? Perhaps by modifying the projector shader? I'm a complete n00b with it comes to writing shaders, so I'm not sure where to begin if that's a workable option.
     
  2. MattFS

    MattFS

    Joined:
    Jul 14, 2009
    Posts:
    219
    in the same shader technique as the sunlight, just lookup your cloud texture (i'm assuming it's a tileable 'noise/cloud' texture) with the worldspace XY of the vertex modulated by Time, that's about it for basic scrolling clouds, up to you how you wish to blend it with the diffuse etc

    CloudUV = (Vertex.xy * Scale) + (Time * ScrollSpeed)
    ...something like that I think :)
     
  3. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    Thanks, but that's the basic technique I tried and it doesn't seem to work with projectors. No UV offset seems to alter how the projector...err... projects its cookie. I'm basically trying to project the cloud shadows onto the ground (and other objects on the ground).

    Then again, maybe I misunderstood what you were trying to say?
     
  4. MattFS

    MattFS

    Joined:
    Jul 14, 2009
    Posts:
    219
    hmm, sounds like you're trying to make the light itself project a texture of the clouds? such as a spotlight?

    what I meant was, in the ambient/outdoor pass of your shaders - simply index the cloud texture based on the vertices position, this is some code I used in a different engine:

    Code (csharp):
    1. CloudUV = (WorldSpaceVertex.xy * CloudTileFactor) +  float2(Time, Time) * CloudScrollSpeed;

    With a spotlight projection, it's not mesh UV's that are indexing the cookie, it's a projection matrix constructed from the spotlight so altering the mesh UV's in the shader has nothing to do with the projection of the cookie texture. My example above avoids all of that... doesn't require a projection matrix and doesn't even need UV's, because the vertices worldspace xy positions are the UV's (you could visualize that as being a perfect top down orthographic projection) :)
     
  5. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    You could just move the projector.

    /P
     
  6. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    Urgrund, ok, now I see where you're going with this. I may have to post the question over in the shaderlab forum then to see exactly how to do something like this. But that makes perfect sense.

    Metervara, yes, I considered doing that, and if push comes to shove, I may have to. But I'd prefer to avoid it since that would mean I'd need at least two projectors when I'd like to be able to get away with one for performance reasons (this is for iPhone).
     
  7. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    Replace Matrix [_Projector] with let's say Matrix [_MyMatrix] in your shader and add a script to the projector that creates _MyMatrix and feeds it to your shader like so:

    Code (csharp):
    1. Matrix4x4 _Projector = m.GetMatrix("_Projector");
    2. Matrix4x4 off = Matrix4x4.TRS(transform.TransformDirection(-Vector3.up)*Time.time, Quaternion.identity, Vector3.one);
    3. Matrix4x4 _MyMatrix = _Projector * off;
    4. Shader.SetGlobalMatrix("_MyMatrix", _MyMatrix);
    /Patrik
     
  8. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    Positively brilliant! It works perfectly!

    Thanks a ton!

    urgrund, I'm still interested in pursuing your idea as well... I'm thinking it might save some extra rendering since it seems it could be accomplished in a single pass, whereas using a projector has to render the geometry a second time.

    Still, having a scrollable projector is REALLY handy in cases where you don't want a more or less orthogonal projection.
     
  9. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    One extra note:
    Over time, as the values in the matrix begin to accumulate, the shadows start looking more like reflections from a pool of water or something. It's really weird (but cool looking if that's what you're after). So I figured the values needed to loop within an acceptable range. This lead to still more problems because it was difficult to find the "loop point" in the value going into the matrix. The reason for this is, if you find one that works for a distant object, it doesn't work for a nearby object. So I switched to an orthographic projection (which is what I really need anyway for cloud cover). Now I just clamp the values to 0-1. I also decided I could get down and dirty with the matrix itself and directly manipulate the pertinent value to avoid all the extra math each frame. So here's what I wound up with:

    Code (csharp):
    1.  
    2. void Start()
    3. {
    4.    // Get the projector matrix...
    5.    _Projector = p.material.GetMatrix("_Projector");
    6. }
    7.  
    8. void Update()
    9. {
    10.    // Scroll the texture:
    11.    _Projector.m13 += scrollSpeed * Time.deltaTime;
    12.  
    13.    if(_Projector.m13 > 1f)
    14.       _Projector.m13 = 0;
    15.  
    16.    Shader.SetGlobalMatrix("_AnimatedProjector", _Projector);
    17. }
    18.  
    That, on an orthographic projector, works perfectly and seamlessly, and should be really, really fast.

    Thanks again!!! Now onto trying out urgrund's solution!
     
  10. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    urgrund, okay, I know this is probably straying into the Shaderlab forum domain a bit now, but I wanted to follow up on your suggestion. I know next to nothing about shader programming, but I'm trying to teach myself. It struck me that essentially what I'm trying to do here is lightmapping, only with non-conventional UVs. So I looked up the iPhone lightmapping shader:

    Code (csharp):
    1.  
    2. Shader "iPhone/Lightmap/Lightmap Only"
    3. {
    4.     Properties
    5.     {
    6.         _Color ("Main Color", Color) = (1,1,1,1)
    7.         _MainTex ("Base (RGB)", 2D) = "white" {}
    8.         _LightMap ("Lightmap (RGB)", 2D) = "black" { LightmapMode }
    9.     }
    10.  
    11.     SubShader
    12.     {
    13.         Pass
    14.         {
    15.             Name "BASE"
    16.             Tags {"LightMode" = "Always"}
    17.    
    18.             BindChannels {
    19.                 Bind "Vertex", vertex
    20.                 Bind "texcoord1", texcoord0 // lightmap uses 2nd uv
    21.                 Bind "texcoord", texcoord1 // main uses 1st uv
    22.             }
    23.             SetTexture [_LightMap] {
    24.                 constantColor [_Color]
    25.                 combine texture * constant
    26.             }
    27.             SetTexture [_MainTex] {
    28.                 combine texture * previous
    29.             }
    30.         }
    31.     }
    32. }
    Now unless I'm mistaken, it seems what I need to do is implement your code snippet so that "CloudUV", as you called it, would be stored in "texcoord1"? Or instead of binding I'm sort of at a loss how to go about this though. Or do I need to go a completely different way about it?
     
  11. MattFS

    MattFS

    Joined:
    Jul 14, 2009
    Posts:
    219
    Yep - though maybe texcoord0? (going by the comments in that shader?)... but since that looks like fixed function I can't help you there (yes, maybe time to stray into shaderlab :) ), I've only made the simplest of ffp shaders... but, you could easily do this directly to the mesh UV's, which was actually the answer I recieved when asking here how to get basic UV scrolling shaders working in FFP.

    Show us a screeny when you've got something! :p
     
  12. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    Yeah, I suppose I could alter the UVs manually, but that seems awfully inefficient to do in-script if you have a large number of vertices in-scene.

    I could use a lookup table and alter the object's material color based on its position, but then I'd break iPhone batching, leading to tons of drawcalls...
     
  13. tornadotwins

    tornadotwins

    Joined:
    May 21, 2008
    Posts:
    308
    Hey Brady,

    Last September you put a post on the forums on how to get a projector to scroll.
    Apparently, it worked out for you, but I'm having huge trouble following the solution in the forum post:
    http://forum.unity3d.com/viewtopic.php?p=205335

    I have no C# skills, so I'm trying to translate your code:
    Code (csharp):
    1.  
    2. var proj;
    3. var mat;
    4. var scrollSpeed = 0.5;
    5.  
    6. function Start()
    7. {
    8.    // Get the projector matrix...
    9.    var proj : Projector = GetComponent (Projector);
    10.    
    11.    var mat = proj.material.GetMatrix("_Projector");
    12.    
    13.    print(mat);
    14. }
    15.  
    16. function Update()
    17. {
    18.     mat.m13 += scrollSpeed * Time.deltaTime;
    19.     if(mat.m13 > 1.0)
    20.     {
    21.         mat.m13 = 0;
    22.     }
    23.    
    24.     Shader.SetGlobalMatrix("_AnimatedProjector", mat);
    25. }
    26.  
    Of course, the 'm13' part returns a null reference exception, since it isn't defined. I don't know where the 'm13' part comes from, what it does or how to define it.
    Could you help?

    Also, does this code only work with a specific type of shader only?
    If so, what is the code for the shader?

    If you could help me with this one, I'd REALLY appreciate it, I've been trying this for two days now and lost hope a little bit...

    -TT
     
  14. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    I'm no JS guru by any means, but I suspect it may have to do with the fact you're using implicit typing? Try explicitly declaring the type of "mat" like so:

    var mat : Matrix4x4;

    At any rate, I've made this into a stand-alone MonoBehaviour that you should just be able to attach to your Projector and forget about it. If for some reason you're going to call it from JS (which you shouldn't need to since it is stand-alone), just put the script into your 'Plugins' folder so it gets compiled before any JS. Also, this is an updated version which also allows you to control the "scale" of the projected image. Try values between 0.2 and 1.0 to get a feel for how the scaling works. And for nice, slow, subtle moving clouds, I use 0.03 for the speed.

    Code (csharp):
    1.  
    2. // A script to scroll a projected image.
    3. // Copyright 2009 Above and Beyond Software. All rights reserved
    4.  
    5. using UnityEngine;
    6. using System.Collections;
    7.  
    8. public class ProjectorScroller : MonoBehaviour
    9. {
    10.    public float scrollSpeed;            // Speed to scroll
    11.    public float scale;
    12.  
    13.    protected Matrix4x4 _Projector;
    14.  
    15.    // Use this for initialization
    16.    void Start ()
    17.    {
    18.       Projector p = (Projector) gameObject.GetComponent(typeof(Projector));
    19.       p.orthographic = true;
    20.       _Projector = p.material.GetMatrix("_Projector");
    21.  
    22.       // Set the scale:
    23.       _Projector.m00 = 0.005f / scale;
    24.       _Projector.m12 = 0.005f / scale;
    25.    }
    26.    
    27.    void Update()
    28.    {
    29.       _Projector.m13 += scrollSpeed * Time.deltaTime;
    30.  
    31.       if (_Projector.m13 > 1f)
    32.          _Projector.m13 = 0;
    33.  
    34.       Shader.SetGlobalMatrix("_AnimatedProjector", _Projector);
    35.    }
    36. }
    37.  
    Just name the file "ProjectorScroller.cs" and drag it onto a projector and you should be good to go.

    I'm not sure if you need a special shader other than the standard projector shader or not, but here's what I'm using for mine, and I renamed it, so I probably modified it in some way, but I haven't taken the time to compare it to see:
    Code (csharp):
    1.  
    2. Shader "Projector/Additive, Animated" {
    3.    Properties {
    4.      _Color ("Main Color", Color) = (1,1,1,1)      
    5.       _ShadowTex ("Cookie", 2D) = "" { TexGen ObjectLinear }
    6.       _FalloffTex ("FallOff", 2D) = "" { TexGen ObjectLinear }
    7.    }
    8.    Subshader {
    9.       Pass {
    10.          ZWrite off
    11.          //Fog { Color (1, 1, 1) }
    12.          ColorMask RGB
    13.          Blend DstColor One
    14.          SetTexture [_ShadowTex] {
    15.             constantColor [_Color]
    16.             combine constant * texture, ONE - texture
    17.             Matrix [_AnimatedProjector]
    18.          }
    19.          SetTexture [_FalloffTex] {
    20.             constantColor (0,0,0,0)
    21.             combine previous lerp (texture) constant
    22.             Matrix [_ProjectorClip]
    23.          }
    24.       }
    25.    }
    26. }
    27.  
    I hope that helps! I'd love to see a screenshot of your game when you get this working. Thanks!
     
  15. tornadotwins

    tornadotwins

    Joined:
    May 21, 2008
    Posts:
    308
    You totally saved my LIFE on this one!
    Thanks so much for taking the time to help out!

    I think the shader does matter, since the same script didn't work on mine (particle/additive).

    Script works perfectly, I might just try and remake it in JavaScript, but either way it works now.

    Attached a screenshot for ya -- thanks for the help!

    -TT
     
  16. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    Yeah, particle/additive won't work. It has to be a projector shader for sure.

    Hey, seeing that this is an under water scene, you ought to see about getting some perlin textures that look like caustics, then change the frames out progressively by re-assigning the "cookie" texture. I've never used a movie texture before so I don't know if that would work as a cookie or not, but that would look awesome.

    Anyway, it looks great and I'm glad I was able to help. :)
     
  17. tornadotwins

    tornadotwins

    Joined:
    May 21, 2008
    Posts:
    308
    Great idea!
    I'll look into it!

    Will probably need some good compression to keep the movie file small for the web-version, but that's no problem.

    Thanks for all the help!!

    -TT
     
  18. MegadethRocks

    MegadethRocks

    Joined:
    Dec 12, 2009
    Posts:
    162
    Tornado, I have never written a line of JS in my life but I'm guessing that m13 is undefined because you redeclared your vars in the Start function. If you just change "var mat" to "mat" in the Start function it should work fine. I guess this is coming a bit late, but I figured if you were going to change the code to JS you might still be stuck on this.
     
  19. Al-Anselmo

    Al-Anselmo

    Joined:
    Apr 6, 2010
    Posts:
    86
    Hey

    I tryied to follow the discussion but had no success.
    I'm very noob with Shaders, and I couldn't load the scripts right so the projector would animate.

    I created the ProjectorScroller.cs and added to my Shadow prefab (which is a Projector), created a new Shader and apllied it to the the projector material (the standard Blob Shadow material). When I play the scene, when the projector is called the light just explodes super bright, and I cannot see the projector itself.

    Shader:
    Code (csharp):
    1. Shader "Projector/Additive, Animated" {
    2.    Properties {
    3.      _Color ("Main Color", Color) = (1,1,1,1)    
    4.       _ShadowTex ("Cookie", 2D) = "" { TexGen ObjectLinear }
    5.       _FalloffTex ("FallOff", 2D) = "" { TexGen ObjectLinear }
    6.    }
    7.    Subshader {
    8.       Pass {
    9.          ZWrite off
    10.          //Fog { Color (1, 1, 1) }
    11.          ColorMask RGB
    12.          Blend DstColor One
    13.          SetTexture [_ShadowTex] {
    14.             constantColor [_Color]
    15.             combine constant * texture, ONE - texture
    16.             Matrix [_AnimatedProjector]
    17.          }
    18.          SetTexture [_FalloffTex] {
    19.             constantColor (0,0,0,0)
    20.             combine previous lerp (texture) constant
    21.             Matrix [_ProjectorClip]
    22.          }
    23.       }
    24.    }
    25. }
    I want to try this because it may be handy in my game, which involves clouds in different sizes with shadow projected (by a instantiated projector). I plan to add a wind effect to move clouds and their shadows, so this is where these scripts may be useful.

    Thanks.
     
  20. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,469
    I'm not sure what to tell you as it sounds like you're doing everything right from what I can tell. Be sure you've set a cookie texture, and perhaps see if it works if the projector is in the scene rather than instantiated from prefab just to see if there's any difference maybe. Also remember that for it to work with ProjectorScroller.cs properly, the projector needs to be set to orthographic.
     
  21. Al-Anselmo

    Al-Anselmo

    Joined:
    Apr 6, 2010
    Posts:
    86
    The Cookie texture is the shadow texture from the Standard Asses, inside the Blob Shadow folder. I forgot to set the Projector as Orthographic, so I will test if this works as you said, with a projector in the scene and I post the results later.

    Thank you for replying ;)
     
  22. Westmark

    Westmark

    Joined:
    Nov 1, 2009
    Posts:
    187
    I'e found (I think) a better way to animate a projector texture. this works regardless of what shader you use.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. //NOTE: Split this file into two seperate components for next project
    5.  
    6. public class projectorScrollingTexture : MonoBehaviour {
    7.     public Transform target; ///<If this contains a reference then that is animated, otherwise the behaviours transform is used
    8.     public string textureName = "_MainTex";
    9.    
    10.     public Vector2 scrollSpeed = Vector2.zero;  //How fast does the texture scroll
    11.     public Vector2 sinusRange = Vector2.zero;   //How large should the sin wave be (1 = one texture width*tiling)
    12.     public Vector2 waveTime = new Vector2(10, 10); //How long does it take the sin wave to oscillate (1 = 1 sec for full wave)
    13.    
    14.     public Vector2 tilingSinusRange = Vector2.zero; //How large should the tiling sin wave be (1 = ±1 extra tiling)
    15.     public Vector2 tilingWaveTime = new Vector2(10, 10); //How long does it take the tiling sin wave to oscillate (in sec for full wave)
    16.    
    17.     private MaterialData[] materialData;
    18.     private Projector projector;
    19.    
    20.     void Start() {
    21.         projector = (target ? target : transform).GetComponent(typeof(Projector)) as Projector;
    22.         if (projector) {
    23.             //projector.material = projector.material; //Copy material
    24.            
    25.             //Find all material with textures to be scrolled
    26.             ArrayList materialList = new ArrayList();
    27.             //foreach (Material m in projector.material) {
    28.                 if (projector.material.HasProperty(textureName)) {
    29.                     projector.material.GetTexture(textureName).wrapMode = TextureWrapMode.Repeat; //Make sure the texture's wrapmode is set to repeat
    30.                    
    31.                     materialList.Add(new MaterialData(projector.material, projector.material.GetTextureOffset(textureName), projector.material.GetTextureScale(textureName)));
    32.                 }
    33.             //}
    34.            
    35.             if (materialList.Count > 0) {
    36.                 //Convert the arrayList to an builtin array for better performance
    37.                 materialData = new MaterialData[materialList.Count];
    38.                 for (int i = 0; i < materialList.Count; i++)
    39.                     materialData[i] = materialList[i] as MaterialData;
    40.             }          
    41.             else {
    42.                 Debug.LogWarning("No material with property " + textureName + " found", this);
    43.             }
    44.         }
    45.         else {
    46.             Debug.LogError("No projector attached", this);
    47.         }
    48.        
    49.         if (materialData == null) { //IF there are no textures to be scrolled THEN disable the script
    50.             enabled = false;
    51.         }
    52.     }
    53.    
    54.     void Update() {
    55.         Timer.Start();
    56.        
    57.         foreach (MaterialData data in materialData) {
    58.             float scaleX = data.initialTiling.x + ComputePlacement(0, tilingSinusRange.x, tilingWaveTime.x, 1);
    59.             float scaleY = data.initialTiling.y + ComputePlacement(0, tilingSinusRange.y, tilingWaveTime.y, 1);
    60.            
    61.             float offsetX = data.initialOffset.x + ComputePlacement(scrollSpeed.x, sinusRange.x, waveTime.x, scaleX);
    62.             float offsetY = data.initialOffset.y + ComputePlacement(scrollSpeed.y, sinusRange.y, waveTime.y, scaleY);              
    63.                            
    64.             data.material.SetTextureOffset(textureName, new Vector2(offsetX, offsetY));
    65.             data.material.SetTextureScale(textureName, new Vector2(scaleX,scaleY));
    66.         }
    67.        
    68.         Timer.Stop();
    69.     }
    70.    
    71.     private float ComputePlacement(float scrollSpeed, float sinusRange, float waveTime, float scale) {
    72.         float linearScroll = scrollSpeed * Time.time;
    73.         float sinusScroll = sinusRange * Mathf.Sin( (360 * Mathf.Deg2Rad * Time.time)/waveTime );
    74.         return (linearScroll + sinusScroll) * scale;
    75.     }
    76.    
    77.     public class MaterialData {
    78.         public Material material;
    79.         public Vector2 initialOffset;
    80.         public Vector2 initialTiling;
    81.        
    82.         public MaterialData(Material material, Vector2 initialOffset, Vector2 initialTiling) {
    83.             this.material = material;
    84.             this.initialOffset = initialOffset;
    85.             this.initialTiling = initialTiling;
    86.         }
    87.     }
    88. }
    Add this script toa random gameobject, it then has a slot for a projector (object transform)

    This is a script i found which whre intended for scrolling textures on meshes but it is now changed to work with projetors (does not work with meshes anymore)

    For underwater caustics this script works great with the particle additie shader.
     
  23. zxcvasd

    zxcvasd

    Joined:
    Nov 17, 2012
    Posts:
    1
    Material doesn't have a matrix property '_Projector'
    UnityEngine.Material:GetMatrix(String)

    I see it used in the shader "Matrix [_Projector]", so what's up with that?

    EDIT: This is with reference to Brady's script/shader solution on the first page.
     
    Last edited: Jan 10, 2013
  24. StaticDelvar

    StaticDelvar

    Joined:
    Aug 1, 2013
    Posts:
    5
    thanks Westmark i used your code as a base for my shadows, I basically just cleaned it up, forced it to single material, forced it to be attached directly to a projector (removed target) and made a copy of the material so we don't modify the original.

    works great witht eh default shadow projector using Particles/Multiply shader and a single grayscale cloud layer.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. //NOTE: Split this file into two seperate components for next project
    6.  
    7. public class projectorScrollingTexture : MonoBehaviour {
    8.     public string textureName = "_MainTex"; // The texture name WITHIN the shader default usualy _MainTex
    9.     public Vector2 scrollSpeed = Vector2.zero;  //How fast does the texture scroll
    10.     public Vector2 sinusRange = Vector2.zero;   //How large should the sin wave be (1 = one texture width*tiling)
    11.     public Vector2 waveTime = new Vector2(10, 10); //How long does it take the sin wave to oscillate (1 = 1 sec for full wave)
    12.     public Vector2 tilingSinusRange = Vector2.zero; //How large should the tiling sin wave be (1 = A+1 extra tiling)
    13.     public Vector2 tilingWaveTime = new Vector2(10, 10); //How long does it take the tiling sin wave to oscillate (in sec for full wave)
    14.    
    15.     private Projector projector;
    16.     private Material material;
    17.    
    18.     private Vector2 initialTiling = new Vector2();
    19.     private Vector2 initialOffset = new Vector2();
    20.        
    21.     void Start() {
    22.         //Get projector
    23.         this.projector = this.GetComponent(typeof(Projector)) as Projector;
    24.    
    25.         if (this.projector) {
    26.                 //check if the projector has a material with a texture with teh internal name of this.textureName
    27.                 if (this.projector.material.HasProperty(textureName)) {
    28.                    
    29.                 //make a copy of the texture
    30.                 this.material = new Material(this.projector.material);
    31.                                
    32.                 //set the projectors material to the copy
    33.                 this.projector.material = this.material;
    34.  
    35.                 //force wraping
    36.                 this.material.GetTexture(this.textureName).wrapMode = TextureWrapMode.Repeat;  
    37.                
    38.                 this.initialTiling = material.GetTextureScale(this.textureName);
    39.                 this.initialOffset = material.GetTextureOffset(this.textureName);
    40.             }
    41.         }
    42.     }
    43.  
    44.     void Update() {
    45.             float scaleX = this.initialTiling.x + this.ComputePlacement(0, this.tilingSinusRange.x, this.tilingWaveTime.x, 1);
    46.             float scaleY = this.initialTiling.y + this.ComputePlacement(0, this.tilingSinusRange.y, this.tilingWaveTime.y, 1);
    47.             float offsetX = this.initialOffset.x + this.ComputePlacement(this.scrollSpeed.x, this.sinusRange.x, this.waveTime.x, scaleX);
    48.             float offsetY = this.initialOffset.y + this.ComputePlacement(this.scrollSpeed.y, this.sinusRange.y, this.waveTime.y, scaleY);              
    49.             this.material.SetTextureOffset(this.textureName, new Vector2(offsetX, offsetY));
    50.             this.material.SetTextureScale(this.textureName, new Vector2(scaleX,scaleY));
    51.     }
    52.  
    53.     private float ComputePlacement(float scrollSpeed, float sinusRange, float waveTime, float scale) {
    54.         float linearScroll = scrollSpeed * Time.time;
    55.         float sinusScroll = sinusRange * Mathf.Sin( (360 * Mathf.Deg2Rad * Time.time)/waveTime );
    56.         return (linearScroll + sinusScroll) * scale;
    57.     }
    58. }
     
  25. petewarbis

    petewarbis

    Joined:
    Sep 12, 2013
    Posts:
    1
    Hey zxcvasd,

    I'm having the same problem. Did you ever find a solution to this?

    Thanks,
    Pete
     
  26. Novodantis

    Novodantis

    Joined:
    Nov 12, 2009
    Posts:
    95
    I also have the same problem as zxcvasd; most likely something in the last few years has changed and caused Brady's original c# script to no longer work. Try as I might, I can't get it to find the "_Projector" Matrix property on the material (Projector/Light, which has the same structure as the other projectors as far as I can tell).
     
  27. Vashchuk

    Vashchuk

    Joined:
    May 24, 2012
    Posts:
    27
    Hi guys.
    Animated projector shader:

    Code (JavaScript):
    1. Shader "Projector/Animated" {
    2.     Properties {
    3.         _xSpeed ("xSpeed", Float) = 1.0
    4.         _ySpeed ("ySpeed", Float) = 1.0
    5.         _Color ("Color", Color) = (1,1,1,1)
    6.         _ShadowTex ("Projected Image", 2D) = "white" {}
    7.     }
    8.     SubShader {
    9.         Pass {  
    10.             Blend SrcAlpha OneMinusSrcAlpha // Alpha blending
    11.             CGPROGRAM
    12.  
    13.             #pragma vertex vert
    14.             #pragma fragment frag
    15.        
    16.             fixed _xSpeed;
    17.             fixed _ySpeed;
    18.             fixed4 _Color;
    19.             uniform sampler2D _ShadowTex;
    20.  
    21.             uniform fixed4x4 _Projector; // transformation matrix
    22.  
    23.             struct vertexInput {
    24.                 fixed4 vertex : POSITION;
    25.             };
    26.        
    27.             struct vertexOutput {
    28.                 fixed4 pos : SV_POSITION;
    29.                 fixed4 posProj : TEXCOORD0;
    30.             };
    31.  
    32.             vertexOutput vert(vertexInput input) {
    33.                 vertexOutput output;
    34.                 output.posProj = mul(_Projector, input.vertex);
    35.                 output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
    36.                 return output;
    37.             }
    38.  
    39.             fixed4 frag(vertexOutput input) : COLOR{
    40.                 if (input.posProj.w > 0.0)  { // in front of projector?
    41.                     fixed2 anim;
    42.                     anim.x = _xSpeed * _Time.y;
    43.                     anim.y = _ySpeed * _Time.y;
    44.                     return _Color * tex2D(_ShadowTex ,(fixed2(input.posProj) / input.posProj.w) + anim);
    45.                 }
    46.                 else { // behind projector
    47.                     return fixed4(0.0);
    48.                 }
    49.             }
    50.  
    51.             ENDCG
    52.         }
    53.     }
    54.    // Fallback "Projector/Light"
    55. }
    56.  
     

    Attached Files:

    Roy-Massaad1 and twobob like this.
  28. Roy-Massaad1

    Roy-Massaad1

    Joined:
    Jun 30, 2015
    Posts:
    16
    Hi guys,

    Vashchuk's shader is real cool but needs a few fixes to work on unity 2017 (and i suppose 5.6) without build errors

    line 45 should be

    Code (CSharp):
    1. return _Color * tex2D(_ShadowTex, fixed2(input.posProj.x / input.posProj.w + anim.x, input.posProj.y / input.posProj.w + anim.y));
    and line 47

    Code (CSharp):
    1. return fixed4(0.0, 0.0, 0.0, 0.0);
    this will make it run.

    on a side note since this is a shader for cloud use in theory, i prefer multiply blending to additive

    so i would also change Blend SrcAlpha OneMinusSrcAlpha on line 10 to

    Code (CSharp):
    1. Blend DstColor Zero