In Unity, I am attempting to create a custom skybox that use a single render texture to create a flat unmoving skybox (the render texture source will do it's own movement) and reflect off objects as if it were an equiangular cubemap. So far using the unity custom skybox documentation I have been able to create a skybox with a flat image, however I have no idea how to read from the 2D render texture as if it were an equiangular cubemap. I've tried just using same UV coordinates from the skybox rendering pass as the reflection pass, but this results in a very small tiled reflection that looks very poor. I have also tried converting the view direction into cubemap uvs but this has the same result but with the entire image tiled.
What I am basically looking for is one of the following (but I am open to suggestions for better approaches):
1.) A way I can convert a float3 view direction into the uv coordinates needed to read from my image as if it were an equiangular cubemap.
2.) A way to convert the texture2D into an equiangular cubemap in real time every frame.
Here are some images I have taken of my current progress to show what I am looking for:
Custom Skybox:
Background Correct.
Reflection Wrong
HDRI Skybox:
Background Wrong.
Reflection Correct
Sample Image
]4
Test Pattern
*(apologies for the crazy table, turns out markdown doesn't work as advertised on StackExchange.)
Although this may not be helpful here is some of the shader code I am working on for reference:
Shader "Hidden/DontTouchMyStuff_OkayOnlyALittle_BeGentle/HDRP/Skyboxes/HdriFlatSky"
{
HLSLINCLUDE
// Some vertex shader stuff here, don't worry about it.
///////////////////////////////////////////////////////////////////
// FRAGMENT SHADER
///////////////////////////////////////////////////////////////////
float4 GetTextureColor(float4 screenPixelPosition)
{
return tex2D(_MainTex, float2(screenPixelPosition.x / _ScreenParams.x, screenPixelPosition.y / _ScreenParams.y));
}
// Renders reflected cubemap
float4 FragBaking(Varyings input) : SV_Target
{
return GetTextureColor(input.positionCS); // tex2D(_MainTex, float2(4 * ((input.positionCS.x / _ScreenParams.x)), 4 * (1 - (input.positionCS.y / _ScreenParams.y))));
}
// renders sky, works perfectly so far.
float4 FragRender(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float4 color = GetTextureColor(input.positionCS);
color.rgb *= 1;// GetCurrentExposureMultiplier();
return color;
}
// experiment to use direction as uvs. Didn't work, results in reflection like texture is every side of a cubemap.
float4 Frag(Varyings input) : SV_Target
{
// Points towards the camera
float3 viewDirWS = normalize(mul(float3(input.positionCS.xy, 1.0), (float3x3)_PixelCoordToViewDirWS));
// Reverse it to point into the scene
float3 dir = -viewDirWS;
// Rotate direction
float phi = 0.0;
float cosPhi, sinPhi;
sincos(phi, sinPhi, cosPhi);
float3 rotDirX = float3(cosPhi, 0, -sinPhi);
float3 rotDirY = float3(sinPhi, 0, cosPhi);
dir = float3(dot(rotDirX, dir), dir.y, dot(rotDirY, dir));
float3 dirAbs = abs(dir);
float ma = 0;
float2 uv = float2(0, 0);
if (dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y)
{
ma = 0.5 / dirAbs.z;
uv = float2(dir.z < 0.0 ? -dir.x : dir.x, dir.y);
}
else if (dirAbs.y >= dirAbs.x)
{
ma = 0.5 / dirAbs.y;
uv = float2(dir.x, dir.y < 0.0 ? -dir.z : dir.z);
}
else
{
ma = 0.5 / dirAbs.x;
uv = float2(dir.x < 0.0 ? dir.z : -dir.z, dir.y);
}
return float4(tex2D(_MainTex, uv * ma + 0.5).rgb, 1.0);
}
ENDHLSL
SubShader
{
// For cubemap
Pass
{
ZWrite Off
ZTest Always
Blend Off
Cull Off
HLSLPROGRAM
#pragma fragment FragBaking
ENDHLSL
}
// For fullscreen Sky
Pass
{
ZWrite Off
ZTest LEqual
Blend Off
Cull Off
HLSLPROGRAM
#pragma fragment FragRender
ENDHLSL
}
}
}