Skip to content

Instantly share code, notes, and snippets.

@Keenuts
Last active April 13, 2019 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Keenuts/969a1d412a00c0d044693add2355dff1 to your computer and use it in GitHub Desktop.
Save Keenuts/969a1d412a00c0d044693add2355dff1 to your computer and use it in GitHub Desktop.
Self shadow on parrallax mapping
#version 420 core
/* frame definition */
uniform mat4 u_matrix_mvp;
uniform mat4 u_matrix_m;
uniform mat4 u_matrix_v;
uniform mat4 u_matrix_p;
uniform vec3 u_camera_position;
/* material definition */
uniform sampler2D tex_albedo;
uniform sampler2D tex_normal;
uniform sampler2D tex_height;
in vertex_data {
mat3 iTBN;
vec3 tan_wpos;
vec3 tan_vpos;
vec2 uv;
} fs_in;
out vec4 result;
#define EPSILON 1e-5f
const float HEIGHT_SCALE = 0.05f;
const float AMBIENT_LIGHT = 0.15f;
const bool CLAMP_UVS = false;
const vec3 LIGHT_POS = vec3(10.f, 300.f, 50.f);
float parrallax_lambert(vec2 uv, vec3 ldir)
{
vec3 normal = texture2D(tex_normal, uv).rgb;
normal = normalize(normal * 2.f - 1.f);
const float step_count = 2.f;
const float step_height = 1.f / step_count;
vec2 uv_step = (-ldir.xy * HEIGHT_SCALE) / step_count;
uv_step.y *= -1.f; /* because of OpenGL norm */
float sample_height = texture2D(tex_height, uv).r;
float ray_height = sample_height + EPSILON;
while (sample_height < ray_height && ray_height < 1.f - EPSILON) {
uv += uv_step;
sample_height = texture2D(tex_height, uv).r;
ray_height += step_height;
}
ldir.y *= -1.f; /* OpenGL norm */
float light = max(0.f, dot(-ldir, normal));
return light;
if (ray_height < 1.f - EPSILON) {
return min(AMBIENT_LIGHT, light);
}
return light;
}
vec2 parrallax_occlusion_mapping(vec2 uv_in, vec3 vdir)
{
const float STEP_COUNT = 10.f;
const float step_height = 1.f / STEP_COUNT;
vec2 uv_step = (vdir.xy * HEIGHT_SCALE) / STEP_COUNT;
uv_step.y *= -1.f; /* OpenGL norm */
vec2 uv = uv_in.xy;
float last_sample = 0.f;
float current_height = 1.f;
float sampled_height = texture2D(tex_height, uv).r;
while (current_height > sampled_height) {
last_sample = sampled_height;
uv += uv_step;
current_height -= step_height;
sampled_height = texture2D(tex_height, uv).r;
}
const float l = last_sample - (current_height + step_height);
const float c = sampled_height - current_height;
const float w = c / (c - l);
return uv * (w) + (uv + uv_step) * (1.f - w);
}
void main()
{
vec3 res;
vec3 tan_vdir = normalize(fs_in.tan_wpos - fs_in.tan_vpos);
vec2 p_uv = parrallax_occlusion_mapping(fs_in.uv, tan_vdir);
if (CLAMP_UVS && (p_uv.x > 1.f || p_uv.y > 1.f || p_uv.x < 0.f || p_uv.y < 0.f))
discard;
vec3 p_wpos = fs_in.tan_wpos;
p_wpos.xy += p_uv;
vec3 tan_lpos = fs_in.iTBN * LIGHT_POS;
vec3 tan_ldir = normalize(p_wpos - tan_lpos);
vec3 albedo = texture2D(tex_albedo, p_uv).rgb;
res.rgb = albedo * parrallax_lambert(p_uv, tan_ldir);
result = vec4(res, 1.f);
}
#version 330 core
/* frame definition */
uniform mat4 u_matrix_mvp;
uniform mat4 u_matrix_m;
uniform mat4 u_matrix_v;
uniform mat4 u_matrix_p;
uniform mat4 u_matrix_normal;
uniform vec3 u_camera_position;
in vec3 vertex;
in vec3 normal;
in vec3 tangent;
in vec2 uv;
out vertex_data {
mat3 iTBN;
vec3 tan_wpos;
vec3 tan_vpos;
vec2 uv;
} vs_out;
void main()
{
vec3 world_position = (u_matrix_m * vec4(vertex, 1.f)).xyz;
vec3 bitangent = normalize(cross(normal, tangent));
vec3 T = normalize(u_matrix_normal * vec4(tangent, 0.f)).xyz;
vec3 B = normalize(u_matrix_normal * vec4(bitangent, 0.f)).xyz;
vec3 N = normalize(u_matrix_normal * vec4(normal, 0.f)).xyz;;
vs_out.iTBN = transpose(mat3(T, B, N));
vs_out.tan_wpos = vs_out.iTBN * world_position;
vs_out.tan_vpos = vs_out.iTBN * u_camera_position;
vs_out.uv = vec2(uv.x, 1.f - uv.y);
gl_Position = u_matrix_mvp * vec4(vertex.xyz, 1.0);;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment