godot/drivers/gles2/shaders/cubemap_filter.glsl
Rémi Verschelde 57416bfbce GLES2: Define 'lowp' for OpenGL 2.1
Precision qualifiers are only used on OpenGL ES 2.0 and 3.0,
and while OpenGL 3.3 defines them for compatibility (but without
practical effect), they're missing from OpenGL 2.1, so we define
them to prevent compilation errors.

Fixes #24521.
2018-12-21 15:14:58 +01:00

199 lines
4.6 KiB
GLSL

/* clang-format off */
[vertex]
#ifdef USE_GLES_OVER_GL
#define lowp
#define mediump
#define highp
#else
precision mediump float;
precision mediump int;
#endif
attribute highp vec2 vertex; // attrib:0
/* clang-format on */
attribute highp vec2 uv; // attrib:4
varying highp vec2 uv_interp;
void main() {
uv_interp = uv;
gl_Position = vec4(vertex, 0, 1);
}
/* clang-format off */
[fragment]
#extension GL_ARB_shader_texture_lod : enable
#ifndef GL_ARB_shader_texture_lod
#define texture2DLod(img, coord, lod) texture2D(img, coord)
#define textureCubeLod(img, coord, lod) textureCube(img, coord)
#endif
#ifdef USE_GLES_OVER_GL
#define lowp
#define mediump
#define highp
#else
precision mediump float;
precision mediump int;
#endif
#ifdef USE_SOURCE_PANORAMA
uniform sampler2D source_panorama; //texunit:0
#else
uniform samplerCube source_cube; //texunit:0
#endif
/* clang-format on */
uniform int face_id;
uniform float roughness;
varying highp vec2 uv_interp;
uniform sampler2D radical_inverse_vdc_cache; // texunit:1
#define M_PI 3.14159265359
#ifdef LOW_QUALITY
#define SAMPLE_COUNT 64
#else
#define SAMPLE_COUNT 512
#endif
#ifdef USE_SOURCE_PANORAMA
vec4 texturePanorama(sampler2D pano, vec3 normal) {
vec2 st = vec2(
atan(normal.x, normal.z),
acos(normal.y));
if (st.x < 0.0)
st.x += M_PI * 2.0;
st /= vec2(M_PI * 2.0, M_PI);
return texture2DLod(pano, st, 0.0);
}
#endif
vec3 texelCoordToVec(vec2 uv, int faceID) {
mat3 faceUvVectors[6];
// -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
// 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;
}
float radical_inverse_VdC(int i) {
return texture2D(radical_inverse_vdc_cache, vec2(float(i) / 512.0, 0.0)).x;
}
vec2 Hammersley(int i, int N) {
return vec2(float(i) / float(N), radical_inverse_VdC(i));
}
uniform bool z_flip;
void main() {
vec3 color = vec3(0.0);
vec2 uv = (uv_interp * 2.0) - 1.0;
vec3 N = texelCoordToVec(uv, face_id);
vec4 sum = vec4(0.0);
for (int sample_num = 0; sample_num < SAMPLE_COUNT; sample_num++) {
vec2 xi = Hammersley(sample_num, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX(xi, roughness, N);
vec3 V = N;
vec3 L = (2.0 * dot(V, H) * H - V);
float NdotL = clamp(dot(N, L), 0.0, 1.0);
if (NdotL > 0.0) {
#ifdef USE_SOURCE_PANORAMA
vec3 val = texturePanorama(source_panorama, L).rgb;
#else
vec3 val = textureCubeLod(source_cube, L, 0.0).rgb;
#endif
//mix using Linear, to approximate high end back-end
val = mix(pow((val + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), val * (1.0 / 12.92), vec3(lessThan(val, vec3(0.04045))));
sum.rgb += val * NdotL;
sum.a += NdotL;
}
}
sum /= sum.a;
vec3 a = vec3(0.055);
sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308))));
gl_FragColor = vec4(sum.rgb, 1.0);
}