Hello again!

I’ve also adapted some work from here and here to create parallax-corrected cubemaps, something I’ve been using for a project. This technique still blows my mind. All we’re looking at here are GridSOPs.

The main bulk of the work is here. There’s essentially a simulated cube that we check for intersections with, casting a ray from the camera. We then use that intersection as a position in the cubemap texture.

``````vec4 parallexCorrectedCubemap(samplerCube cubemap,
vec3 camDirection,
vec3 worldPos,
vec3 boxMin,
vec3 boxMax,
vec3 worldSpaceCubemapPos) {

// get ray from camera to pos in world
vec3 ray = normalize(worldPos - camDirection);

// gets min / max intersections with ray and cube
vec3 planeIntersect1 = (boxMax - worldPos) / ray;
vec3 planeIntersect2 = (boxMin - worldPos) / ray;

// pick the furthest intersection
vec3 furthestPlane = max(planeIntersect1, planeIntersect2);

// get the distance to closest intersection on this cube plane
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);

// use this to recover the final intersected world space
vec3 intersectedWorldSpacePos = worldPos + ray * dist;

// now get the ray in cubemap coords
ray = intersectedWorldSpacePos - worldSpaceCubemapPos;

// return cubemap texture value
if (uTextureInstancing) {
return TDInstanceTexture(iVert.instanceTextureIndex, ray);
}
return texture(sColorMap, ray);
}
``````

This part gets the direction from the interpolated world space position to the back corner of the simulated cube.

`vec3 planeIntersect1 = (boxMax - worldPos) / ray;`

Why dividing by `ray` works to find the intersection along the ray is a gap in my knowledge, happy to hear an explanation from someone

The simulated cube is assembled in the vertex shader and is built around the GridSOP we’re instancing…

``````void populatePCStruct() {
// Parallax Correct Cubemap stuff
vec3 instancePos = texelFetch(sInstancePos, ivec2(TDInstanceID(), 0), 0).xyz;

// calculate simulated cube using the
// plane we're rendering to (GridSOP)
vec3 pc = uPlaneCenter;
vec2 ps = uPlaneSize;
pC.boxMinPos = vec3(pc.x + ps.x / 2, pc.y - ps.y / 2, pc.z) + instancePos;
pC.boxMaxPos = vec3(pc.x - ps.x / 2, pc.y + ps.y / 2, pc.z - ps.x) + instancePos;

// calculate center of simulated cube
// and adjust center if were instancing
vec3 cubeCenter = vec3(pc.x, pc.y, -ps.x / 2);
pC.worldSpaceCubemapPos = cubeCenter + instancePos;
}
``````

As always I hope this helps someone!

ParallaxCubemap.toe (10.1 KB)

4 Likes