Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/eevee_next/shaders/eevee_camera_lib.glsl')
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_camera_lib.glsl166
1 files changed, 166 insertions, 0 deletions
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_camera_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_camera_lib.glsl
new file mode 100644
index 00000000000..f79e9102d76
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_camera_lib.glsl
@@ -0,0 +1,166 @@
+
+/**
+ * Camera projection / uv functions and utils.
+ **/
+
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+
+/* -------------------------------------------------------------------- */
+/** \name Panoramic Projections
+ *
+ * Adapted from Cycles to match EEVEE's coordinate system.
+ * \{ */
+
+vec2 camera_equirectangular_from_direction(CameraData cam, vec3 dir)
+{
+ float phi = atan(-dir.z, dir.x);
+ float theta = acos(dir.y / length(dir));
+ return (vec2(phi, theta) - cam.equirect_bias) * cam.equirect_scale_inv;
+}
+
+vec3 camera_equirectangular_to_direction(CameraData cam, vec2 uv)
+{
+ uv = uv * cam.equirect_scale + cam.equirect_bias;
+ float phi = uv.x;
+ float theta = uv.y;
+ float sin_theta = sin(theta);
+ return vec3(sin_theta * cos(phi), cos(theta), -sin_theta * sin(phi));
+}
+
+vec2 camera_fisheye_from_direction(CameraData cam, vec3 dir)
+{
+ float r = atan(length(dir.xy), -dir.z) / cam.fisheye_fov;
+ float phi = atan(dir.y, dir.x);
+ vec2 uv = r * vec2(cos(phi), sin(phi)) + 0.5;
+ return (uv - cam.uv_bias) / cam.uv_scale;
+}
+
+vec3 camera_fisheye_to_direction(CameraData cam, vec2 uv)
+{
+ uv = uv * cam.uv_scale + cam.uv_bias;
+ uv = (uv - 0.5) * 2.0;
+ float r = length(uv);
+ if (r > 1.0) {
+ return vec3(0.0);
+ }
+ float phi = safe_acos(uv.x * safe_rcp(r));
+ float theta = r * cam.fisheye_fov * 0.5;
+ if (uv.y < 0.0) {
+ phi = -phi;
+ }
+ return vec3(cos(phi) * sin(theta), sin(phi) * sin(theta), -cos(theta));
+}
+
+vec2 camera_mirror_ball_from_direction(CameraData cam, vec3 dir)
+{
+ dir = normalize(dir);
+ dir.z -= 1.0;
+ dir *= safe_rcp(2.0 * safe_sqrt(-0.5 * dir.z));
+ vec2 uv = 0.5 * dir.xy + 0.5;
+ return (uv - cam.uv_bias) / cam.uv_scale;
+}
+
+vec3 camera_mirror_ball_to_direction(CameraData cam, vec2 uv)
+{
+ uv = uv * cam.uv_scale + cam.uv_bias;
+ vec3 dir;
+ dir.xy = uv * 2.0 - 1.0;
+ if (len_squared(dir.xy) > 1.0) {
+ return vec3(0.0);
+ }
+ dir.z = -safe_sqrt(1.0 - sqr(dir.x) - sqr(dir.y));
+ const vec3 I = vec3(0.0, 0.0, 1.0);
+ return reflect(I, dir);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Regular projections
+ * \{ */
+
+vec3 camera_view_from_uv(mat4 projmat, vec2 uv)
+{
+ return project_point(projmat, vec3(uv * 2.0 - 1.0, 0.0));
+}
+
+vec2 camera_uv_from_view(mat4 projmat, bool is_persp, vec3 vV)
+{
+ vec4 tmp = projmat * vec4(vV, 1.0);
+ if (is_persp && tmp.w <= 0.0) {
+ /* Return invalid coordinates for points behind the camera.
+ * This can happen with panoramic projections. */
+ return vec2(-1.0);
+ }
+ return (tmp.xy / tmp.w) * 0.5 + 0.5;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name General functions handling all projections
+ * \{ */
+
+vec3 camera_view_from_uv(CameraData cam, vec2 uv)
+{
+ vec3 vV;
+ switch (cam.type) {
+ default:
+ case CAMERA_ORTHO:
+ case CAMERA_PERSP:
+ return camera_view_from_uv(cam.wininv, uv);
+ case CAMERA_PANO_EQUIRECT:
+ vV = camera_equirectangular_to_direction(cam, uv);
+ break;
+ case CAMERA_PANO_EQUIDISTANT:
+ /* ATTR_FALLTHROUGH; */
+ case CAMERA_PANO_EQUISOLID:
+ vV = camera_fisheye_to_direction(cam, uv);
+ break;
+ case CAMERA_PANO_MIRROR:
+ vV = camera_mirror_ball_to_direction(cam, uv);
+ break;
+ }
+ return vV;
+}
+
+vec2 camera_uv_from_view(CameraData cam, vec3 vV)
+{
+ switch (cam.type) {
+ default:
+ case CAMERA_ORTHO:
+ return camera_uv_from_view(cam.winmat, false, vV);
+ case CAMERA_PERSP:
+ return camera_uv_from_view(cam.winmat, true, vV);
+ case CAMERA_PANO_EQUIRECT:
+ return camera_equirectangular_from_direction(cam, vV);
+ case CAMERA_PANO_EQUISOLID:
+ /* ATTR_FALLTHROUGH; */
+ case CAMERA_PANO_EQUIDISTANT:
+ return camera_fisheye_from_direction(cam, vV);
+ case CAMERA_PANO_MIRROR:
+ return camera_mirror_ball_from_direction(cam, vV);
+ }
+}
+
+vec2 camera_uv_from_world(CameraData cam, vec3 V)
+{
+ vec3 vV = transform_point(cam.viewmat, V);
+ switch (cam.type) {
+ default:
+ case CAMERA_ORTHO:
+ return camera_uv_from_view(cam.persmat, false, V);
+ case CAMERA_PERSP:
+ return camera_uv_from_view(cam.persmat, true, V);
+ case CAMERA_PANO_EQUIRECT:
+ return camera_equirectangular_from_direction(cam, vV);
+ case CAMERA_PANO_EQUISOLID:
+ /* ATTR_FALLTHROUGH; */
+ case CAMERA_PANO_EQUIDISTANT:
+ return camera_fisheye_from_direction(cam, vV);
+ case CAMERA_PANO_MIRROR:
+ return camera_mirror_ball_from_direction(cam, vV);
+ }
+}
+
+/** \} */