private void positionShadowMapCamera() { // We begin by setting our light coordinates at the player coordinates, ignoring the player's altitude Vector3f mainLightPosition = new Vector3f(activeCamera.getPosition().x, 0.0f, activeCamera.getPosition().z); // world-space coordinates // The shadow projected onto the ground must move in in light-space texel-steps, to avoid causing flickering. // That's why we first convert it to the previous frame's light-space coordinates and then back to world-space. shadowMapCamera.getViewProjectionMatrix().transformPoint(mainLightPosition); // to light-space mainLightPosition.set(TeraMath.fastFloor(mainLightPosition.x / texelSize) * texelSize, 0.0f, TeraMath.fastFloor(mainLightPosition.z / texelSize) * texelSize); shadowMapCamera.getInverseViewProjectionMatrix().transformPoint(mainLightPosition); // back to world-space // This is what causes the shadow map to change infrequently, to prevent flickering. // Notice that this is different from what is done above, which is about spatial steps // and is related to the player's position and texels. Vector3f quantizedMainLightDirection = getQuantizedMainLightDirection(STEP_SIZE); // The shadow map camera is placed away from the player, in the direction of the main light. Vector3f offsetFromPlayer = new Vector3f(quantizedMainLightDirection); offsetFromPlayer.scale(256.0f + 64.0f); // these hardcoded numbers are another mystery. mainLightPosition.add(offsetFromPlayer); shadowMapCamera.getPosition().set(mainLightPosition); // Finally, we adjust the shadow map camera to look toward the player Vector3f fromLightToPlayerDirection = new Vector3f(quantizedMainLightDirection); fromLightToPlayerDirection.scale(-1.0f); shadowMapCamera.getViewingDirection().set(fromLightToPlayerDirection); shadowMapCamera.update(worldRenderer.getSecondsSinceLastFrame()); }
activeCameraToLightSpace.sub(cameraPosition, lightCamera.getPosition()); mainLightInViewSpace = backdropProvider.getSunDirection(true); activeCamera.getViewMatrix().transformPoint(mainLightInViewSpace);
activeCamera.getViewMatrix().transformPoint(lightPositionInViewSpace); lightGeometryMaterial.setFloat3("lightViewPos", lightPositionInViewSpace.x, lightPositionInViewSpace.y, lightPositionInViewSpace.z, true);