I basically have a caustics texture that i want to project coming from the light direction of my main directional light. Planar Mapping should be the solution to this, for example using just this line of code to project it from the xy plane of the world works pretty straight forward. Code (CSharp): fixed caustics = tex2D(_CausticsTex, IN.worldPos.xy); I thought of replacing the world position with _WorldSpaceLightPos0.xy, which should be the light direction vectors, but it just results in a glitchy color change. Does somebody has an idea how to solve this?
Why you not use light cookie? I think you can use "unity_WorldToLight" matrix to project texture coords.
That's not possible, because it should be a seamless projection across the objects, ignoring their original uvs. I also thought about it, but for example, i cant mask a light cookie to under beneath a give surface, in my case, the water surface. (Atleast i don't know any way how) Also I'm nor sure how light cookies play with batching and so on. That's why i want to have the caustics on each object themself and just blend it in based on an height number from the watersurface. And the light direction as projection base would be perfect for giving it directionality.
Ok, so i tried around with unity_WorldToLight and it goes into the right direction, but still has two errors- So this is the code im using now: Code (CSharp): float2 lightSpaceUVs = mul(unity_WorldToLight , float4(IN.worldPos, 1)).xy; First, it seems to work ok, but when i look with my camera from a specific angle on it, theres some glitching happening? I noticed this in general with light pos stuff- And secondly, theres some weird stuff with the definiton of unity_WorldToLight. I need to define the float4x4 unity_WorldToLight for it to be declared, because else he wouldnt find the matrix. Then he says tho, that its a redefiniton. Now when i add #inculde "Autolight.cginc", where this is supposed to be and i delete the redef in my shader, he just can't find it anymore- (Also this only seems to work in deferred, as in forward, the texture doesn't get moved at all-)
I was try use that matrix, no luck, I have no clue how to use it without cookie. Pass worldToLocalMatrix from script, it's do the job if you have only one light source. Code (CSharp): using UnityEngine; [ExecuteInEditMode] public class SetLightMatrix : MonoBehaviour { void Update() { Matrix4x4 mat = transform.worldToLocalMatrix; Shader.SetGlobalMatrix("PrjMatrix", mat); } }
Flogel can you give a bit of rundown on how to get caustics to be applied to multiple materials but look like the same caustics? Right now I have a caustics shader working and it looks lovely except that each object has its own caustics. Any help you can provide will really help me, I have been pulling my hair out for a few days and you seem best placed to answer this!
Can you elaborate a bit on that? Ive only been learning shaders for about 18 months so I am still not the best! Wouldnt I also need to use the depth buffer to some degree? Anyone that can shed a bit more light on this I will be very happy! Alternatively I can make a new thread if anyone thinks thats pertinent @flogel any help you can provide will be greatly appreciated. I will repay you in kind words and virtual hugs!
Well basically if you want to have the caustic being coherent to the world coordinate (ie seamless between multiple object) you must project onto that set of coordinate, if each object have different caustic references, but coherent to themselves, so you probably is in object space. If the caustics move with the object, then you are in object space. Just find the part that use coordinate and replace with world space, it's not specific to shader, it's just teh basic logic. Try to find shadow casting algo lik in cat like coding tutorial and look at teh part where the read the texture.
Sweet! Glad that's working for you atleast! About the coherent look across objects, @neoshaman is quite right regarding the worldcoordinates. It's actually quite simple to atleast get some world coordinate textures going, it gets a bit more complicated when adding in the lightdirection though! Does the light direction stuff already works for you? Would be awesome if you could share your code her! For example you can just use the worldpos.xz as the UV coordinates of a texture and already have a texture projected from the top onto every object! You can do cool stuff with that alone already! (Isn't regarding your problem tho, just a general hint)
So I was following the alan zucconi tutorial that I am pretty sure is based on a tweet of yours, and ended up with the following: Code (CSharp): // Caustics UV fixed2 uv = IN.uv_MainTex * _Caustics1_ST.xy + _Caustics1_ST.zw; uv += _Caustics1_Speed * _Time.y; // Sampling // RGB split fixed s = _SplitRGB; fixed r = tex2D(_CausticsTex, uv + fixed2(+s, +s)).r; fixed g = tex2D(_CausticsTex, uv + fixed2(+s, -s)).g; fixed b = tex2D(_CausticsTex, uv + fixed2(-s, -s)).b; fixed3 caustics1 = fixed3(r, g, b); // Caustics 2 sampling uv = IN.uv_MainTex * _Caustics2_ST.xy + _Caustics2_ST.zw; uv += _Caustics2_Speed * _Time.y; // Sampling s = _SplitRGB; r = tex2D(_CausticsTex, uv + fixed2(+s, +s)).r; g = tex2D(_CausticsTex, uv + fixed2(+s, -s)).g; b = tex2D(_CausticsTex, uv + fixed2(-s, -s)).b; fixed3 caustics2 = fixed3(r, g, b); // Blend o.Albedo.rgb += min(caustics1, caustics2) * _CausticsStrength; It samples twice and blends between and the effect is working great, but as far as I can see its seperate per object right now. So based on what you were saying about worldPos.xz, would I put that in the Code (CSharp): fixed r = tex2D(_CausticsTex, uv + fixed2(+s, +s)).r; fixed g = tex2D(_CausticsTex, uv + fixed2(+s, -s)).g; fixed b = tex2D(_CausticsTex, uv + fixed2(-s, -s)).b; bit in the place of the uv co-ordinates (keeping the +s -s bit as thats for the RGB split effect)? Also I noticed you said worldPos.xz but in the original comment at the top of this thread you used xy, just checking which I should be using? Thanks for getting back so fast
Yes, exactly! This should now be in world space from the top (i think-) .xz are the coordinates when you want to project it from top, while .xy are from the side in world space. I'm can't exactly remember why I used .xy specifically, but i probably worked this way with the lightmatrix in combination. Using the world coordinates only will give you a top or side view in worldspace. (That's why the lightmatrix is super helpful, since it projects the same worldspace coordinates from the sun direction) I hope this clears the whole thing up a bit!
Okay fantastic, thanks so much that really helps a lot Will give this a go when I get home from work Thanks again!
Half a year later now and I found out, that you can actually use the built-in unity_WorldToShadow[0] Matrix, instead of making an extra script, that sets the matrix of your main directional light global. Just makes things easier~
Hi, flogel! This post helps me a lot, thanks. Unfortunately, "unity_WorldToLight" in Unity 2019.4.11f still has some trouble to use. But the method @mouurusai put forward works fun, and i get the correct result. As the method using "unity_WorldToShadow[0]", the caustics changes strangely while moving cam. Code (CSharp): half2 uv = mul(unity_WorldToShadow[0], float4(i.worldPos, 1)).xy; Any wrong with this code? Thanks