GhettoFett

03-17-2015, 12:11 PM

Dear fellow OpenGL-ers

I've spent the last week or so rendering a simple ocean using gerstner waves but having issues with tiling, so I decided to start rendering them "properly" and dip my toes into the murky waters of rendering a heightfield using an iFFT.

There are plenty of papers explaining the basic gist -

1) calculate a frequency spectrum

2) use this to create a heightfield using ifft to convert from frequency domain to spatial domain - animating with time t

Since the beginning of this journey I have learned about things like the complex plane, the complex exponent equation, the FFT in more detail etc but after the initial steps of creating an initial spectrum (rendering a texture full of guassian numbers with mean 0 and sd of 1, filtered by the phillips spectrum) I am still totally lost.

My code for creating the initial data is here (GLSL):

float PhillipsSpectrum(vec2 k){

//kLen is the length of the vector from the centre of the tex

float kLen = length(k);

float kSq = kLen * kLen;

// amp is wave amplitude, passed in as a uniform

float Amp = amplitude;

//L = velocity * velcoity / gravity

float L = (velocity*velocity)/9.81;

float dir = dot(normalize(waveDir),normalize(k));

return Amp * (dir*dir) * exp(-1.0/(kSq * L * L))/ (kSq * kSq) ;

}

void main(){

vec3 sums;

//get screenpos - center is 0.0 and ranges from -0.5 to 0.5 in both

//directions

vec2 screenPos = vec2(gl_FragCoord.x,gl_FragCoord.y)/texSize - vec2(0.5,0.5);

//get random Guass number

vec2 randomGuass = vec2(rand(screenPos),rand(screenPos.yx));

//use phillips spectrum as a filter depending on position in freq domain

float Phil = sqrt(PhillipsSpectrum(screenPos));

float coeff = 1.0/sqrt(2.0);

color = vec3(coeff *randomGuass.x * Phil,coeff * randomGuass.y * Phil,0.0);

}

which creates a texture like this:

wave.png

Now I am totally lost as how to :

a) derive spectrums in three directions from the initial texture

b) animate this according to time t like mentioned in this paper (https://developer.nvidia.com/sites/default/files/akamai/gamedev/files/sdk/11/OceanCS_Slides.pdf) on slide 5

I might be completely stupid and overlooking something really obvious - I've looked at a bunch of papers and just get lost in formulae even after acquainting myself with their meaning. Please help.

I've spent the last week or so rendering a simple ocean using gerstner waves but having issues with tiling, so I decided to start rendering them "properly" and dip my toes into the murky waters of rendering a heightfield using an iFFT.

There are plenty of papers explaining the basic gist -

1) calculate a frequency spectrum

2) use this to create a heightfield using ifft to convert from frequency domain to spatial domain - animating with time t

Since the beginning of this journey I have learned about things like the complex plane, the complex exponent equation, the FFT in more detail etc but after the initial steps of creating an initial spectrum (rendering a texture full of guassian numbers with mean 0 and sd of 1, filtered by the phillips spectrum) I am still totally lost.

My code for creating the initial data is here (GLSL):

float PhillipsSpectrum(vec2 k){

//kLen is the length of the vector from the centre of the tex

float kLen = length(k);

float kSq = kLen * kLen;

// amp is wave amplitude, passed in as a uniform

float Amp = amplitude;

//L = velocity * velcoity / gravity

float L = (velocity*velocity)/9.81;

float dir = dot(normalize(waveDir),normalize(k));

return Amp * (dir*dir) * exp(-1.0/(kSq * L * L))/ (kSq * kSq) ;

}

void main(){

vec3 sums;

//get screenpos - center is 0.0 and ranges from -0.5 to 0.5 in both

//directions

vec2 screenPos = vec2(gl_FragCoord.x,gl_FragCoord.y)/texSize - vec2(0.5,0.5);

//get random Guass number

vec2 randomGuass = vec2(rand(screenPos),rand(screenPos.yx));

//use phillips spectrum as a filter depending on position in freq domain

float Phil = sqrt(PhillipsSpectrum(screenPos));

float coeff = 1.0/sqrt(2.0);

color = vec3(coeff *randomGuass.x * Phil,coeff * randomGuass.y * Phil,0.0);

}

which creates a texture like this:

wave.png

Now I am totally lost as how to :

a) derive spectrums in three directions from the initial texture

b) animate this according to time t like mentioned in this paper (https://developer.nvidia.com/sites/default/files/akamai/gamedev/files/sdk/11/OceanCS_Slides.pdf) on slide 5

I might be completely stupid and overlooking something really obvious - I've looked at a bunch of papers and just get lost in formulae even after acquainting myself with their meaning. Please help.