#The water in my game is basically a
1 messages ยท Page 1 of 1 (latest)
coool
first time using the threads feature
i understand the usecase now
anyhow
So my understanding of the ShaderGraph is that..
Each vertex, looks at the same Gradient Noise, offsets its Y position using some Multiply and Add Nodes
Now I need to somehow recreate this in C#
Though there is a lot of ambiguity in my mind
what exactly us UV0, How does Tiling and Offset work, What is Normal Vector, What is Position
Time was pretty straightforward to convert, it was just Time.time
also in case it does help, I was using this video as reference to set up my water shader
Let's make some simple cartoon water!
82% OFF for Web Hosting and FREE Domain included!: https://www.hostinger.com/brackeys
Coupon Code is "BRACKEYS" for an additional 15% discount.
The shader is based on this amazing video: https://youtu.be/jBmBb-je4Lg
GduX: https://www.gdux.me/
Game Dev Unchained: https://www.gamedevunchained.com/
ยทยทยทยทยทยทยทยทยท...
so the shader basically loops through the list of all vertices on the mesh and deforms them in a way you specify in the shader. this shader you're using uses the uv coordinate (also the local space normal which constant (0, 1, 0) in case of default plane) as a input to the gradient function. in order to understand this, we first need to take a look at what uv coordinate is
okay, with you so far
btw, it's actually Time.timeSinceLevelLoad (time after the last level load. for example when you first click start or load new level using script the value of time node will restart and so does Time.timeSinceLevelLoad)
ah okay
@tawdry swan actually, could you share the shader graph you have right now with me (as an actual shader graph file) so I could experiment with it. I'd change the shader a bit to make this little bit easier
oh sure, gimme a sec
Here, this works?
seems to work
cool!
ok so this is what I changed this to to more easily make this is c# (the uv coordinate depends on the mesh you're using so if you decide to change the plane later, you'd need to change the code). now if you multiply the wave speed (in inspector, not in the shader code itself) by 10 and divide the turbulance value (in inspector too) by 10, you should get exactly same look (assuming your plane isn't scaled, if it is, you can play around with the values to get the results you want)
ok let me try to understand this
okay.. this does look a bit more intuitive
I'm still a bit confused with the beginning and ending Position nodes though
what exactly do they give us?
they both give us the position of the vertex we are currently deforming. the only difference is that the one on the left is in world space (global coordinates. relative to the actual world coordinates) and the one on the right is in object space (relative to the objects transform)
I think the object space position is bit more tricky to understand am I right?
so if you imagine the vertex being child of the water plane, the object space value would be the one you see in inspector. even if you rotate or scale the plane, the object space value will remain the same
I kind of understand
so basically the object's transform will be the origin
0,0,0
and in relation to that
yes
My confusion is again, when recreating this in C# what do I plug in place of those two
and x axis would be the objects right direction, y would be up direction etc.
Everything else seems understandable to me
so now in the shader code the Position node gives the position of the vertex we are currently deforming (in world/object space). because we want to sample the water height at position named Position (the function parameter) we have to put in those places the Vector2 Position in world space and (the water planes) objects space
ok, so the first time around we provide the Vector2 Position in world space. Then towards the end we provide the same but in Object space instead (of water plane)
and we convert world space to Object Space using
waterPlaneTransform.InverseTransformPoint(Position)
you're figuring this out faster than I can type ๐, exactly
well, not exactly like that
but pretty close
the thing you forgot is that InverseTransformPoint takes a world space position (vector3) and Position is vector2 where x is x axis and y is z axis
im sure this is just beginning to scratch the surface of possibilities though haha >.<
so you can make new vector3 (Position.x, 0f, Position.y) and plot that to InverseTransformPoint
yupp that's what I had in mind
cool, I feel like im getting a handle on things..
Dude, Thanks so much for having the patience to sit through this with me
and explaining all of this
np mate
This graph makes sense to me I think. A bit hard to visualize everything thats going on, but slowly getting used to thinking in nodes
I think I can get cracking on this
one thing to note is that this node here is actually on the planes object space. you can get the actual world space position by using planeTransform.TransformPoint
because we are overwriting the y position to be always 0f (we should put the "vertices" y position in world space in there but in this case it doesn't matter), we are getting wrong y coordinate on the object space position. because the mesh is a plane (every vertex has y coordinate of 0 in object space) we can just set the y of the result of InverseTransformPoint to be 0f
okay so whatever float value I get from the final add function,
needs to be plugged back into a Vector3 and transformed using planeTransform.TransformPoint
The vec3 would look something like (0f, Height, 0f). This would convert it back into world space to be used by the cube
Since while inputting the Y is irrelevant, and while Outputting X and Z are irrelevant
actually you're getting the transformed position (vector3, not float) in the planes object space. that means you just need to put that vector3 in the TransformPoint function to get the world space position out of that
oh wait. yeah
at this point it would be good idea for me to try to do this myself to see if it works ๐. I'm not that confident I haven't made any mistakes
makes sense, im a dummy
ah don't bother going through the trouble >.<
I've got another hour or so before I head to sleep.. I'll try implementing this and update here if it works out or not
it's not trouble at all, i'll try that anyways
ohp well :P
i converted the hlsl functions to c#
now connecting all inputs and outputs
ok im done implementing it, time to test whew
im in testing part too ๐
well
it seems to be moving up and down somewhat with the phase of the wave
but its like, a few feet under the water
for some reason
nvm its glitching and teleporting
Transform myTransform = GetComponent<Transform>();
float waterLevel = GetHeight(new Vector2(myTransform.position.x, myTransform.position.z));
myTransform.position = new Vector3(myTransform.position.x, waterLevel, myTransform.position.z);
Does this seem like the right way to be changing position?
for me this seems to work perfectly fine expect the very first second which seems to be bit off. I think we are on right track tho
god damn that looks beautiful
well in that case there must be something wrong in my implementation
that very first second is fine
can I put my code here and you can have a look and tell me where i'm messing up?
or better if you share yours and i'll compare
This is mine
actually there seems to be something more wrong here. after some time, the ball seems to go off sync with the waves but for a moment it seems to work perfectly which is quite odd
Maybe the time variable?
or float precision loss??
dunno..
also hey, I'm gonna have to start packing up and heading off now, its like 5am here..
I'll have to continue on this in the morning
could you share your code for reference?
I'll have a look at it in the morning
yup
it's 2:37am here ๐
true ๐. this is mine: https://pastebin.com/Tqysb5wf. I don't think floating point inaccuracy can be reason for this (actually I may have an idea... let me check... or maybe not it seems)
it seems so weird because first it doesnt work, then it works perfectly for a moment and snaps off the road something like 10 seconds later. it still keeps going up and down but at wrong timing
ok, i'll continue debugging this tomorrow. because it still works for a moment, we are surely close to the correct solution
I'm back too. this is really confusing problem, I'm surely missing something obvious
for some reason it seems to be off sync for exactly 1 second at the very start
after that it seems to be going gradually more and more off sync
hmm
im going to try to implement your code in my project and try to experiment too
damn you're so much better at writing cleaner and efficient code >.<
I had all these unnecessary functions all over the place for simple calculations
I have a doubt in your code
Vector3 objectSpacePosition = plane.InverseTransformPoint(new Vector3(posXZ.x, 0f, posXZ.y)); Over here
You use plane.InverseTrasnform...
but
while plane is declared, its value is never initilizaed to anything
public Transform plane, sphere;
unless wait, you exposed that variable and set the value from there
im stupid
yep, it's public so I can drag and drop it from inspector. using GameObject.Find and GetComponent methods to find objects/components is bit clumsy, I just like using public keyword (usually I use [SerializeField] attribute instead)
aye
for the off sync think
could it be maybe that we need to multiply something with Time.deltaTime somewhere?
im not sure though
we shouldn't need to because we use Time.timeSinceLevelLoad already
hmmm
but I think the problem with off sync over time is related to Time.timeSinceLevelLoad somehow
wait a minute, that seems to be the case...
Would simply using Time.time be better?
I can try
but I don't think that's it
the time node seems to be doing something really odd
nope. Time.time wasn't any better, i'm currently experimenting with the time thingy
hmm man its so strange
it is. I have been told that _Time.y (which Time node uses) is exactly same as Time.timeSinceLevelLoad but actually they seems to get off sync after some time (it seems like _Time.y grows slightly faster than Time.timeSinceLevelLoad)
huh
well is there some sort of fixed rate at which it grows
which maybe we can just hardcode?
oh or maybe
instead of in
void Update(){}
we run it in
void FixedUpdate(){}
would that make a difference?
also umm
unsure what i'm doing wrong
but its not working on my end..
for some reason
it tells the time in seconds after the last level load meaning it should grow exactly 1 unit per second. the function we are doing this should have nothing to do with this because we use Time.timeSinceLevelLoad
btw you have to use exactly same waveSpeed and turbulence values as you do in the shader code
I am, infact i'm pulling the values from the shader itself
Vector3 GetPosition(Vector2 posXZ)
{
float waveSpeed = rend.material.GetFloat("_Wave_Speed");
float turbulence = rend.material.GetFloat("_Turbulence");
float time = Time.timeSinceLevelLoad/*Shader.GetGlobalVector("_Time").y*/ * waveSpeed;
Vector2 addNode = posXZ + Vector2.one * time;
float gradientNode = Unity_GradientNoise_float(addNode, turbulence);
Vector3 multiplyNode = new Vector3(0f, gradientNode, 0f);
Vector3 objectSpacePosition = plane.InverseTransformPoint(new Vector3(posXZ.x, 0f, posXZ.y));
objectSpacePosition.y = 0f;
Vector3 finalAddNode = multiplyNode + objectSpacePosition;
return plane.TransformPoint(finalAddNode);
}
I'm currently trying to build the game to see how the Time.timeSinceLevelLoad and _Time.y works there. in the editor it seems those are definitely not the same (_Time.y doesn't even seem to reset when I load the scene again)
okai
wait that's weird. I kept the code same, but changed the turbulence and wavespeed to match it to what you've set it
and now it works
why is it only working for specific values?
The same exact code.
It works like you are showing at
Wavespeed = 2```
But if I change it back to
Turbulence = 2
WaveSpeed = 0.05
It stops working
works perfectly?
no i mean^
Try adjusting the Turbulence and Wavespeed on ur end to
2 and 0.05 respectively
it doesn't work properly at those valules
for me it works just as "properly" (doesn't work at first and goes off sync over time) as it did with 20 and 0.02
it works like this for me at 2 and 0.05
so it doesn't work at all...
I'm really confused about _Time.y now... according to docs it should be
Time since level load (t/20, t, t*2, t*3), use to animate things inside the shaders.
but it seems it's for sure not time since level load
just a thought.. Maybe the time itself is actually fine.
but the gradient function
does some weird math with integer and float subtractions
could that be going wrong in C# somehow?
Maybe this
have to try that too
wait... why does print(Shader.GetGlobalVector("_Time").y); give these values? that's surely not same as Time.timeSinceLevelLoad. maybe I should ask about this in #archived-shaders. maybe unity have changed this behaviour
how much is the difference between the two??
about 6000 seconds ๐
actually, I think I know what's happening. print(Shader.GetGlobalVector("_Time").y); seems to give different value when I'm looking at game view and scene view
huh
ok wait
what is game view vs scene view
ik its probably a noob question
i've implemented a differnet frac function, testing with it rn
Vector2 frac(Vector2 p)
{
string sx = p.x.ToString().Substring(p.x.ToString().LastIndexOf('.'));
string sy = p.y.ToString().Substring(p.y.ToString().LastIndexOf('.'));
return new Vector2(float.Parse(sx), float.Parse(sy));
//return new Vector2(p.x % 1f, p.y % 1f);
}
scene view is the one you use to edit things and move things around and game view is the view of the camera
ah ok
wait, what is that horrible stuff ๐
instead of doing x%1f to get the decimals off a float
its doing string manipulation
i know it looks horrendous
but its just a test >.<
that is horrendous, doing float calculations using strings, yuck
aand it has no effect whatsoever
it just gives the same result
going back to %1f ...
let me ask this _Time.y stuff on #archived-shaders
oki
im trying to implement what Cyan suggested for now
just testing if it does solve the issue
okay...
thats strange
even with a custom variable which Updates in C# itself being used as time
it goes off sync
public Transform plane, sphere;
float WaveTimer = 0f;
//Get Rendeder to get Material to get floats from
Renderer rend;
void Start()
{
//Get Water Plane Renderer
rend = plane.GetComponent<Renderer>();
}
void Update()
{
WaveTimer += 0.005f;
rend.material.SetFloat("_Wave_Timer", WaveTimer);
sphere.position = GetPosition(new Vector2(sphere.position.x, sphere.position.z));
}
Vector3 GetPosition(Vector2 posXZ)
{
float waveSpeed = rend.material.GetFloat("_Wave_Speed");
float turbulence = rend.material.GetFloat("_Turbulence");
float time = WaveTimer * waveSpeed; /*Time.timeSinceLevelLoad //Shader.GetGlobalVector("_Time").y*/
Vector2 addNode = posXZ + Vector2.one * time;
float gradientNode = Unity_GradientNoise_float(addNode, turbulence);
Vector3 multiplyNode = new Vector3(0f, gradientNode, 0f);
Vector3 objectSpacePosition = plane.InverseTransformPoint(new Vector3(posXZ.x, 0f, posXZ.y));
objectSpacePosition.y = 0f;
Vector3 finalAddNode = multiplyNode + objectSpacePosition;
return plane.TransformPoint(finalAddNode);
}
This is just strange...
.
does this mean that the Time.time being out of sync is not the issue?
I think it does, which means we have error somewhere in our calculations
I think I'm about to get this (once again)
hmm
I'm fiddling around with the GradientNoise C# Calculations
That is the function which has the most weird calculations
3rd times the charm
.<
I get this feeling that if it doesnt work out
The next step could be to generate the Noise in C# using Mathf.PerlinNoise
I'm currently trying to use the GradientNoise function inside compute shader to see if there's difference between c# and hlsl version (i'm generating texture using both)
and then Pass that into the ShaderNode
what is a compute shader?
it's basically a hlsl code that runs on gpu and can generate/modify textures/buffers
okay.. how is it different from the normal ShaderGraph?
doesnt it do the same thing?
it does what I tell it to do. I'm currently trying to give it the gradient noise function from the shader graph docs
oh ok
yep, the problem is somewhere within the generate noise function. see, with noise scale of 0.1, both looks pretty much the same (left is generated by c# script and right is generated by compute shader running the exact hlsl code copied from the docs page) but not quite
scale of 2.433
and scale of -0.1, lol ๐ (I mean you're not supposed to use negative scale ig but still, doesn't look the same as they should)
Ah god damn
well there we go..
in HLSL
float2 Unity_GradientNoise_Dir_float(float2 p)
{
// Permutation and hashing used in webgl-nosie goo.gl/pX7HtC
p = p % 289;
// need full precision, otherwise half overflows when p > 1
float x = float(34 * p.x + 1) * p.x % 289 + p.y;
x = (34 * x + 1) * x % 289;
x = frac(x / 41) * 2 - 1;
return normalize(float2(x - floor(x + 0.5), abs(x) - 0.5));
}
this function has these two comments
I have no idea what they actually mean, but they sound very important
would it maybe be better to work in Double instead of float?
I thought that too at first but it doesn't really matter atleast not at this point. becasue the shader code uses single precision floats too, it wont be the reason behind this
yeah..
most of the issues seems to happen with negative uv values (off sync seems to happen when further away from origin too) which makes me believe it has something to do with frac/floor/abs functions
hmm
I think I got it..?
so frac() is supposed to return the decimal part to us
so for example frac(1.23) should return 0.23
but should frac(-1.23) return -0.23 or 0.23
because using -1.23%1f is going to return -0.23 not 0.23
does the return value have to be absolute?
Yeah.. % operator seems to be the wrong way of going about things
frac(-1.2) should return 0.8
but in our case it would return -0.2
heck, I think I'm dum
Yo
i think...
I made a change to the frac function
It is no longer doing that 1s delay before it snaps into position on start
though it is still going off sync
that's different problem then ๐ , here we go again
the new frac function btw
Vector2 frac(Vector2 p)
{
return new Vector2(p.x-Mathf.Floor(p.x), p.y-Mathf.Floor(p.y));
//return new Vector2(p.x % 1f, p.y % 1f);
}
can you generate the textures with this frac function and see how it works out?
also dude, you're going above and beyond in helping me, I hope im not taking away time from your chores and work and stuff
no worries. if I wasn't doing this, Id have played mobile games/watched yt videos whole morning, this is much better way to spend time ๐
this fixed the negative weirdness but the off sync problem remains
can you send an ss of how it looks?
let me actually send you the compute shader and the script i'm using to generate the textures
yes please, i was researching how to write my own and it was unfortunately going all over my head
this is the compute shader
here is the c# script to generate the textures (sorry, took some time): https://pastebin.com/w2vDU6wy
npp at all
ok wait i have one more doubt >.<
where do I attach this script
to run it
doens't matter, to any active object. if you just remember to drag the plane1, plane2 and computeShader in inspector, it doesn't matter
oh yeah, that's where I think the bug actually is. any whole number as a scale gives that blank thing (doesn't work like that in shader graph)
hmm
ah ok
i changed it to 30.23 and it does display
yeah i can see the differences
hmm
If you put something like 0.1 in it, you get the normal looking gradient thing
yup
got it
I can see like minute differences near the boundaries of the planes
which then add up and change a lot as the offset changes
yeah
hmm
seems to me like there is some weird different math working behind the scenes
how can this even be fixed >.<
just fix the math ๐
well..
if only it were that easy T_T
I mean, HLSL and C# are interpreting the same math
in different ways
how do we get them to see eye to eye
hmm
maybe I should try to create the c# noise function again very carefully
how much more careful, it looks pretty correct to me >.<
i don't see what could be changed further
lmao
I have one more solution..
Can we use this
and then simply pass in the Same function we use in C# into this node
then we can plug in the Custom Node instead of gradient noise node
hold on
oki
well, it wasn't that. I spotted this error here but it didn't fix anything I think
that's exactly I was going to look at next. I have to go eat something now but I'll come back bit later
all good man, enjoy your meal!
people facing same issue as here
Also..
is it possible to just use the Compute shader to make those calculations
since it works in HLSL
the output "Should" be same?
And then pass the value back to C# using a buffer or something
in theory yes, why not. but that's not going to be optimal solution in any way (if you only need to calculate single value, gpus and shaders are good at calculating thousands of values simultaneously)
except if you calculate a lot of values at once
I understand that GPU's are great at working calcs in parallel
yes, they are incredible fast
but is there any downside to actually just giving it a single calc
Like does it hog resources from other tasks, or is it generally slower at single calculations than a CPU?
i'm pretty sure it is slower than cpu, yes. the thing is, gpu can calculate a lot of things parallel but it can't calculate single calculation at once. gpu calculates things using so called "wavefronts" which nowadays consists 64 threads meaning all of the 64 threads (gpus can also lauch couple of wavefronts at once, many gpus have thousands of threads on them) will calculate the same thing even if you use the result of only one of them. I'm also not sure what is the general cost of preparing the threads for calculations/moving data between cpu and gpu etc.
I can't really say using compute shader is bad solution tho. not so long ago I made conways game of life using compute shaders and I managed to use 8192x8192 grid simulated every frame at realtime (I didn't read the data back to cpu tho, afaik that's the slowest part. I just rendered the map using the buffer calculated in the compute shader). if I can calculate 67 million values per frame, I don't think 1 (well technically 64 ig) will cause that many problems, I think only way to know is try and see
Yeah.. I'm looking at a video on introduction to compute shaders
Trying to understand how it works
I'm gonna have a shower first, will continue in a bit
the compute shader approach would allow you to calculate a lot of positions at once if you need many floating objects for example (maybe millions? no problem ๐)
probably not in the millions, its only an arena survival type thingy
but yeah..
i'm gonna try my hand at this now
I just got this working using compute shader
seems to stay on sync forever
I'm not actually sure if this is usable in actual game application. for me it seems to take several milliseconds per call (maybe 5 ms). i'm using dell latitude 3300 laptop atm so that's obviously not the most optimal gaming pc but still that sounds quite lot. if it's possible to do some other way, i'd probably choose not to use compute shaders in this case (I think reading the data back from gpu to cpu is the heaviest part here even though it's only 32 bits). you can obviously try that yourself and see how it performs
woah
i'm still learning how to implement this in a compute shader >.<
first time working
with them
5ms huh..
dang
do you think there is any other way to go about solving this problem?
I feel so dum I'm only asking this at this point but do these floating objects only exist for visuals or do you want to interact with them in some way?
ah ok
To calculate buyoyancy for objects
otherwise i'd have just made them into a shader as well :P >.<
yeah, that's why I asked
can you show me how you got the calculations into a compute shader
i'm struggling to understand this..
only way I can think of now would be to use precalculated texture instead for the gradient stuff and sample that in both water shader and cpu side
the precalculated texture would have to be about as big as the water in my game then
and it would only work for fixed Turbulence and Wavespeed
i'd have to generate a new one every time right..?
and even then, how would I make the waves actually happen unless this texture is infinitely big
why? just scale the texture/scroll it faster
seamless texture is what I had in mind
oh wait yeah
hmm, that would make repeating patterns in waves but it would work
how would I go about making a seamless texture like this
if the texture is something like 1024x1024, you can't really notice the repeating patterns ig
I found this great site some time ago: http://kitfox.com/projects/perlinNoiseMaker/
just make sure:
The final image will tile seamlessly if the width and height of the image are whole multiples of the cell spacing. For best results, use numbers that are powers of 2 for the image width, height and cell spacing
I'm gonna try this compute shader stuff first, observe the performance issues. If they seem like a huge problem to me at this stage or even later.
I'll overhaul this, into this new method that you're suggesting.. it does sound much more resource friendly and consistent..
In that case i'd have to learn a bunch of things.
1) Generating a seamless noise texture
2) Passing a pre calculated texture in place of Gradient Noise
3) Reading values from a texture in C#
but it does sound doable
and hey howsoever this ends up, i've ended up learning a lot of shaders, hlsl, c#, etc..
so thats good
cool understood
also
could you share that compute shader code with me?
that you're working with
I'm having trouble understanding how to Get values after dispatching a shader
you mean the actual hlsl cs code or the c# one?
both >.<
i assume a c# script is dispatching a compute shader from within it
then getting the values calculated by the compute shader somehow
i wanted to see both, i'm looking at references online, but I'm having some doubts
so this is the cs code
this is how I dispatch the shader and read the data back. arrayData is just float[] arrayData = new float[1] which unity then fills with the results from the buffer when buffer.Getdata is called. ```cs
computeShader.SetVector("_Uv", addNode);
computeShader.SetFloat("_Scale", turbulence);
computeShader.Dispatch(computeShader.FindKernel("CSMain"), 1, 1, 1);
buffer.GetData(arrayData);
float gradientNode = arrayData[0];
okay, looks like I was on the right track with the .compute at least..
hmm okay, I think this makes sense to me
and float[] arrayData = new float[1] is declared within the GetHeight funciton itself
any reason why we get data in form of an array instead of like just a float?
this is how I create the buffer (with one element that contains 4 bytes) and give it to the shader:
buffer = new ComputeBuffer(1, sizeof(float));
computeShader.SetBuffer(computeShader.FindKernel("CSMain"), "Result", buffer);
that's only defined once at the top of the script. same way the buffer needs to be created and given to the compute shader only once (this is done in start method)
okay, makes sense
oh ok
atleast I don't know a way to write into float field in compute shader. compute shaders are meant to compute huge amount of data so it only supports textures and buffers (which are basically just array of given data type/structure)
I don't actually know if using 1x1 RenderTexture (render texture is texture that's specifically meant to be used to read from/write to in shaders. regular textures cannot be written to in shaders) would be better in some odd way, most likely not
yeah the video I saw was using a texture which the shader wrote to
but idk if it'll be faster
doesn't it still have to pass the data from GPU to CPU somehow
okay i got the ocmpute shader working..
can I ask you how did you measure the 5ms latency?
I did you Stopwatch from System.Diagnostics, it's not really a good way to measure performance but should give some idea
well, thats a whole new thing to learn ๐
for now.. I think this works out
I'll continue working on the game, keep checking how performance holds up
Thank you so much again
I can't begin to thank you enough >.<
Learnt a lot
I think we're good to archive this thread now too
np
Stopwatch is basically just a timer. you can create it like any other c# object by doing Stopwatch stopOrAnyOtherName:) = new Stopwatch();. when you want to start the timer, you call stop.Start(); and when you want to end it, you call stop.Stop();. after you have stop the timer, you can see how much time have elapsed between Start()/Restart() and Stop() by using stop.Elapsed.TotalMilliseconds
oh its literally like a stopwatch operated through code
that sounds rad..
I also want to ask
this ComputeShader.Dispatch function
its Syncronous or Async?
yeah
async, kind of
meaning it will literally hold the execution of the rest of the C# script until it finishes?
or no?
usually the c# script will not wait for the compute shader to finish but if you call buffer.GetData (or do something with the render texture I think?) in the c# script, the script will wait for the shader and after that reads the values from the buffer
What you mean by that?
like when we look at the list of threads under #archived-code-general , you can see active threads and ones which have been "archived" or closed
I assume this thread has well beyond served the purpose now :P
so we can close it I think
Ah i thoguht you meant gpu threads ๐. These threads gets deacticated/archived after they have been unused for certain amount of time (maybe day or few). We dont need to do anything ourself
Gn
wellp
the problem extends..
This is my new node setup
I'm using a SampleTexture2D node here to use pregenerated image noise from a .png file
and my C# converison is
now for some reason GetHeight() only returns a constant value
the value is not updating at all for some reason :(
This is the noise im using
I checked by printing values
and it seems there is something that i'm doing wrong when it comes to C#
this is a long freakin thread that I only really glanced through, I guess something that kinda stood out to me is I don't see a modulus in the tiling calculation. Is the perlin noise texture set to wrap or clamp? sorry if not helpful, don't have time to follow along further. Would probably be helpful to see your printed values at various points in GetHeight
ah no need to follow along the entire thread, most of it is unrelated to current problem
wdym modulus in tiling calculation?
so when I look at the Generated code for the TIling And Offset node, I get this in hlsl
can you just double check if your perlinNoise texture is set to wrap?
okay lemme see
float time = Time.time * waveSpeed;
Vector2 addNode = posXZ + (Vector2.one * time);
Vector2 tilingNode = addNode * turbulence;
Looks like
it is
Repeat right?
yeah that's fine then
The thing is the ShaderGraph setup itself is working,
its just when I'm trying to emulate the TilingNode in C#
The values I'm getting are
well they don't seem right
what about the values you printed inside GetHeight?
which ones?
Oh wow wait
hold on
I understand the problem happening..
Color value = perlinNoise.GetPixel(Mathf.FloorToInt(tilingNode.x), Mathf.FloorToInt(tilingNode.y));
Over here I use Mathf.FloorToInt
which well, rightly so floors the values to 0.. since tilingNode.x is a really small float like 0.00xx
I think this is a limitation of the fact that a png image can only really take whole numbers as coordinates
really low turbulence value causing that?
yeah..
the thing is I need the turbulence values to match in the ShaderGraph and C#
What i'm doing here is displacing the vater using a ShaderGraph.
But I also need to calculate the "height" of water at any given X/Z coordinates in the world. So I can have objects which use that "height" and float in the water
actually wait, don't UVs in shaders cover the whole distance in texture from float 0f to 1f representing how far along the x/y axis of the texture, or am I misremembering.
I haven't.. the faintest Idea
try multiply by texture width/height before flooring to int in getPixel
so..
Color value = perlinNoise.GetPixel(Mathf.FloorToInt(tilingNode.x*texture.width), Mathf.FloorToInt(tilingNode.y*texture.height));
?
i'll try
oh huh
it seems to be working..
I think
correctly?
let me plug in the transforms and check
yeah.. no
the values seem to be offset a bit than the ShaderGraph
I think
the empties are moving up and down, but out of sync with how the ShaderGraph is displacing the water
same cycle duration though? (amount of time to go up & down once?)
I can only say visually, but it looks about right
oh yeah and its
Super laggy
and chunky
is it because the Texture2D is too low resolution?
its a 1024x1024 png image
yes/no, I believe shaders also interpolate between points when sampling from textures, but I can't say without research how
you could maybe try lerping the texture color between rounding down & rounding up based on its integer remainder
hmm
hey but wait
there is someone
In this article the person is having the same exact application / use case as me
but they have got it to work
the problem is they have only provided part of their code out of context
and its a bit difficult for me to understand theirs
wait hold on
wrong article
I have made a simple shader graph that takes in a height map and modifies the objects vertices accordingly. I'm planning to use this to generate a sea...
float texX = tilingNode.x*texture.width;
float texY = tilingNode.y*texture.height;
Color lowValue = perlinNoise.GetPixel(Mathf.FloorToInt(texX), Mathf.FloorToInt(texY));
Color highValue = perlinNoise.GetPixel(Mathf.CeilToInt(texX), Mathf.CeilToInt(texY));
Color value = Color.Lerp(lowValue, highValue, texX - Mathf.FloorToInt(texX));
I'll take a look, sorry I just wanted to finish writing that lol
no problemo
tried this
While it is generally more smoother
it still jitters up and down for some reason, and out of sync with the water itself
well I do see that in the page you linked they are getting the linearized color, I don't actually understand why but supposedly it matches the shader more closely
float textureX = Mathf.Lerp(displMapSize.x, 0, Mathf.InverseLerp(0, oceanSize.x, pointPos.x));
float textureY = Mathf.Lerp(displMapSize.y, 0, Mathf.InverseLerp(0, oceanSize.z, pointPos.y));
``` They are also lerping the tex coords before getting the color (get rid of color lerp), so I guess try that
hmm
I have confusion regarding this
I don't exactly understand what the math behind it is doing
the syntax is a bit overwhelming
with nested lerps
hard to visualize
and what would be the variables i plug in instead of theirs
ok, I understand why they are doing it and it doesn't make sense in your case. They are applying height based on position along object, while you are doing it in world space. I do still think you need some kind of interpolation between colors to smooth it out as you move across the texture, and maybe try playing around with the linearized color. Also maybe try posting in advanced lol.
going to sleep now, gl ๐
thanks for help mate!