2016-10-21 12:27:13 +02:00
|
|
|
[vertex]
|
|
|
|
|
|
|
|
|
|
|
|
layout(location=0) in highp vec2 vertex;
|
|
|
|
|
2016-10-30 01:48:09 +02:00
|
|
|
layout(location=4) in highp vec2 uv;
|
2016-10-21 12:27:13 +02:00
|
|
|
|
|
|
|
out highp vec2 uv_interp;
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
|
|
|
uv_interp=uv;
|
|
|
|
gl_Position=vec4(vertex,0,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
[fragment]
|
|
|
|
|
|
|
|
|
2016-10-27 16:50:26 +02:00
|
|
|
precision highp float;
|
|
|
|
precision highp int;
|
|
|
|
|
|
|
|
|
|
|
|
uniform samplerCube source_cube; //texunit:0
|
2016-10-21 12:27:13 +02:00
|
|
|
uniform int face_id;
|
|
|
|
uniform float roughness;
|
|
|
|
in highp vec2 uv_interp;
|
|
|
|
|
|
|
|
|
2016-10-27 16:50:26 +02:00
|
|
|
layout(location = 0) out vec4 frag_color;
|
|
|
|
|
|
|
|
|
|
|
|
#define M_PI 3.14159265359
|
2016-10-21 12:27:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
vec3 texelCoordToVec(vec2 uv, int faceID)
|
|
|
|
{
|
|
|
|
mat3 faceUvVectors[6];
|
2016-10-27 16:50:26 +02:00
|
|
|
/*
|
2016-10-21 12:27:13 +02:00
|
|
|
// -x
|
|
|
|
faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
|
|
|
|
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
|
|
|
faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
|
|
|
|
|
|
|
|
// +x
|
|
|
|
faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
|
|
|
|
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
|
|
|
faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
|
|
|
|
|
|
|
|
// -y
|
|
|
|
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
|
|
|
faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
|
|
|
|
faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
|
|
|
|
|
|
|
|
// +y
|
|
|
|
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
|
|
|
faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
|
|
|
|
faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
|
|
|
|
|
|
|
|
// -z
|
|
|
|
faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
|
|
|
|
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
|
|
|
faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
|
|
|
|
|
|
|
|
// +z
|
|
|
|
faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
|
|
|
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
|
|
|
faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
|
2016-10-27 16:50:26 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
// -x
|
|
|
|
faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z
|
|
|
|
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
|
|
|
faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face
|
|
|
|
|
|
|
|
// +x
|
|
|
|
faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z
|
|
|
|
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
|
|
|
faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face
|
|
|
|
|
|
|
|
// -y
|
|
|
|
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
|
|
|
faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z
|
|
|
|
faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face
|
|
|
|
|
|
|
|
// +y
|
|
|
|
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
|
|
|
faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z
|
|
|
|
faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face
|
|
|
|
|
|
|
|
// -z
|
|
|
|
faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
|
|
|
|
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
|
|
|
faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face
|
|
|
|
|
|
|
|
// +z
|
|
|
|
faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
|
|
|
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
|
|
|
faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face
|
2016-10-21 12:27:13 +02:00
|
|
|
|
|
|
|
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
|
|
|
|
vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
|
|
|
|
return normalize(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
|
|
|
|
{
|
|
|
|
float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
|
|
|
|
|
|
|
|
// Compute distribution direction
|
|
|
|
float Phi = 2.0 * M_PI * Xi.x;
|
|
|
|
float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
|
|
|
float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
|
|
|
|
|
|
|
|
// Convert to spherical direction
|
|
|
|
vec3 H;
|
|
|
|
H.x = SinTheta * cos(Phi);
|
|
|
|
H.y = SinTheta * sin(Phi);
|
|
|
|
H.z = CosTheta;
|
|
|
|
|
|
|
|
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
|
|
vec3 TangentX = normalize(cross(UpVector, N));
|
|
|
|
vec3 TangentY = cross(N, TangentX);
|
|
|
|
|
|
|
|
// Tangent to world space
|
|
|
|
return TangentX * H.x + TangentY * H.y + N * H.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
|
|
|
|
float GGX(float NdotV, float a)
|
|
|
|
{
|
|
|
|
float k = a / 2.0;
|
|
|
|
return NdotV / (NdotV * (1.0 - k) + k);
|
|
|
|
}
|
|
|
|
|
|
|
|
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
|
|
|
|
float G_Smith(float a, float nDotV, float nDotL)
|
|
|
|
{
|
|
|
|
return GGX(nDotL, a * a) * GGX(nDotV, a * a);
|
|
|
|
}
|
|
|
|
|
|
|
|
float radicalInverse_VdC(uint bits) {
|
|
|
|
bits = (bits << 16u) | (bits >> 16u);
|
|
|
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
|
|
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
|
|
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
|
|
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
|
|
|
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2 Hammersley(uint i, uint N) {
|
|
|
|
return vec2(float(i)/float(N), radicalInverse_VdC(i));
|
|
|
|
}
|
|
|
|
|
2016-11-19 17:23:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef LOW_QUALITY
|
|
|
|
|
|
|
|
#define SAMPLE_COUNT 64u
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define SAMPLE_COUNT 512u
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
uniform bool z_flip;
|
2016-10-21 12:27:13 +02:00
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
2016-11-19 17:23:37 +01:00
|
|
|
#ifdef USE_DUAL_PARABOLOID
|
|
|
|
|
|
|
|
vec3 N = vec3( uv_interp * 2.0 - 1.0, 0.0 );
|
|
|
|
N.z = 0.5 - 0.5*((N.x * N.x) + (N.y * N.y));
|
|
|
|
N = normalize(N);
|
|
|
|
|
|
|
|
if (!z_flip) {
|
|
|
|
N.y=-N.y; //y is flipped to improve blending between both sides
|
|
|
|
} else {
|
|
|
|
N.z=-N.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
2016-10-21 12:27:13 +02:00
|
|
|
vec2 uv = (uv_interp * 2.0) - 1.0;
|
|
|
|
vec3 N = texelCoordToVec(uv, face_id);
|
2016-11-19 17:23:37 +01:00
|
|
|
#endif
|
2016-10-21 12:27:13 +02:00
|
|
|
//vec4 color = color_interp;
|
2016-11-19 17:23:37 +01:00
|
|
|
|
|
|
|
#ifdef USE_DIRECT_WRITE
|
|
|
|
|
|
|
|
frag_color=vec4(texture(N,source_cube).rgb,1.0);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2016-10-21 12:27:13 +02:00
|
|
|
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
|
|
|
2016-10-27 16:50:26 +02:00
|
|
|
for(uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) {
|
2016-10-21 12:27:13 +02:00
|
|
|
vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT);
|
|
|
|
|
|
|
|
vec3 H = ImportanceSampleGGX( xi, roughness, N );
|
|
|
|
vec3 V = N;
|
|
|
|
vec3 L = normalize(2.0 * dot( V, H ) * H - V);
|
|
|
|
|
2016-10-27 16:50:26 +02:00
|
|
|
float ndotl = clamp(dot(N, L),0.0,1.0);
|
2016-10-21 12:27:13 +02:00
|
|
|
|
2016-10-27 16:50:26 +02:00
|
|
|
if (ndotl>0.0) {
|
|
|
|
sum.rgb += textureLod(source_cube, H, 0.0).rgb *ndotl;
|
|
|
|
sum.a += ndotl;
|
|
|
|
}
|
2016-10-21 12:27:13 +02:00
|
|
|
}
|
2016-10-27 16:50:26 +02:00
|
|
|
sum /= sum.a;
|
2016-10-21 12:27:13 +02:00
|
|
|
|
|
|
|
frag_color = vec4(sum.rgb, 1.0);
|
2016-11-19 17:23:37 +01:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2016-10-21 12:27:13 +02:00
|
|
|
}
|
|
|
|
|