-
Notifications
You must be signed in to change notification settings - Fork 2
/
terrain.glsl
371 lines (285 loc) · 11.8 KB
/
terrain.glsl
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
#include "source/render/shaders/layout.glsli"
#include "source/render/shaders/ubo.glsli"
//uniform vec3 patchPosition;
//uniform vec3 patchCubeNormal;
uniform float patchLength;
uniform dmat4 patchToModel;
uniform dmat4 doubleModelView;
#ifdef _VERTEX_
layout(location = VertexLayout_Position) in vec2 vertexPosition_patchspace;
layout(binding = SamplerBinding_Diffuse1) uniform sampler2D heightMap;
out vec3 vPosition;
out vec3 tempColor;
void main() {
vPosition = vec3(vertexPosition_patchspace.xy,
texture(heightMap, vertexPosition_patchspace.xy).r); // height scalar
tempColor.rg = 1.0 - vertexPosition_patchspace.xy;
tempColor.b = 0.0;
}
#endif
#ifdef _TESS_CONTROL_
layout(vertices = 16) out;
//uniform mat4 basis;
//uniform mat4 basisTranspose;
const /*uniform*/ float tessLevelInner = 4.0;
const /*uniform*/ float tessLevelOuter = 8.0;
const mat4 bicubicBasis = mat4( 1.0f/6,-3.0f/6, 3.0f/6,-1.0f/6,
4.0f/6, 0.0f/6,-6.0f/6, 3.0f/6,
1.0f/6, 3.0f/6, 3.0f/6,-3.0f/6,
0.0f/6, 0.0f/6, 0.0f/6, 1.0f/6);
const mat4 bicubicBasisTranspose = transpose(bicubicBasis);
const mat4 bicubicTangentBasis = mat4(-3.0f/6, 6.0f/6,-3.0f/6, 0.0f/6,
0.0f/6,-12.0f/6, 9.0f/6, 0.0f/6,
3.0f/6, 6.0f/6,-9.0f/6, 0.0f/6,
0.0f/6, 0.0f/6, 3.0f/6, 0.0f/6);
const mat4 bicubicTangentBasisTranspose = transpose(bicubicTangentBasis);
in vec3 vPosition[];
in vec3 tempColor[];
out vec3 tcTempColor[];
// coefficient matrices should be "patch out" variables, but crashes AMD driver (at least on my 6900)
// to hack around the issue we use the first three elements of a normal out variable array
//patch out mat4 cx, cy, cz;
out mat4 cMat[]; // cMat[0] == cx, cMat[1] == cy, cMat[2] == cz, the rest are unused
//out vec3 tcPosition[];
void main()
{
tcTempColor[gl_InvocationID] = tempColor[gl_InvocationID];// temp
switch (gl_InvocationID) {
case 0: {
gl_TessLevelInner[0] = tessLevelInner;
gl_TessLevelInner[1] = tessLevelInner;
gl_TessLevelOuter[0] = tessLevelOuter;
gl_TessLevelOuter[1] = tessLevelOuter;
gl_TessLevelOuter[2] = tessLevelOuter;
gl_TessLevelOuter[3] = tessLevelOuter;
// calculate coefficient matrices for cubic surface
mat4 Px = mat4(
vPosition[0].x, vPosition[1].x, vPosition[2].x, vPosition[3].x,
vPosition[4].x, vPosition[5].x, vPosition[6].x, vPosition[7].x,
vPosition[8].x, vPosition[9].x, vPosition[10].x, vPosition[11].x,
vPosition[12].x, vPosition[13].x, vPosition[14].x, vPosition[15].x);
cMat[gl_InvocationID] = bicubicBasis * Px * bicubicBasisTranspose;
break;
}
case 1: {
mat4 Py = mat4(
vPosition[0].y, vPosition[1].y, vPosition[2].y, vPosition[3].y,
vPosition[4].y, vPosition[5].y, vPosition[6].y, vPosition[7].y,
vPosition[8].y, vPosition[9].y, vPosition[10].y, vPosition[11].y,
vPosition[12].y, vPosition[13].y, vPosition[14].y, vPosition[15].y);
cMat[gl_InvocationID] = bicubicBasis * Py * bicubicBasisTranspose;
break;
}
case 2: {
mat4 Pz = mat4(
vPosition[0].z, vPosition[1].z, vPosition[2].z, vPosition[3].z,
vPosition[4].z, vPosition[5].z, vPosition[6].z, vPosition[7].z,
vPosition[8].z, vPosition[9].z, vPosition[10].z, vPosition[11].z,
vPosition[12].z, vPosition[13].z, vPosition[14].z, vPosition[15].z);
cMat[gl_InvocationID] = bicubicBasis * Pz * bicubicBasisTranspose;
break;
}
/*case 3: {
mat4 Px = mat4(
vPosition[0].x, vPosition[1].x, vPosition[2].x, vPosition[3].x,
vPosition[4].x, vPosition[5].x, vPosition[6].x, vPosition[7].x,
vPosition[8].x, vPosition[9].x, vPosition[10].x, vPosition[11].x,
vPosition[12].x, vPosition[13].x, vPosition[14].x, vPosition[15].x);
cMat[gl_InvocationID] = bicubicTangentBasis * Px * bicubicTangentBasisTranspose;
break;
}
case 4: {
mat4 Py = mat4(
vPosition[0].y, vPosition[1].y, vPosition[2].y, vPosition[3].y,
vPosition[4].y, vPosition[5].y, vPosition[6].y, vPosition[7].y,
vPosition[8].y, vPosition[9].y, vPosition[10].y, vPosition[11].y,
vPosition[12].y, vPosition[13].y, vPosition[14].y, vPosition[15].y);
cMat[gl_InvocationID] = bicubicTangentBasis * Py * bicubicTangentBasisTranspose;
break;
}
case 5: {
mat4 Pz = mat4(
vPosition[0].z, vPosition[1].z, vPosition[2].z, vPosition[3].z,
vPosition[4].z, vPosition[5].z, vPosition[6].z, vPosition[7].z,
vPosition[8].z, vPosition[9].z, vPosition[10].z, vPosition[11].z,
vPosition[12].z, vPosition[13].z, vPosition[14].z, vPosition[15].z);
cMat[gl_InvocationID] = bicubicTangentBasis * Pz * bicubicTangentBasisTranspose;
break;
}*/
}
}
#endif
#ifdef _TESS_EVAL_
layout(quads) in;
layout(binding = SamplerBinding_Diffuse1) uniform sampler2D heightMap;
//patch in mat4 cx, cy, cz;
in mat4 cMat[];
//out vec4 tePatchDistance;
out vec4 positionModelspace;
out vec4 positionViewspace;
out vec3 normalModelspace;
out vec3 normalViewspace;
out float linearDepth;
out float slope;
in vec3 tcTempColor[];
out vec3 teTempColor;
void main()
{
float u = gl_TessCoord.x;
float v = gl_TessCoord.y;
vec4 U = vec4(1.0, u, u*u, u*u*u);
vec4 V = vec4(1.0, v, v*v, v*v*v);
vec4 CVx = cMat[0] * V;
vec4 CVy = cMat[1] * V;
vec4 CVz = cMat[2] * V;
double x = dot(CVx, U);
double y = dot(CVy, U);
double z = dot(CVz, U);
double pl = patchLength;
dvec4 pos = patchToModel * dvec4(x * pl, y * pl, 5700000.0, 1.0);
pos.xyz = normalize(pos.xyz) * (5700000.0 /*+ (z * 500000.0)*/);
// dvec4 pos = patchToModel * dvec4(x * pl, y * pl, z * 500.0, 1.0);
positionModelspace = vec4(pos);
//positionModelspace = patchToModel * vec4(x * patchLength, y * patchLength, 5700000.0, 1.0);
//positionModelspace = vec4(normalize(positionModelspace.xyz) * (5700000.0 + (z * 500000.0)), 1.0);
//positionViewspace = vec4(x, y, z, 1.0);
// offset surface by noise texture
//positionModelspace.z += texture(heightMap, vec2(x / 64.0 / 1000.0 * 8, y / 64.0 / 1000.0 * 8)).r * 1000.0f;
// derivatives with respect to u and v
// TODO: does not account for noise displacement of z
vec4 dU = vec4(0.0, 1.0, 2.0*u, 3.0*u*u);
vec4 dV = vec4(0.0, 1.0, 2.0*v, 3.0*v*v);
float nxU = dot(CVx, dU);
float nyU = dot(CVy, dU);
float nzU = dot(CVz, dU);
float nxV = dot(cMat[0] * dV, U);
float nyV = dot(cMat[1] * dV, U);
float nzV = dot(cMat[2] * dV, U);
vec3 nU = vec3(nxU, nyU, nzU) * vec3(patchLength, patchLength, 500000);
vec3 nV = vec3(nxV, nyV, nzV) * vec3(patchLength, patchLength, 500000);
normalModelspace = normalize(cross(nU, nV));
//tePatchDistance = vec4(u, v, 1.0-u, 1.0-v);
/////
/*float u = gl_TessCoord.x;
float v = gl_TessCoord.y;
vec3 x = mix(tcPosition[0], tcPosition[3], u);
vec3 y = mix(tcPosition[12], tcPosition[15], u);
vec4 positionModelspace = vec4(mix(x, y, v), 1.0);*/
/////
// Get the position and normal in viewspace
positionViewspace = vec4(doubleModelView * pos);
normalViewspace = normalize(vec3(normalMatrix * vec4(normalModelspace, 0.0)));
// Get dot product between surface normal and geocentric normal for slope
vec4 geocentricNormal = vec4(0,0,1.0,0); // simplified for now as straight up z-axis, eventually needs to be vector to center of planet
vec3 geocentricNormalViewspace = normalize(vec3(normalMatrix * geocentricNormal));
slope = 1.0 - dot(normalViewspace, geocentricNormalViewspace);
// linear depth for z buffer
linearDepth = (-positionViewspace.z - frustumNear) * inverseFrustumDistance; // map near..far linearly to 0..1
teTempColor = tcTempColor[0]; // temp
//gl_Position = modelViewProjection * positionModelspace;
gl_Position = projection * positionViewspace;
}
#endif
#ifdef _FRAGMENT_
// TODO: these are duplicated
struct Light {
vec4 positionViewspace; // Light position in viewspace
vec3 directionViewspace; // Light spot direction in viewspace
vec3 La; // light color ambient
vec3 Lds; // light color diffuse and specular
float Kc; // attenuation base constant
float Kl; // attenuation linear constant
float Kq; // attenuation quadratic constant
float spotAngleCutoff; // spotlight angle cutoff, dot product comparison (% from 90deg)
float spotEdgeBlendPct; // spotlight edge blend, in % of spot radius
};
struct Material {
vec3 Ma; // Ambient reflectivity
vec3 Md; // Diffuse reflectivity
vec3 Ms; // Specular reflectivity
vec3 Me; // Emissive reflectivity
float shininess; // Specular shininess factor
float metallic; // Metallic determines color of specular highlight
};
Light light;
Material material;
// Globals
vec3 surfaceColor;
// Input Variables
in vec4 positionModelspace;
in vec4 positionViewspace;
in vec3 normalModelspace;
in vec3 normalViewspace;
in float linearDepth;
in float slope;
in vec3 teTempColor;
//in vec4 color;
//in vec2 uv;
//in vec3 tangent;
// Output Variables
layout(location = 0) out vec4 albedoDisplacement;
layout(location = 1) out vec4 eyeSpacePosition;
layout(location = 2) out vec4 normalReflectance;
layout(binding = SamplerBinding_Diffuse2) uniform sampler2D diffuse1;
layout(binding = SamplerBinding_Diffuse3) uniform sampler2D diffuse2;
// Functions
#include "source/render/shaders/blinnPhong.glsl"
// the following two functions are from http://www.gamasutra.com/blogs/AndreyMishkinis/20130716/196339/Advanced_Terrain_Texture_Splatting.php
// this blends without per-vertex alpha mask
/*float3 blend(float4 texture1, float a1, float4 texture2, float a2)
{
return texture1.a + a1 > texture2.a + a2 ? texture1.rgb : texture2.rgb;
}*/
// this blends with a per-vertex alpha mask
/*float3 blend(float4 texture1, float a1, float4 texture2, float a2)
{
float depth = 0.2;
float ma = max(texture1.a + a1, texture2.a + a2) - depth;
float b1 = max(texture1.a + a1 - ma, 0);
float b2 = max(texture2.a + a2 - ma, 0);
return (texture1.rgb * b1 + texture2.rgb * b2) / (b1 + b2);
}*/
void main()
{
// all TEMP for light
vec4 lightPos = vec4( 0.1, 1.0, 150.0, 1.0 );
vec4 lightDir = normalize(vec4( 0.0, 1.5, -1.0, 0.0 ));
light.positionViewspace = modelView * lightPos;
light.directionViewspace = normalize(vec3(modelView * lightDir));
light.La = vec3( 0.10, 0.10, 0.10 );
light.Lds = vec3( 0.6, 0.5, 0.4 );
light.Kc = 1.0;
light.Kl = 0.007;
light.Kq = 0.0002;
light.spotAngleCutoff = 0.96;
light.spotEdgeBlendPct = 0.4;
material.Ma = vec3( 1.0 );
material.Md = vec3( 1.0 );
material.Ms = vec3( 0.0 );
material.Me = vec3( 0.0 );
material.shininess = 0.0;
material.metallic = 0.0;
/////
//vec4 d1 = texture(diffuse1, positionModelspace.xy / 64.0 / 1000.0 * 8.0);
//vec4 d2 = texture(diffuse2, positionModelspace.xy / 64.0 / 1000.0 * 8.0);
//vec4 surfaceColor = mix(d2, d1, smoothstep(0.2, 0.4, slope));
// tri-planar mapping
vec3 uvw = positionModelspace.xyz / 64.0 / 1000.0 * 8.0;
vec3 blending = abs(normalModelspace);
blending = normalize(max(blending, 0.0000001)); // Force weights to sum to 1.0
float b = 1.0 / (blending.x + blending.y + blending.z);
blending *= vec3(b);
vec4 xaxis = texture(diffuse1, uvw.yz);
vec4 yaxis = texture(diffuse1, uvw.xz);
vec4 zaxis = texture(diffuse2, uvw.xy);
// blend the results of the 3 planar projections.
vec4 surfaceColor = xaxis * blending.x + yaxis * blending.y + zaxis * blending.z;
vec3 lightIntensity = blinnPhongDirectionalLight(positionViewspace, normalViewspace, light.directionViewspace, surfaceColor.rgb);
//vec3 lightIntensity = blinnPhongDirectionalLight(positionModelspace, normalModelspace, lightDir.xyz, vec3(1.0)/*surfaceColor.rgb*/);
// write to g-buffer
albedoDisplacement = vec4(lightIntensity, 1.0) * vec4(teTempColor, 1.0);
eyeSpacePosition = vec4(positionViewspace.xyz, 0.0);
normalReflectance = vec4(normalViewspace, 0.0);
gl_FragDepth = linearDepth;
}
#endif