sine/cosine optimization?

Hi all!
I’m working again (after more than 1 year) on my ocean shader (yes… I know there is community ocean now… but I like to explore something different :slight_smile: ).
Using waves (a lot of waves) my material performs a lot of sine/cosine operations for each vertex of a high tesseleted mesh, so I asked myself “is it possible to make sine/cosine faster?”.
Instead of approximating the value using some other formula, I’ve created a 256x2 pixel lookup texture containing a greyscale “sine” (with a viewport screenshot at first, with a DrawMaterialOnRenderTarget then) and I use it to output the value of a sine (for example, put a Time node as UV and you’ll have a 1 second period sine).
So… it works! Sine and cosine with no difference (at first glance) from the standard node.
But my question is: the instruction count is a little higher with my system, but I suspected that look up a texture could be faster than compute a real sine… Am I wrong?
What do you think about that?
Please remember that my idea is to optimize a material with a lot of sine/cosine nodes… of course the standard node will be better for simpler shaders.


I would expected texture lookup to be overall slower than trig function. Have you ran any conclusive tests?
Plus, you are likely to run with precision issues with texture, compared to math. Might be not severe enough to notice though.

The fastest way of evaluating sum of sine waves, that is known to me so far, is sparse fast Fourier transform

Hi Deathrey!
Conclusive tests… not yet. I was building a testing material right a few minutes ago but the engine crashed :smiley:
Maybe you’re right, mine is just an idea maybe worth a try (maybe not :slight_smile: )

Yeah definitely worth a try. Be sure to share the results. :smiley: It is quite interesting.

sine and cosine are single instructions. You can´t optimize it.

Mars, I think you’re right.
At the moment I’ve tested a material with 48 sine and 48 cosine operating on different channels of WorldPosition and VertexNormal on a 441 vertices plane.
On my GTX980 I have an almost fixed 120fps… opening another window to slowdown the engine I see that trying both materials my framerate remains at about 82-85 fps.
I did just a very rough test but I don’t see any particular difference.

I did the same thing when I was doing my gerstner wave stuff, but was unable to see any convincing benefit to storing sine and cosine in a texture. I stored Sin as Red and Cosine as Green.

My shader had 18 gerstner waves (which means 18 sine and 18 cosine operations), and around 500k polys. I tested on both the vertex shader and pixel shader. In some cases, original sin/cos instruction was faster, in some cases the texture was faster but it was pretty slight from what I recall, so I just abandoned it. Basically, modern GPUs are pretty fast at doing sine and cosine. I even tried using “Linear Sine” which uses a function to remap a triangle gradient to be round, but it was much slower in addition to using far more instructions.

Hi Ryan!
I did exactly the same thing (well, at first I used only 1 texture and added an offset to obtain cosine, but in the end I also used 2 channels).
Unfortunately it seems useless in order to optimize the material and use more waves (that was my actual goal).

This is a little “off topic” since we’re talking about plan sine/cosine but I had this other idea: store in R G B and A 4 different sine with different period and phase, then use one lookup to obtain 4 values and see if this could work to use more waves at the cost of one. I’m not really sure about that, but it could be useful to reduce the overall sine/cosine numbers.
Or maybe…it’s just a silly product of my tired mind in this evening :slight_smile:
(Off topic again: I’ll dig more in the DrawMaterialToRenderTarget because maybe (speaking of oceans) precompute different displaces and stor them in textures could be ok)