diff --git a/shaders/basic.vert b/shaders/basic.vert index 3774ffde1272d28cb47aa541d97805d61eafe113..f7e6ed93a25b21dc54b66347b068d0d139447ee0 100644 --- a/shaders/basic.vert +++ b/shaders/basic.vert @@ -7,11 +7,17 @@ in vec2 in_TexCoord; uniform mat4 projectionMatrix; uniform mat4 modelToWorldToView; -out float shade; + +out vec3 position; +out vec3 normal; +out vec2 tex_coord; void main(void) { - shade = (mat3(modelToWorldToView)*in_Normal).z; // Fake shading + position = in_Position; + normal = in_Normal; + tex_coord = in_TexCoord; + gl_Position=projectionMatrix*modelToWorldToView*vec4(in_Position, 1.0); } diff --git a/shaders/ground.frag b/shaders/ground.frag index 7d92382799e0b4e4370ba9fc4c86ebcb5e8c3c01..cc59c06dbaf47026028eeac2e8239763cc5d8365 100644 --- a/shaders/ground.frag +++ b/shaders/ground.frag @@ -1,11 +1,30 @@ #version 150 -in float shade; +in vec3 position; +in vec3 normal; +in vec2 tex_coord; + +uniform sampler2D grass; +uniform sampler2D dirt; out vec4 out_Color; +const float tex_scale = 4.0; + +const vec3 sun = normalize(vec3(0, 1, 0)); + +float unlerp(float lo, float hi, float t) +{ + return clamp((t - lo) / (hi - lo), 0.0, 1.0); +} + void main(void) { - out_Color=vec4(shade,shade,shade,1.0); + vec3 nnormal = normalize(normal); + float light = max(0.0, dot(nnormal, sun)); + + vec3 albedo = mix(texture(dirt, tex_coord * tex_scale).rgb, texture(grass, tex_coord * tex_scale).rgb, unlerp(-0.2, 0.2, position.y)); + + out_Color = vec4(albedo * light, 1.0); } diff --git a/shaders/surface.frag b/shaders/surface.frag index 18f3dfa2131de80ac0ef82a7bef8ae6bfd9a0e21..69128ec03c561823e8898112b69623d33923c684 100644 --- a/shaders/surface.frag +++ b/shaders/surface.frag @@ -2,14 +2,21 @@ in vec3 world_pos; in vec3 normal; +in vec2 tex_coord; out vec4 out_Color; uniform sampler2D sky; +uniform sampler2D ground; +uniform sampler2D ground_depth; uniform vec3 camera_pos; const float PI = 3.1415926535897f; const float R0 = 0.04; +const float MIN_T = 0; +const float MAX_T = 10.0; +const float DT = 0.1; + vec2 sphere_uv(vec3 direction) { @@ -25,16 +32,55 @@ float fresnel(vec3 normal, vec3 view) { return mix(R0, 1.0, x * x * x * x * x); } +vec2 tex_at(vec3 pos) { + return pos.xz * vec2(0.1f) + vec2(0.5f); +} + +float depth_at(vec3 pos) { + return mix(4.5, -2.0, texture(ground_depth, tex_at(pos)).r); +} + +/** + * Adapted from Inigo Quilez article on raymarching terrain + * https://iquilezles.org/articles/terrainmarching/ + */ +vec3 refraction_ray(vec3 pos, vec3 dir) { + float lh = 0.0f; + float ly = 0.0f; + + for (float t = MIN_T; t < MAX_T; t += DT) { + vec3 cur_pos = pos + t * dir; + + float y_at = depth_at(cur_pos); + if (cur_pos.y < y_at) { + float res_t = t - DT + DT * (lh - ly) / (cur_pos.y - ly - y_at + lh); + + return texture(ground, tex_at(pos + res_t * dir)).rgb; + } + + lh = y_at; + ly = cur_pos.y; + } + + return vec3(1, 0, 1); +} + + void main(void) { vec3 view = normalize(world_pos - camera_pos); vec3 nnormal = normalize(normal); vec3 reflected = reflect(view, nnormal); float R = fresnel(nnormal, view); - vec3 water_color = vec3(0, 0.05, 0.1); + // vec3 water_color = vec3(0, 0.05, 0.1); vec3 sky_color = texture(sky, sphere_uv(reflected)).rgb; + vec3 refracted = refract(view, nnormal, 0.667); + vec3 water_color = refraction_ray(world_pos, refracted); + //out_Color = vec4(1,0,1,1); + // out_Color = vec4(refracted * vec3(0.5) + vec3(0.5), 1.0); out_Color = vec4(mix(water_color, sky_color, R), 1.0); + // out_Color = texture(ground_depth, tex_coord); } diff --git a/shaders/surface.vert b/shaders/surface.vert index 4e09f949d6a6875c23f955805f2ba96ec2c916cb..4bc9c68843659575cd1426c029d328e95cbbca96 100644 --- a/shaders/surface.vert +++ b/shaders/surface.vert @@ -10,12 +10,14 @@ uniform float time; out vec3 world_pos; out vec3 normal; +out vec2 tex_coord; void main(void) { vec3 offset_pos = vec3(in_Position.x, in_Position.y + 0.05 * sin(10.0 * in_Position.x + time), in_Position.z); world_pos = offset_pos; normal = normalize(vec3(-0.05 * cos(10.0 * in_Position.x + time), 1.0, 0.0)); + tex_coord = in_TexCoord; gl_Position = projectionMatrix * modelToWorldToView * vec4(offset_pos, 1.0); } diff --git a/src/main.cpp b/src/main.cpp index 19ef9e98351706d76bfcb8cb9e046beca75ab609..283dc510e988f18ca0b4f45c7c9d467e9d164019 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,6 +26,8 @@ struct Scene { GLuint skybox_tex; FBOstruct *ground_fbo; + GLuint dirt_tex; + GLuint grass_tex; mat4 proj_matrix = perspective(70.0, 1.0, 0.2, 20.0); mat4 orth_matrix = ortho(-5.0, 5.0, -5.0, 5.0, -2.0, 4.5); @@ -64,6 +66,10 @@ struct Scene { printError("bind texture"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); printError("tex parameteri"); + + LoadTGATextureSimple("textures/grass.tga", &grass_tex); + LoadTGATextureSimple("textures/dirt.tga", &dirt_tex); + printError("tex parameteri"); } void do_keyboard_input() { @@ -94,18 +100,27 @@ struct Scene { void draw_ground_fbo() { - useFBO(ground_fbo, nullptr, nullptr); - ground.use(); - GLuint program = ground.program; + useFBO(ground_fbo, nullptr, nullptr); + ground.use(); + GLuint program = ground.program; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"), 1, GL_TRUE, orth_matrix.m); + glUniformMatrix4fv(glGetUniformLocation(program, "modelToWorldToView"), 1, GL_TRUE, top_view_matrix.m); - glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"), 1, GL_TRUE, orth_matrix.m); - glUniformMatrix4fv(glGetUniformLocation(program, "modelToWorldToView"), 1, GL_TRUE, top_view_matrix.m); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, grass_tex); - ground.draw(); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, dirt_tex); - useFBO(nullptr, nullptr, nullptr); + glUniform1i(glGetUniformLocation(program, "grass"), 0); + glUniform1i(glGetUniformLocation(program, "dirt"), 1); + + ground.draw(); + + useFBO(nullptr, nullptr, nullptr); } void draw_surface() @@ -118,25 +133,23 @@ struct Scene { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, skybox_tex); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, ground_fbo->texid); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, ground_fbo->depth); + glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"), 1, GL_TRUE, proj_matrix.m); glUniformMatrix4fv(glGetUniformLocation(program, "modelToWorldToView"), 1, GL_TRUE, view_matrix.m); glUniform1i(glGetUniformLocation(program, "sky"), 0); + glUniform1i(glGetUniformLocation(program, "ground"), 1); + glUniform1i(glGetUniformLocation(program, "ground_depth"), 2); glUniform3f(glGetUniformLocation(program, "camera_pos"), pos.x, pos.y, pos.z); glUniform1f(glGetUniformLocation(program, "time"), time); surface.draw(); } - void draw_ground() - { - ground.use(); - GLuint program = ground.program; - glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"), 1, GL_TRUE, proj_matrix.m); - glUniformMatrix4fv(glGetUniformLocation(program, "modelToWorldToView"), 1, GL_TRUE, view_matrix.m); - - ground.draw(); - } - void update_view_matrix() { vec3 up{0.0, 1.0, 0.0}; mat4 rot = Rx(pitch) * Ry(yaw); @@ -163,7 +176,6 @@ struct Scene { glEnable(GL_CULL_FACE); } - void draw_waterfall() { waterfall.use(); GLuint program = waterfall.program; @@ -179,11 +191,32 @@ struct Scene { waterfall.draw(); waterfall.move_waterfall_balls(); } + void draw_ground() + { + ground.use(); + GLuint program = ground.program; + glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"), 1, GL_TRUE, proj_matrix.m); + glUniformMatrix4fv(glGetUniformLocation(program, "modelToWorldToView"), 1, GL_TRUE, view_matrix.m); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, grass_tex); - void draw() { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, dirt_tex); + + glUniform1i(glGetUniformLocation(program, "grass"), 0); + glUniform1i(glGetUniformLocation(program, "dirt"), 1); + + waterfall.draw(); + } + + + void draw() + { do_keyboard_input(); update_view_matrix(); + draw_ground_fbo(); + draw_skybox(); draw_surface(); draw_ground(); diff --git a/textures/dirt.tga b/textures/dirt.tga new file mode 100644 index 0000000000000000000000000000000000000000..0b87bfe1c249e6b235d4ef3afc6380db70e2f260 Binary files /dev/null and b/textures/dirt.tga differ diff --git a/textures/grass.tga b/textures/grass.tga new file mode 100644 index 0000000000000000000000000000000000000000..841a4ecb5fa5ce8a3aa616491637eb655f5251b6 Binary files /dev/null and b/textures/grass.tga differ