Last active
December 14, 2023 22:38
-
-
Save tesu/196db5421559de3e9555d4f9da9d847d to your computer and use it in GitHub Desktop.
mpv opengl shader for viewing 360 video
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//!HOOK MAINPRESUB | |
//!BIND HOOKED | |
//!DESC un360 | |
#define M_PI 3.1415926535897932384626433832795 | |
const float fov = M_PI/2; // [0 to M_PI] horizontal field of view, range is exclusive | |
const float yaw = M_PI*1; // [any float] polar angle, one full revolution is 2*M_PI | |
const float pitch = M_PI*0; // [any float] vertical tilt, positive is up | |
const float roll = M_PI*0; // [any float] view rotation, positive is clockwise | |
const bool cubemap = false; // either cubemap or equirectangular | |
const float t = tan(fov/2); | |
const float c = cos(pitch); | |
const float s = sin(pitch); | |
float r = target_size.y/target_size.x; | |
const float sR = sin(roll); | |
const float cR = cos(roll); | |
mat3 m = mat3( 2*t*cR, 2*sR*t*r, -t*(cR+sR*r), | |
-2*sR*t*c, 2*cR*t*c*r, t*c*(sR-cR*r)-s, | |
-2*sR*t*s, 2*cR*t*s*r, t*s*(sR-cR*r)+c); | |
vec4 hook() { | |
vec3 p = vec3(HOOKED_pos, 1.0) * m; | |
float theta = atan(p.x, p.z) + yaw; | |
float phi = atan(p.y, length(p.xz)) + M_PI/2; | |
float x, y; | |
if (!cubemap) { | |
// equirectangular | |
x = fract(theta / (2*M_PI)); | |
y = phi / M_PI; | |
} else { | |
// cubemap | |
float offset = mod(theta, M_PI/2)-M_PI/4; | |
float quadrant = mod(floor(theta*2/M_PI), 4); | |
float h = tan(phi)*cos(offset); | |
if (abs(h) > 1) { // side | |
if (quadrant == 3) { // back | |
x = .5/(tan(phi)*cos(offset))+.5; | |
y = .5*tan(offset)+.5; | |
x *= 1.0/3; | |
y *= 1.0/2; | |
x += 1.0/3; | |
y += 1.0/2; | |
} else { | |
x = .5*tan(offset)+.5; | |
y = -.5/(tan(phi)*cos(offset))+.5; | |
x *= 1.0/3; | |
y *= 1.0/2; | |
x += quadrant/3; | |
} | |
} else if (h > 0) { // top | |
x = .5*tan(M_PI-phi)*cos(theta+M_PI/4)+.5; | |
y = -.5*tan(M_PI-phi)*sin(theta+M_PI/4)+.5; | |
x *= 1.0/3; | |
y *= 1.0/2; | |
x += 2.0/3; | |
y += 1.0/2; | |
} else { // bottom | |
x = .5*tan(M_PI-phi)*cos(theta+M_PI/4)+.5; | |
y = .5*tan(M_PI-phi)*sin(theta+M_PI/4)+.5; | |
x *= 1.0/3; | |
y *= 1.0/2; | |
y += 1.0/2; | |
} | |
} | |
return HOOKED_tex(vec2(x,y)); | |
} |
To my would like me use it for this type of video
https://www.youtube.com/watch?v=xCkqpGBMl8M
how to use it?
To use add glsl-shaders-append="~/.config/mpv/un360.glsl"
to ~/.config/mpv/mpv.conf
and tweak parameters for video.
With the recent addition of --glsl-shader-opts
you could make this at least a bit more adjustable at runtime (maybe with an accompanying lua script to allow e.g. mouse dragging the view).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I originally wasn't able to get the implicit edge clamping to work correctly because I didn't know how to change the HEIGHT and WIDTH of the texture, but now I've rewritten it to properly allow for rotating to values of theta greater than 2pi (also negative values), and so that extreme values of phi show some of what's "behind."