summaryrefslogtreecommitdiff
path: root/advanced_lighting/5.parallax_mapping/shaders/parallax.frag
blob: 6813a3053df310b53195a0863c8ff06348ee9eca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#version 330 core

in VS_OUT {
	vec3		frag_pos;
	vec2		tex_coords;
	vec3		tangent_light_pos;
	vec3		tangent_view_pos;
	vec3		tangent_frag_pos;
} fs_in;

out vec4		frag_color;

uniform sampler2D	diffuse_texture;
uniform sampler2D	normal_map;
uniform sampler2D	depth_map;

uniform float hscale;

vec2 parallax_mapping(vec2 tex_coords, vec3 view_dir)
{
	float	h;
	vec2	p, r;

	h = texture(depth_map, tex_coords).r;
	p = view_dir.xy/view_dir.z*h*hscale;
	r = tex_coords-p;

	return r;
}

vec2 step_parallax_mapping(vec2 tex_coords, vec3 view_dir)
{
	float	minsteps, maxsteps, nsteps, step, dstep, depth;
	vec2	p, cur_tex_coords, dtex_coords;

	minsteps = 8.0;
	maxsteps = 32.0;
	nsteps = mix(maxsteps, minsteps, max(dot(vec3(0.0, 0.0, 1.0), view_dir), 0.0));

	dstep = 1.0/nsteps;
	step = 0.0;

	p = view_dir.xy*hscale;
	dtex_coords = p/nsteps;

	cur_tex_coords = tex_coords;
	depth = texture(depth_map, cur_tex_coords).r;

	while (step < depth) {
		cur_tex_coords -= dtex_coords;
		depth = texture(depth_map, cur_tex_coords).r;
		step += dstep;
	}

	return cur_tex_coords;
}

vec2 parallax_occlusion_mapping(vec2 tex_coords, vec3 view_dir)
{
	float	minsteps, maxsteps, nsteps, step, dstep, depth,
		after_depth, before_depth, weight;
	vec2	p, cur_tex_coords, dtex_coords, prev_tex_coords, result;

	minsteps = 8.0;
	maxsteps = 32.0;
	nsteps = mix(maxsteps, minsteps, max(dot(vec3(0.0, 0.0, 1.0), view_dir), 0.0));

	dstep = 1.0/nsteps;
	step = 0.0;

	p = view_dir.xy*hscale;
	dtex_coords = p/nsteps;

	cur_tex_coords = tex_coords;
	depth = texture(depth_map, cur_tex_coords).r;

	while (step < depth) {
		cur_tex_coords -= dtex_coords;
		depth = texture(depth_map, cur_tex_coords).r;
		step += dstep;
	}

	prev_tex_coords = cur_tex_coords+dtex_coords;

	after_depth = depth-step;
	before_depth = texture(depth_map, prev_tex_coords).r-step+dstep;

	weight = after_depth/(after_depth-before_depth);
	result = prev_tex_coords*weight+cur_tex_coords*(1.0-weight);
	
	return result;
}

void main(void)
{
	vec3	color, light_color,
		normal, view_dir, halfway_dir, light_dir,
		ambient, diffuse, specular, result;
	vec2	tex_coords;
	float	diff, spec;

	view_dir = normalize(fs_in.tangent_view_pos-fs_in.tangent_frag_pos);
	tex_coords = parallax_occlusion_mapping(fs_in.tex_coords, view_dir);
	if ((tex_coords.x > 1.0) || (tex_coords.y > 1.0) || (tex_coords.x < 0.0) || (tex_coords.y < 0.0))
		discard;

	color = vec3(texture(diffuse_texture, tex_coords));
	normal = vec3(texture(normal_map, tex_coords));
	normal = normalize((normal*2.0)-1.0);

	light_color = vec3(1.0);

	ambient = vec3(0.01);

	light_dir = normalize(fs_in.tangent_light_pos-fs_in.tangent_frag_pos);
	diff = max(dot(light_dir, normal), 0.0);
	diffuse = diff*light_color;

	halfway_dir = normalize(light_dir+view_dir); 
	spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0);
	specular = spec*light_color;

	result = (ambient+diffuse+specular)*color;

	frag_color = vec4(result, 1.0);
}