Skip to content

Commit

Permalink
blend perlin noise
Browse files Browse the repository at this point in the history
  • Loading branch information
iamyoukou committed Oct 12, 2020
1 parent 883b151 commit 4499f27
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 40 deletions.
37 changes: 16 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,6 @@ It will have features as following:

- and so on.

# Tricks to reduce cost

There are `three` things to calculate each frame.

1. Height (`Eq. 19`). (`1` dimension, `1` IFFT)

2. Normal (`Eq. 20`). (`2` dimension, `2` IFFT)

3. Horizontal displacement (`Eq. 29`). (`2` dimension, `2` IFFT)

Normally, `5` IFFT are needed `per frame`,
as each equation has different frequency term.
However, given the number of sampling points `N` along each axis,
their complex exponent terms are always the same, i.e.

![Wk](./image/Wk.png)

So it is better to calculate these exponents once before simulation,
and write them into a lookup table.
Then, access that table when performing IFFT in each frame.

# A specially designed IFFT

Using standard FFT codes (e.g. [Cooley–Tukey FFT](https://rosettacode.org/wiki/Fast_Fourier_transform#C.2B.2B)) results in incorrect geometry changes.
Expand Down Expand Up @@ -120,6 +99,14 @@ A GPU-based parallelization is needed.

## Periodic artifact

According to [5], there are two ways to reduce the periodic (or tiling) artifact.

I have tried the one that blends the result with some noise [6, 7] and it actually can reduce the periodic artifact a little bit.

## Shading

I would like to try the BRDF shading method proposed by [8] in the future.

# Reference

[1] Tessendorf, Jerry. "Simulating ocean water." Simulating nature: realistic and interactive techniques. SIGGRAPH 1.2 (2001): 5.
Expand All @@ -129,3 +116,11 @@ A GPU-based parallelization is needed.
[3] An introduction to Realistic Ocean Rendering through FFT - Fabio Suriano - Codemotion Rome 2017 ([slide](https://www.slideshare.net/Codemotion/an-introduction-to-realistic-ocean-rendering-through-fft-fabio-suriano-codemotion-rome-2017), [video](https://www.youtube.com/watch?v=ClW3fo94KR4))

[4] Claes, J. "Real-time water rendering-introducing the projected grid concept." Master's thesis (2004).

[5] Gamper, Thomas. "Ocean Surface Generation and Rendering." (2018).

[6] Rydahl, Björn. "A VFX ocean toolkit with real time preview." (2009).

[7] Ocean Surface Simulation ([slide](http://www-evasion.imag.fr/~Fabrice.Neyret/images/fluids-nuages/waves/Jonathan/articlesCG/NV_OceanCS_Slides.pdf))

[8] Bruneton, Eric, Fabrice Neyret, and Nicolas Holzschuch. "Real‐time realistic ocean lighting using seamless transitions from geometry to BRDF." Computer Graphics Forum. Vol. 29. No. 2. Oxford, UK: Blackwell Publishing Ltd, 2010.
2 changes: 2 additions & 0 deletions header/ocean.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ class cOcean {
GLuint shader;
GLuint tboHeight, tboNormal, tboFresnel;
GLuint tboDispX, tboDispZ;
GLuint tboPerlin;
GLint uniM, uniV, uniP;
GLint uniLightColor, uniLightPos;
GLint uniTexReflect, uniTexRefract, uniTexHeight, uniTexNormal, uniTexSkybox;
GLint uniTexDispX, uniTexDispZ;
GLint uniTexPerlin;
GLint uniTexFresnel;
GLint uniEyePoint;
GLint uniDudvMove;
Expand Down
Binary file added image/perlin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 1 addition & 3 deletions shader/fsOcean.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ void main() {

// farther the ocean, flatter the appearance
float dist2 = max(length(eyePoint - worldPos), 0.01);
dist2 = exp(-0.2 * dist2);
dist2 = exp(-0.1 * dist2);

fragColor = mix(fragColor, refr, 1 - dist2);

// fragColor = vec4(dist2);
}
4 changes: 3 additions & 1 deletion shader/tcsQuad.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ float getTessLevel(float dist0, float dist1) {
if (avgDist <= 8.0) {
return 128.0;
} else if (avgDist <= 16.0) {
return 32.0;
return 64.0;
} else if (avgDist < 32.0) {
return 16.0;
} else {
return 2.0;
}
Expand Down
34 changes: 25 additions & 9 deletions shader/tesQuad.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
layout(quads, equal_spacing, ccw) in;

uniform mat4 M, V, P;
uniform sampler2D texHeight, texNormal, texDispX, texDispZ;
uniform sampler2D texHeight, texDispX, texDispZ;
uniform sampler2D texPerlin;
uniform vec2 dudvMove;
uniform vec3 eyePoint;

in vec3 esInWorldPos[];
Expand Down Expand Up @@ -45,28 +47,42 @@ void main() {
float alpha = max(length(eyePoint - worldPos), 0.01);
alpha = exp(-0.05 * alpha);

// height map
vec3 tempY = texture(texHeight, mod(uv, 1.0)).rgb;
// float scale = 0.3 * alpha;
// float offset = texture(texHeight, mod(uv + dudvMove, 1.0)).r * 2.0 - 1.0;
// worldPos.y = offset * scale;

// perlin noise
float perlinZ = texture(texPerlin, uv.xy / 16.0).r * 2.0 - 1.0;
float perlinX = texture(texPerlin, uv.yx / 16.0).r * 2.0 - 1.0;

vec3 tempY = texture(texHeight, uv).rgb;
float offsetY = tempY.x;
// using tempY.y < 0.01 or == 0 causes strong artifact
float signY = (tempY.y < 0.5) ? -1.0 : 1.0;
float scaleY = 0.3 * (tempY.z * 255.0) * alpha;
worldPos.y += offsetY * signY * scaleY;
float scaleY = 0.5 * (tempY.z * 255.0) * alpha;
float finalY = offsetY * signY * scaleY;
float noiseY = (perlinX + perlinZ) * 0.5 * 10.0 * alpha;
worldPos.y += mix(finalY, noiseY, 0.35);

// x-displacement
vec3 tempX = texture(texDispX, mod(uv, 1.0)).rgb;
float offsetX = tempX.x;
float signX = (tempX.y < 0.5) ? -1.0 : 1.0;
float scaleX = 0.3 * (tempX.z * 255.0) * alpha;
worldPos.x += offsetX * signX * scaleX;
float scaleX = 0.5 * (tempX.z * 255.0) * alpha;
float finalX = offsetX * signX * scaleX;
float noiseX = perlinX * 5.0 * alpha;
worldPos.x += mix(finalX, noiseX, 0.35);

// z-displacement
vec3 tempZ = texture(texDispZ, mod(uv, 1.0)).rgb;
float offsetZ = tempZ.x;
float signZ = (tempZ.y < 0.5) ? -1.0 : 1.0;
float scaleZ = 0.3 * (tempZ.z * 255.0) * alpha;
worldPos.z += offsetZ * signZ * scaleZ;
float scaleZ = 0.5 * (tempZ.z * 255.0) * alpha;
float finalZ = offsetZ * signZ * scaleZ;
float noiseZ = perlinZ * 5.0 * alpha;
worldPos.z += mix(finalZ, noiseZ, 0.35);

gl_Position = P * V * vec4(worldPos, 1.0);

clipSpace = gl_Position;
}
15 changes: 9 additions & 6 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Skybox *skybox;
cOcean *ocean;
ScreenQuad *screenQuad;

bool saveTrigger = false;
bool saveTrigger = true;
int frameNumber = 0;
bool resume = true;
bool saveMap = true;
Expand All @@ -40,6 +40,8 @@ vec3 eyeDirection =
sin(verticalAngle) * sin(horizontalAngle));
vec3 up = vec3(0.f, 1.f, 0.f);

vec3 direction;

mat4 model, view, projection;
bool isRising = false, isDiving = false;

Expand Down Expand Up @@ -125,13 +127,14 @@ int main(int argc, char *argv[]) {

// ocean
glDisable(GL_CULL_FACE);
vec3 tempLightPos = eyePoint + vec3(4.0, 2.0, 0.0);
vec3 tempLightPos =
eyePoint + vec3(direction.x * 4.0, 2.0, direction.z * 4.0);

double start = omp_get_wtime();
// double start = omp_get_wtime();
ocean->render(t, model, view, projection, eyePoint, lightColor,
tempLightPos, resume, frameNumber);
double end = omp_get_wtime();
std::cout << end - start << '\n';
// double end = omp_get_wtime();
// std::cout << end - start << '\n';

// for pre-computed FFT water
// if (t < 200.0) {
Expand Down Expand Up @@ -274,7 +277,7 @@ void computeMatricesFromInputs() {
verticalAngleReflect = 3.1415f - verticalAngle;

// Direction : Spherical coordinates to Cartesian coordinates conversion
vec3 direction =
direction =
vec3(sin(verticalAngle) * cos(horizontalAngle), cos(verticalAngle),
sin(verticalAngle) * sin(horizontalAngle));

Expand Down
3 changes: 3 additions & 0 deletions src/ocean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ void cOcean::initTexture() {
setTexture(tboDispX, 13, "./image/xDisp.png", FIF_PNG);
setTexture(tboDispZ, 14, "./image/zDisp.png", FIF_PNG);
setTexture(tboFresnel, 15, "./image/fresnel.png", FIF_PNG);
setTexture(tboPerlin, 16, "./image/perlin.png", FIF_PNG);
}

void cOcean::initUniform() {
Expand All @@ -174,12 +175,14 @@ void cOcean::initUniform() {
uniTexDispZ = myGetUniformLocation(shader, "texDispZ");
uniTexSkybox = myGetUniformLocation(shader, "texSkybox");
uniTexFresnel = myGetUniformLocation(shader, "texFresnel");
uniTexPerlin = myGetUniformLocation(shader, "texPerlin");

glUniform1i(uniTexHeight, 11);
glUniform1i(uniTexNormal, 12);
glUniform1i(uniTexDispX, 13);
glUniform1i(uniTexDispZ, 14);
glUniform1i(uniTexFresnel, 15);
glUniform1i(uniTexPerlin, 16);
glUniform1i(uniTexReflect, 3);
glUniform1i(uniTexRefract, 2);

Expand Down
Binary file modified withLOD2.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4499f27

Please sign in to comment.