Last active
August 31, 2021 17:34
-
-
Save tschw/da10c43c467ce8afd0c4 to your computer and use it in GitHub Desktop.
Single image, horizontal cross & compact cubemapping
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
vec2 cubeToUV( vec3 v, float texelSize ) { | |
// Horizontal cross layout: | |
// | |
// Y Char: Axis | |
// xzXZ Case: Sign | |
// y | |
vec3 absV = abs( v ); | |
// Intersect unit cube | |
float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) ); | |
v *= scaleToCube; | |
absV *= scaleToCube; | |
// Apply scale to cut the seams | |
// two texels less per square (one texel will do for NEAREST) | |
vec2 zoom = 1.0 - 2.0 * vec2( 4.0, 3.0 ) * texelSize; | |
v.xy *= zoom; | |
// Unwrap | |
// space: -1 ... 1 range for each square | |
// | |
// # dim := ( 4 , 3 ) | |
// #X## | |
// # center := ( 1 , 1 ) | |
vec2 planar = v.xy; | |
float almostATexel = 1.5 * texelSizeY; | |
float almostOne = 1.0 - almostATexel; | |
if ( absV.z >= almostOne ) { | |
if ( v.z > 0.0 ) | |
planar.x = 4.0 - v.x; | |
} else if ( absV.x >= almostOne ) { | |
float signX = sign( v.x ); | |
planar.x = v.z * signX * zoom.x + 2.0 * signX; | |
} else if ( absV.y >= almostOne ) { | |
float signY = sign( v.y ); | |
planar.y = v.z * signY * zoom.y + 2.0 * signY; | |
} | |
// Transform to UV space | |
// scale := 0.5 / dim | |
// translate := ( center + 0.5 ) / dim | |
return vec2( 0.125, 0.16666666 ) * planar + vec2( 0.375, 0.5 ); | |
} |
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
vec2 cubeToUVCompact( vec3 v, float texelSizeY ) { | |
// Compact layout: | |
// | |
// xzXZ Char: Axis | |
// y Y Case: Sign | |
// | |
// Horizontal cross layout in this notation: | |
// | |
// Y To convert to compact layout, | |
// xzXZ simply move the top square to | |
// y the lower right corner. | |
// Number of texels to avoid at the edge of each square | |
vec3 absV = abs( v ); | |
// Intersect unit cube | |
float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) ); | |
absV *= scaleToCube; | |
// Apply scale to avoid seams | |
// one texel less per square (half a texel on each side) | |
v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY ); | |
// Unwrap | |
// space: -1 ... 1 range for each square | |
// | |
// #X## dim := ( 4 , 2 ) | |
// # # center := ( 1 , 1 ) | |
vec2 planar = v.xy; | |
float almostATexel = 1.5 * texelSizeY; | |
float almostOne = 1.0 - almostATexel; | |
if ( absV.z >= almostOne ) { | |
if ( v.z > 0.0 ) | |
planar.x = 4.0 - v.x; | |
} else if ( absV.x >= almostOne ) { | |
float signX = sign( v.x ); | |
planar.x = v.z * signX + 2.0 * signX; | |
} else if ( absV.y >= almostOne ) { | |
float signY = sign( v.y ); | |
planar.x = v.x + 2.0 * signY + 2.0; | |
planar.y = v.z * signY - 2.0; | |
} | |
// Transform to UV space | |
// scale := 0.5 / dim | |
// translate := ( center + 0.5 ) / dim | |
return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 ); | |
} |
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
vec2 cubeToUV( vec3 v, float texelSize ); // see cubeToUV.glsl | |
uniform sampler2D tex; | |
const float TextureSize = 512.; | |
// Suitable input: | |
// http://www.kweepa.com/step/ags/tech/Heartland360.jpg | |
// http://learnopengl.com/img/advanced/cubemaps_skybox.png | |
uniform vec4 camAngles; | |
mat3 rot_zyx( vec3 xyz ); | |
void main() { | |
vec4 camAnglesRad = radians( camAngles ); | |
// Generate "ray": | |
vec3 dir = vec3( | |
gl_TexCoord[0].x - 0.5, | |
0.5 - gl_TexCoord[0].y, // flip y | |
-0.5 / tan( camAnglesRad.w * 0.5 ) ); | |
// Transform: | |
dir *= rot_zyx( camAnglesRad.xyz ); | |
// Sample cube map: | |
vec2 uv = cubeToUV( dir, 1. / TextureSize ); | |
uv.y = 1.0 - uv.y; // flip y | |
gl_FragColor = texture2D( tex, uv ); | |
} | |
mat3 rot_x( float a ) { | |
float s = sin( a ), c = cos( a ); | |
return mat3( | |
1.0 , 0.0 , 0.0 , | |
0.0 , +c , +s , | |
0.0 , -s , +c ); | |
} | |
mat3 rot_y( float a ) { | |
float s = sin( a ), c = cos( a ); | |
return mat3( | |
+c , 0.0 , -s , | |
0.0 , 1.0 , 0.0 , | |
+s , 0.0 , +c ); | |
} | |
mat3 rot_z( float a ) { | |
float s = sin( a ), c = cos( a ); | |
return mat3( | |
+c , +s , 0.0 , | |
-s , +c , 0.0 , | |
0.0 , 0.0 , 1.0 ); | |
} | |
mat3 rot_zyx( vec3 xyz ) { | |
return rot_z( xyz.z ) * rot_x( xyz.x ) * rot_y( xyz.y ); | |
} |
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
void main() { | |
gl_TexCoord[0] = gl_MultiTexCoord0; | |
gl_Position = ftransform(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment