Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2710b17
chore: create task preparation for project
Toumeiii Jan 2, 2026
4920916
chore: add core usefull file
Merilonimbus Jan 20, 2026
ca127a1
feat(env_map): add new env_map
Merilonimbus Jan 20, 2026
555174f
fix(shaders): fix tesselation shaders file extensions.
Merilonimbus Jan 21, 2026
7eb95e8
feat(ocean): add a calm white ocean to every loaded scene (two triangle)
Merilonimbus Jan 22, 2026
4309aba
fix(ocean): use the default helmet scene at execution
Merilonimbus Jan 22, 2026
84bc9e4
feat(texture): add ocean texture
Merilonimbus Jan 23, 2026
eee3b90
feat(ocean): add ocean parameter, more precisely the size of the ocean
Merilonimbus Jan 23, 2026
dc7fd34
chore(TODO): remove obsolete TODOs
Merilonimbus Jan 23, 2026
7f1586a
feat(tese|tesc): add basic tessellation to the ocean
Merilonimbus Jan 24, 2026
0b8b527
feat(tesselation): add lod and tesselation control
Merilonimbus Jan 24, 2026
f8cb595
Merge pull request #10 from Toumeiii/remi
Merilonimbus Jan 24, 2026
87262a9
Merge pull request #11 from Toumeiii/tesselation-shader-program
Merilonimbus Jan 24, 2026
1c92e18
Merge pull request #13 from Toumeiii/tesselation-control
Merilonimbus Jan 27, 2026
24e9fdd
fix(ocean.comp): fix ocean.comp and surrounding code to only call it …
Merilonimbus Jan 27, 2026
4886487
Merge pull request #15 from Toumeiii/14-fix-oceancomp-execution
Merilonimbus Jan 28, 2026
e8190c7
feat: first version waves
Toumeiii Jan 28, 2026
46684ce
feat(shadow): add underwater shadow
Merilonimbus Jan 28, 2026
43fb748
fix: foam visible + mouvemnt wave
Toumeiii Jan 28, 2026
b2c521f
feat: do conversion frequency to spacial (ifft)
Toumeiii Jan 28, 2026
22362c2
feat(shadow): better shadow underwater
Merilonimbus Jan 28, 2026
4ec68fd
Merge branch 'refs/heads/tesselation-evaluation' into underwater-shadow
Merilonimbus Jan 28, 2026
eeb1610
fix(merge): fix merge
Merilonimbus Jan 28, 2026
8c0c71e
fix: ifft working but wrong result
Toumeiii Jan 28, 2026
8375415
Merge pull request #16 from Toumeiii/underwater-shadow
Toumeiii Jan 28, 2026
9215f63
fix: ifft good
Toumeiii Jan 28, 2026
a31bc70
fix: remove useless line
Merilonimbus Jan 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ file(GLOB_RECURSE EXTERNAL_FILES
file(GLOB_RECURSE SHADER_FILES
"shaders/*.frag"
"shaders/*.vert"
"shaders/*.tesc"
"shaders/*.tese"
"shaders/*.geom"
"shaders/*.comp"
"shaders/*.glsl"
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,15 @@ make
If you have a problem, please send a mail to
- alexandre.lamure@epita.fr
- gregoire.angerand@gmail.com

### TODO
in file :
- main.cpp
- ocean_control.tess
- ocean_evaluation.tess
- ocean.frag
- ocean.vert

Look if need for file for tesselation.

separate task to do.
Binary file added data/cubemap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/empty.glb
Binary file not shown.
Binary file added data/ocean_texture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/sphere.glb
Binary file not shown.
67 changes: 67 additions & 0 deletions shaders/ifft_horizontal_waves.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#version 450

layout(local_size_x = 1, local_size_y = 16) in;

layout(binding = 0, rgba16f) uniform image2D waves_real;
layout(binding = 1, rgba16f) uniform image2D waves_img;
layout(binding = 2, rgba16f) uniform image2D tmp_real;
layout(binding = 3, rgba16f) uniform image2D tmp_img;

const float PI = 3.14159265359;

vec2 cmul(vec2 a, vec2 b) {
return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
}

void main(){
int y = int(gl_GlobalInvocationID.y);
int size = imageSize(waves_real).x;
if (y >= size)
return;

vec2 Dx[512];
vec2 Dy[512];
vec2 Dz[512];

for (int x = 0; x < size; x++) {
vec4 r = imageLoad(waves_real, ivec2(x, y));
vec4 i = imageLoad(waves_img, ivec2(x, y));
Dx[x] = vec2(r.r, i.r);
Dy[x] = vec2(r.g, i.g);
Dz[x] = vec2(r.b, i.b);
}

for (int s = 1; s <= int(log2(size)); s++) {
int m = 1 << s;
int m2 = m >> 1;
float theta = 2.0 * PI / float(m);
for (int k = 0; k < size; k += m) {
for (int j = 0; j < m2; j++) {
float ang = theta * float(j);
vec2 w = vec2(cos(ang), sin(ang));
vec2 tx = cmul(w, Dx[k + j + m2]);
vec2 ty = cmul(w, Dy[k + j + m2]);
vec2 tz = cmul(w, Dz[k + j + m2]);
vec2 ux = Dx[k + j];
vec2 uy = Dy[k + j];
vec2 uz = Dz[k + j];
Dx[k + j] = ux + tx;
Dy[k + j] = uy + ty;
Dz[k + j] = uz + tz;
Dx[k + j + m2] = ux - tx;
Dy[k + j + m2] = uy - ty;
Dz[k + j + m2] = uz - tz;
}
}
}

for (int x = 0; x < size; x++) {
Dx[x] /= float(size);
Dy[x] /= float(size);
Dz[x] /= float(size);
vec3 real_row = vec3(Dx[x].x, Dy[x].x, Dz[x].x);
vec3 img_row = vec3(Dx[x].y, Dy[x].y, Dz[x].y);
imageStore(tmp_real, ivec2(x, y), vec4(real_row, 1.0));
imageStore(tmp_img, ivec2(x, y), vec4(img_row, 1.0));
}
}
70 changes: 70 additions & 0 deletions shaders/ifft_vertical_waves.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#version 450

layout(local_size_x = 16, local_size_y = 1) in;

layout(binding = 0, rgba16f) uniform image2D tmp_real;
layout(binding = 1, rgba16f) uniform image2D tmp_img;
layout(binding = 2, rgba16f) uniform image2D result_real;
// layout(binding = 3, rgba16f) uniform image2D result_img;

const float PI = 3.14159265359;

vec2 cmul(vec2 a, vec2 b) {
return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
}

void main(){
int x = int(gl_GlobalInvocationID.x);
int size = imageSize(tmp_real).x;
if (x >= size)
return;

vec2 Dx[512];
vec2 Dy[512];
vec2 Dz[512];

for (int y = 0; y < size; y++) {
vec4 r = imageLoad(tmp_real, ivec2(x, y));
vec4 i = imageLoad(tmp_img, ivec2(x, y));
Dx[y] = vec2(r.r, i.r);
Dy[y] = vec2(r.g, i.g);
Dz[y] = vec2(r.b, i.b);
}

for (int s = 1; s <= int(log2(size)); s++) {
int m = 1 << s;
int m2 = m >> 1;
float theta = 2.0 * PI / float(m);
for (int k = 0; k < size; k += m) {
for (int j = 0; j < m2; j++) {
float ang = theta * float(j);
vec2 w = vec2(cos(ang), sin(ang));
vec2 tx = cmul(w, Dx[k + j + m2]);
vec2 ty = cmul(w, Dy[k + j + m2]);
vec2 tz = cmul(w, Dz[k + j + m2]);
vec2 ux = Dx[k + j];
vec2 uy = Dy[k + j];
vec2 uz = Dz[k + j];
Dx[k + j] = ux + tx;
Dy[k + j] = uy + ty;
Dz[k + j] = uz + tz;
Dx[k + j + m2] = ux - tx;
Dy[k + j + m2] = uy - ty;
Dz[k + j + m2] = uz - tz;
}
}
}

for (int y = 0; y < size; y++) {
Dx[y] /= float(size);
Dy[y] /= float(size);
Dz[y] /= float(size);

// Apply frequency shift: multiply by (-1)^(x+y)
float sign = ((x + y) & 1) == 0 ? 1.0 : -1.0;
vec3 real_col = vec3(Dx[y].x, Dy[y].x, Dz[y].x) * sign;

imageStore(result_real, ivec2(x, y), vec4(real_col, 1.0));
// imageStore(result_img, ivec2(x, y), vec4(img_col, 1.0));
}
}
83 changes: 83 additions & 0 deletions shaders/init_waves.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#version 450

layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;

layout(binding = 0, rgba16f) uniform image2D h0k;

uniform float octave;

const float wind_speed = 100.0;
const vec2 wind_direction = normalize(vec2(1.0, 1.0));
const float amplitude = 0.001;

const float PI = 3.14159265359;
const float G = 9.8; // Gravity (m/s**2)

float phillips_spectrum(vec2 k) {
float k_length = length(k);
if (k_length < 0.0001) return 0.0;

float k_length_2 = k_length * k_length;
float k_length_4 = k_length_2 * k_length_2;

float speed_2 = wind_speed * wind_speed;
float L = speed_2 / G;
float L2 = L * L;

vec2 k_norm = k / k_length;
float k_dot_w = dot(k_norm, wind_direction);
float k_dot_w_2 = k_dot_w * k_dot_w;

if (k_dot_w < 0.0) k_dot_w_2 *= 0.07;

float l = L* 0.001;

// Phillips spectrum
return amplitude * exp(-1.0 / (k_length_2 * L2)) / k_length_4 * k_dot_w_2 * exp(-k_length_2 * l * l);
}

uint hash(uint seed) {
uint state = seed * 747796405u + 2891336453u;
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
return (word >> 22u) ^ word;
}

float random(uint seed) {
seed = hash(seed);
return float(seed) / 4294967296.0;
}

vec2 gaussianRandom(uint seed) {
float u1 = random(seed);
float u2 = random(seed);
float r = sqrt(-2.0 * log(u1));
float t = 2.0 * PI * u2;
return vec2(r * cos(t), r * sin(t));
}

void main() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
uint size = imageSize(h0k).x;

if (uv.x >= size || uv.y >= size)
return;

vec2 x = vec2(uv) - float(size) / 2.0;

float wave_size = 8192.0 / pow(2.0, octave);
vec2 k = 2.0 * PI * x / wave_size;

vec2 rg = gaussianRandom(uint(uv.x * size + uv.y));

// h0 k
float P = phillips_spectrum(k);
vec2 h0 = rg * sqrt(P / 2.0);

// h0 -k
vec2 k_minus = -k;
float P_minus = phillips_spectrum(k_minus);
vec2 h0_minus = rg * sqrt(P_minus / 2.0);

// Store in h0k image
imageStore(h0k, uv, vec4(h0.x, h0.y, h0_minus.x, h0_minus.y));
}
17 changes: 10 additions & 7 deletions shaders/lit.frag
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// #define DEBUG_ENV

layout(location = 0) out vec4 out_color;
layout(location = 1) out vec4 out_position;

layout(location = 0) in vec3 in_normal;
layout(location = 1) in vec2 in_uv;
Expand Down Expand Up @@ -41,21 +42,23 @@ layout(binding = 1) buffer PointLights {
PointLight point_lights[];
};

uniform uint is_main;

void main() {
const vec3 normal_map = unpack_normal_map(texture(in_normal_texture, in_uv).xy);
const vec3 normal = normal_map.x * in_tangent +
normal_map.y * in_bitangent +
normal_map.z * in_normal;
normal_map.y * in_bitangent +
normal_map.z * in_normal;

const vec4 albedo_tex = texture(in_texture, in_uv);
const vec3 base_color = in_color.rgb * albedo_tex.rgb * base_color_factor;
const float alpha = albedo_tex.a;

#ifdef ALPHA_TEST
#ifdef ALPHA_TEST
if(alpha <= alpha_cutoff) {
discard;
}
#endif
#endif

const vec4 metal_rough_tex = texture(in_metal_rough, in_uv);
const float roughness = metal_rough_tex.g * metal_rough_factor.y; // as per glTF spec
Expand All @@ -67,7 +70,7 @@ void main() {

vec3 acc = texture(in_emissive, in_uv).rgb * emissive_factor;
acc += eval_ibl(in_envmap, brdf_lut, normal, view_dir, base_color, metallic, roughness) * frame.ibl_intensity;
{
if (is_main == 0){
float shadow = get_shadow(shadow_map, frame.sun_view_proj, in_position);
if (shadow > 0.) {
acc += shadow * frame.sun_color * eval_brdf(normal, view_dir, frame.sun_dir, base_color, metallic, roughness);
Expand All @@ -91,6 +94,7 @@ void main() {


out_color = vec4(acc, alpha);
out_position = vec4(in_position, 1.);


#ifdef DEBUG_NORMAL
Expand All @@ -108,5 +112,4 @@ void main() {
#ifdef DEBUG_ENV
out_color = vec4(texture(in_envmap, normal).rgb, 1.0);
#endif
}

}
Loading