// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkWebGPUCamera.h" #include "vtkMatrix3x3.h" #include "vtkMatrix4x4.h" #include "vtkObjectFactory.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkWebGPURenderer.h" #include // for uint32_t VTK_ABI_NAMESPACE_BEGIN //------------------------------------------------------------------------------ vtkStandardNewMacro(vtkWebGPUCamera); //------------------------------------------------------------------------------ vtkWebGPUCamera::vtkWebGPUCamera() = default; //------------------------------------------------------------------------------ vtkWebGPUCamera::~vtkWebGPUCamera() = default; //------------------------------------------------------------------------------ void vtkWebGPUCamera::Render(vtkRenderer* renderer) { this->CacheSceneTransforms(renderer); } //------------------------------------------------------------------------------ void vtkWebGPUCamera::CacheSceneTransforms(vtkRenderer* renderer) { if (renderer == nullptr && this->LastRenderer == nullptr) { return; } // has the camera changed? if (renderer != this->LastRenderer || this->MTime > this->KeyMatrixTime || renderer->GetMTime() > this->KeyMatrixTime) { vtkMatrix4x4* view = this->GetModelViewTransformMatrix(); SceneTransforms& st = this->CachedSceneTransforms; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { st.ViewMatrix[i][j] = view->GetElement(j, i); } } // since directx, vulkan and metal expect z-coordinate to lie in [0, 1] instead of [-1, 1], // webgpu culls fragments that have a z outside of [0, 1]; even for opengl backend. vtkMatrix4x4* projection = this->GetProjectionTransformMatrix(renderer->GetTiledAspectRatio(), 0, 1); for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { // transpose because, shader will interpret it in a column-major order. st.ProjectionMatrix[i][j] = projection->GetElement(j, i); } } st.ProjectionMatrix[1][1] *= -1; // normal matrix for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { // need to transpose. // but do not transpose, shader will interpret it in a column-major order. this->NormalMatrix->SetElement(i, j, view->GetElement(i, j)); } } this->NormalMatrix->Invert(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { // transpose because, shader will interpret it in a column-major order. st.NormalMatrix[i][j] = this->NormalMatrix->GetElement(i, j); } } projection->Invert(); for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { // transpose because, shader will interpret it in a column-major order. st.InvertedProjectionMatrix[i][j] = projection->GetElement(j, i); } } int lowerLeft[2]; int width, height; renderer->GetTiledSizeAndOrigin(&width, &height, &lowerLeft[0], &lowerLeft[1]); st.Viewport[0] = lowerLeft[0]; st.Viewport[1] = lowerLeft[1]; st.Viewport[2] = width; st.Viewport[3] = height; st.Flags = this->ParallelProjection ? 1u : 0u; this->KeyMatrixTime.Modified(); this->LastRenderer = renderer; } } //------------------------------------------------------------------------------ void vtkWebGPUCamera::UpdateViewport(vtkRenderer* renderer) { int lowerLeft[2]; int width, height; renderer->GetTiledSizeAndOrigin(&width, &height, &lowerLeft[0], &lowerLeft[1]); auto rpassEncoder = reinterpret_cast(renderer)->GetRenderPassEncoder(); // Set viewport frustum rpassEncoder.SetViewport( lowerLeft[0], lowerLeft[1], static_cast(width), static_cast(height), 0.0, 1.0); if (this->UseScissor) { // Set scissor rectangle rpassEncoder.SetScissorRect(static_cast(this->ScissorRect.GetLeft()), static_cast(this->ScissorRect.GetBottom()), static_cast(this->ScissorRect.GetWidth()), static_cast(this->ScissorRect.GetHeight())); this->UseScissor = false; } else { rpassEncoder.SetScissorRect( lowerLeft[0], lowerLeft[1], static_cast(width), static_cast(height)); } } //------------------------------------------------------------------------------ void vtkWebGPUCamera::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } VTK_ABI_NAMESPACE_END