Functions for all possible cases.
Shader https://www.shadertoy.com/view/NttGWr
In this shader:
- Image shader — display Cubemap buffer, or BufA Cubemap in buffer, or BufB Cubemap as panorama (Equirectangular projection). Change
#define USE_METHOD 0
(to 1–2–3) to change displaying image. - BufA — Cubemap emulation in single buffer.
- BufB — panorama or Equirectangular projection.
- CubeA — Shadertoy Cubemap.
Functions:
Panorama functions:
panorama_screen_uv_to_rd
generate panorama rayDir from uv.panorama_rd_to_pan_uv
reverse operation return uv of panorama texture from rayDir.
Cubemap functions:
convert_xyz_to_cube_uv
convert rayDir to cubemap face uv, return index of face and uv.convert_cube_uv_to_xyz
reverse function convert face index and uv to rayDir.
Cubemap emulation functions:
buffer_cubemap_rd
return rd, cube side fragCoord and cube side index and size from buffer fragCoord and buffer size(pixels, iResolution on shadertoy).texture_buffer_cubemap
direct replacement for texture function to read cubemap in buffer same as Cubemap texture.
Other functions:
getCubeMap
- display Cubemap as 6 square textures.
How it can be used:
- Using
panorama_screen_uv_to_rd
->convert_xyz_to_cube_uv
result will be fragCoord for Panorama Equirectangular projection. (look BufB) - Using
getCubeMap
->panorama_rd_to_pan_uv
result is Panorama can be displayed as 6 Cube sides. (look#elif USE_METHOD==2
in Image) - Function
convert_xyz_to_cube_uv
can be used to construct Cubemap from 6 separated textures, input is rayDir and to switch texture 1-6 use returned index of cube side, and cube side uv as texture uv. - In Image shader function
rd_to_screen_uv
to select Screen on Cubemap preview (in my shader red rectangle on Cubemap preview show where camera look) - Cubemap emulation — I made it to debug this shader, cubemap emulation to 2D buffer surface.
I made this Vulkan application with 1024 pixels cube side size (same as on Shadertoy), 3072x2048 buffer size, I use it to debug.
Bugs:
- When
rayDir
used to generate 2DfragCoord
remember to dofloor
of generated fragCoord and add 0.5, because fragCoord generated this way does not point to the center of the pixel. (look line 8 in CubeA in this example shader) - Do not expect
length(normalize(rayDir))
- to be equal 1. Example shader. - Length of
rayDir
can be equal to0.
it will ruinnormalize
. Add+0.0001
to rayDir before normalize or check length of rayDir. - Do not use function texture() to read samplerCube or sampler2D if you need “some values”, texture use mipmap levels (even when mipmaps not generated) to calculate value that lead to +-0.05 error in read value.
Use textureLod or texelFetch.
Example shader with this bug, works in Vulkan and OpenGL.
Thanks for reading.