I'm trying to sync a perspective camera with the view of a directional light to help debug shadow maps

I’m trying to make good a lightview camera that uses the exact direction of the light, and the guessitmated position of the light.
Is there anyway to point the camera at the same direction as the directional light using the light’s xyz coordinates instead of the mouse move coordinates.
Basically it’s going to be used for directional light shadow mapping, and to use the camera part or see the exact point the directional light is pointing at.

void PerspectiveCamera::Update(std::shared_ptr<VulkanEngine> engine)
{
    glm::vec3 front;
    front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
    front.y = sin(glm::radians(Pitch));
    front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
    Front = glm::normalize(front);

    Right = glm::normalize(glm::cross(Front, WorldUp));
    Up = glm::normalize(glm::cross(Right, Front));

    ViewMatrix = glm::lookAt(Position, Position + Front, Up);

    const auto Aspect = engine->SwapChain.GetSwapChainResolution().width / (float)engine->SwapChain.GetSwapChainResolution().height;
    ProjectionMatrix = glm::perspective(glm::radians(Zoom), Aspect, 0.1f, 10000.0f);
}

It seems like it working on the shader side.
Tried updating the light pos based on the light view camera position.

Not sure if I understood what’s the question, but since shadows are already working in your application, you surely have a view matrix for the directional light somewhere in your code => use that very same view matrix for the camera to see the scene from the the light source’s position!

P.S.: Don’t overuse std::shared_ptr!

Your post seems to be missing a description of what is not working? You are only describing what you want to do, but not where you got stuck. I’ll just note:

  • the “view” of the scene of a directional light source is more like what an orthographic camera sees, since all light is parallel to the light’s direction
  • when viewed from the light source’s point of view by definition you do not see shadows cast by that light source

I’m I using it wrong?
I’m most just using it for anything Vulkan related like the engineptr or any other hardware stuff, and mostly assets that are being sent to the gpu.

        WindowPtr::SetUpPtr(1280, 720, "VulkanEngine");
        EnginePtr::SetUpPtr(WindowPtr::GetWindowPtr());
        CameraManagerPtr::SetUpPtr(EnginePtr::GetEnginePtr());
        InputManagerPtr::SetUpPtr(WindowPtr::GetWindowPtr(), CameraManagerPtr::GetCameraManagerPtr());
        TextureManagerPtr::SetUpPtr(EnginePtr::GetEnginePtr());
        MaterialManagerPtr::SetUpPtr(EnginePtr::GetEnginePtr());
        MeshManagerPtr::SetUpPtr(EnginePtr::GetEnginePtr(), InputManagerPtr::GetInputManagerPtr(), MaterialManagerPtr::GetMaterialManagerPtr());
        LightManagerPtr::SetUpPtr(EnginePtr::GetEnginePtr(), CameraManagerPtr::GetCameraManagerPtr());
        GuiManagerPtr::SetUpPtr(EnginePtr::GetEnginePtr());
        ObjManagerPtr::SetUpPtr(EnginePtr::GetEnginePtr());
        AssetManagerPtr::SetUpPtr(EnginePtr::GetEnginePtr());

So basically Materials, Lights, Cameras, Mesh, Modles, Textures are using shared_ptrs.

Also looks like I got the directional light working today.

I don’t think that was the issue with shared_ptr here.

A shared_ptr<T> is not just a way to point to a T. It represents ownership of a T. A piece of code which possesses an instance of shared_ptr<T> is saying that the T being pointed to is owned by this code and will not be destroyed until this code says that it is OK to destroy it.

If a function takes a shared_ptr<T> as a parameter, then this represents the external code granting ownership of a T to the function being called. It should have dominion over whether the object can be destroyed.

So tell me: why does PerspectiveCamera::Update need to take ownership of a VulkanEngine?

The function as shown does not need to own the object. It doesn’t store a pointer/reference to the object somewhere for later use. It doesn’t hand ownership responsibilities to someone else. It doesn’t empty out the shared_ptr parameter, thus potentially causing the object’s lifetime to end. It doesn’t do anything except use that object within the function’s runtime. So the only thing Update needs is for the VulkanEngine it is given to continue to exist until it returns.

The way to spell that out in C++ is with a reference, not a shared_ptr. If a function takes a parameter by reference, then it is imposing a requirement on the caller to provide an object which will continue to exist throughout the execution of that function. The caller may ensure this by itself storing a shared_ptr. Or by itself being given a reference that its caller ensures the lifetime of.

Your code bears the hallmarks of treating shared_ptr like garbage collection. Passing a shared_ptr around should not be the default; if you do so, it should be because you are doing it for the purpose of granting ownership.

1 Like

ahh, that.

That was probably because it was old code I forgot to update.
It should be:

void PerspectiveCamera::Update()
{
    glm::vec3 front;
    front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
    front.y = sin(glm::radians(Pitch));
    front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
    Front = glm::normalize(front);

    Right = glm::normalize(glm::cross(Front, WorldUp));
    Up = glm::normalize(glm::cross(Right, Front));

    ViewMatrix = glm::lookAt(Position, Position + Front, Up);

    const auto Aspect = EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainResolution().width / (float)EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainResolution().height;
    ProjectionMatrix = glm::perspective(glm::radians(Zoom), Aspect, 0.1f, 10000.0f);
}