Ok so I decided to take the advice of Ohforf sake and not try and second guess the behaviour and tricks of the DX implementation using assumptions due to the trouble it could bring.

I decided that I knew very well view * projection to clip space /w to NDC is what I wanted and I had all the wits to get there somehow:

Vector4f lsPos = OpenGLHelper.columnVectorMultiplyMatrixVector(cameraController.getActiveCameraView(), new Vector4f(lightPos.x, lightPos.y, lightPos.z, 1.0f)); Vector4f lsPos2 = new Vector4f(lsPos); lsPos.z -= lightRadius; if (lsPos.z*-1 > 0.5/*NEAR_DEPTH*/) { //Convert lPos to NDC lsPos = OpenGLHelper.columnVectorMultiplyMatrixVector(cameraController.getCoreCameraProjection(), new Vector4f(lsPos.x, lsPos.y, lsPos.z, lsPos.w)); lsPos.z = lsPos.z / lsPos.w; lsPos2.z = lsPos2.z + lightRadius; lsPos2 = OpenGLHelper.columnVectorMultiplyMatrixVector(cameraController.getCoreCameraProjection(), new Vector4f(lsPos2.x, lsPos2.y, lsPos2.z, lsPos2.w)); lsPos2.z = lsPos2.z / lsPos2.w; Vector2f zBounds = new Vector2f(); zBounds.y = lsPos.z; zBounds.x = lsPos2.z; if (zBounds.y > 1) { zBounds.y = 1; } else if (zBounds.y < 0) { zBounds.y = 0; } if (zBounds.x > 1) { zBounds.x = -1; } else if (zBounds.x < 0) { zBounds.x = 0; }

It is three vector matrix calculations per light but Humus's genius clearly trumps mine for now. Here is the final product with 0.1 added to the pixels within the calc:

Sure there are clip space lights but I still find this enchanting

If anyone can spot any optimisations to cut down on matrix calcs and can explain Humus's black magic please enlighten me.

Here is something I made less crappy earlier:

public static Vector4f columnVectorMultiplyMatrixVector(Matrix4f matrix, Vector4f vector) { Vector4f returnVec = new Vector4f(); returnVec.setX(matrix.m00 * vector.getX() + matrix.m10 * vector.getY() + matrix.m20 * vector.getZ() + matrix.m30 * vector.getW()); returnVec.setY(matrix.m01 * vector.getX() + matrix.m11 * vector.getY() + matrix.m21 * vector.getZ() + matrix.m31 * vector.getW()); returnVec.setZ(matrix.m02 * vector.getX() + matrix.m12 * vector.getY() + matrix.m22 * vector.getZ() + matrix.m32 * vector.getW()); returnVec.setW(matrix.m03 * vector.getX() + matrix.m13 * vector.getY() + matrix.m23 * vector.getZ() + matrix.m33 * vector.getW()); return returnVec; }

Maybe you haven't read any of the new posts but I am pleased to be roughly 95% there in terms of matching the original matter, thank you very much for your input!