summaryrefslogtreecommitdiff
path: root/glass.frag
blob: 43a319dea7e48d3f97f3cafa0cc664800491f9b6 (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
varying vec3 light_surf;
varying vec3 eye_surf;
varying vec3 tangent_surf;
varying vec4 shadow_coords;
varying vec2 texcoord;
uniform sampler2D normal_sampler;
uniform sampler2D heightmap_sampler;
uniform sampler2DShadow shadow_sampler;
uniform float F0, ni;

float schlick_fresnel(float n_dot_l)
{
	return F0 + (1 - F0) * pow(1 - n_dot_l, 5);
}

/* This returns garbage compared to Schlick. */
float fresnel(float v_dot_h)
{
	float c = v_dot_h; /* cos theta, v . h or l . h */
	float g = sqrt(ni * ni + c * c - 1);
	float gmc = g - c;
	float gpc = g + c;
	float c_gpc_m_1_squared = (c * gpc - 1) * (c * gpc - 1);
	float c_gmc_p_1_squared = (c * gmc + 1) * (c * gmc + 1);

	return gmc*gmc / (2 * gpc*gpc) * (1 + c_gmc_p_1_squared /
					  c_gpc_m_1_squared);
}

void main()
{
	float shadow = shadow2DProj(shadow_sampler, shadow_coords).x;
	const vec4 material_color = vec4(0.7, 0.5, 0.3, 0.0);
	vec3 l = normalize(light_surf);
	vec3 v = normalize(eye_surf);
	vec3 h = normalize(l + v);
	vec3 t = normalize(tangent_surf);
	vec3 n = texture2D(normal_sampler, texcoord).xyz * 2 - 1;
	/* Hack: Reduce the significance of our normal map, which otherwise
	 * looks incongruous with the straight edges.
	 */
	n = normalize(n + vec3(0,0,1));
	float n_dot_l = dot(n, l);
	float n_dot_v = dot(n, v);
	float n_dot_h = dot(n, h);
	float v_dot_h = dot(v, h);
	float s = .7;
	float d = 1 - s;
	float Ii = 0.9; /*intensity of incoming light */
	float Iia = .1 * Ii; /*intensity of ambient light */

	float cos2_alpha = n_dot_h * n_dot_h;
	float tan2_alpha = (1 - cos2_alpha) / cos2_alpha;
	float Rs;
	float D;

	/* Aniso BRDF from Ward's "Measuring and Modeling
	 * Anisotropic Reflection".
	 */

	/* brushed metal */
	float ward_n = .037;
	float ward_m = .063;

	/* Make phi be the angle between the projections of
	 * the tangent and half-angle vectors onto the
	 * surface plane (z=0).  Doing it right would involve
	 * projecting onto the plane defined by n.
	 */
	float cos_phi = dot(normalize(t.xy), normalize(h.xy));

	float cos2_phi_over_m2 = ((cos_phi * cos_phi) / (ward_m * ward_m));
	float sin2_phi_over_n2 = ((1 - cos_phi * cos_phi) / (ward_n * ward_n));
#if 1
	D = exp(-tan2_alpha * (cos2_phi_over_m2 + sin2_phi_over_n2));
#else
	/* Ward's "computationally convenient" equation.
	 * Doesn't work.
	 */
	D = exp(-2 * (cos2_phi_over_m2 +
		      sin2_phi_over_n2) /
		(1 + n_dot_h));
#endif
	Rs = 2 * schlick_fresnel(n_dot_l) * D /
	  sqrt(n_dot_l * n_dot_v) / (ward_m * ward_n);

	Rs *= step(0, n_dot_l);
	Rs *= step(0, n_dot_v);

	float Rd = (1 - F0) * 2;
	/* Ambient occlusion factor -- sample the height map we
	 * used to generate the normal map, and reduce intensity in
	 * the valleys.
	 */
	float heightmap = texture2D(heightmap_sampler, texcoord).x;
	float Ra = Rd * (.8 + .2 * heightmap);

	gl_FragColor = n_dot_l * step(0, n_dot_l) *
	  vec4(material_color.xyz *
	       ((Rd * d + Rs * s) * Ii * shadow),
	       material_color.w) +
	  Iia * Ra * material_color.xyzw;

	/* Debugging scalars -- Map [0,1] to [0.5,1] to catch negative
	 * values.  Multiply by the step function to catch when
	 * the scalar won't come into play because Rs == 0.
	 */
#if 0
	gl_FragColor = vec4(vec3(F0 / 2 + .5), 1);
#endif
/* Normal visualization */
/*
vec3 temp = vec3((normal.x + 1) / 2,
		  (normal.y + 1) / 2,
		  (normal.z + 1) / 2);
gl_FragColor = vec4(temp.xyz, 0);
*/
/*
	gl_FragColor = texture2D(normal_sampler, texcoord);
*/
}