LCOV - code coverage report
Current view: top level - source/renderer - HWLightingModelRenderer.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 1 100 1.0 %
Date: 2023-01-19 00:18:29 Functions: 2 16 12.5 %

          Line data    Source code
       1             : /* Copyright (C) 2023 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "renderer/HWLightingModelRenderer.h"
      21             : 
      22             : #include "graphics/Color.h"
      23             : #include "graphics/LightEnv.h"
      24             : #include "graphics/Model.h"
      25             : #include "graphics/ModelDef.h"
      26             : #include "graphics/ShaderProgram.h"
      27             : #include "lib/bits.h"
      28             : #include "lib/sysdep/rtl.h"
      29             : #include "maths/Vector3D.h"
      30             : #include "ps/containers/StaticVector.h"
      31             : #include "renderer/Renderer.h"
      32             : #include "renderer/RenderModifiers.h"
      33             : #include "renderer/VertexArray.h"
      34             : 
      35             : namespace
      36             : {
      37             : 
      38             : constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_STRIDE = 32;
      39             : constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET = 16;
      40             : constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET = 0;
      41             : 
      42             : } // anonymous namespace
      43             : 
      44           0 : struct ShaderModelDef : public CModelDefRPrivate
      45             : {
      46             :     /// Indices are the same for all models, so share them
      47             :     VertexIndexArray m_IndexArray;
      48             : 
      49             :     /// Static per-CModelDef vertex array
      50             :     VertexArray m_Array;
      51             : 
      52             :     /// The number of UVs is determined by the model
      53             :     std::vector<VertexArray::Attribute> m_UVs;
      54             : 
      55             :     Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
      56             : 
      57             :     ShaderModelDef(const CModelDefPtr& mdef);
      58             : };
      59             : 
      60             : 
      61           0 : ShaderModelDef::ShaderModelDef(const CModelDefPtr& mdef)
      62             :     : m_IndexArray(false),
      63           0 :     m_Array(Renderer::Backend::IBuffer::Type::VERTEX, false)
      64             : {
      65           0 :     size_t numVertices = mdef->GetNumVertices();
      66             : 
      67           0 :     m_UVs.resize(mdef->GetNumUVsPerVertex());
      68           0 :     for (size_t i = 0; i < mdef->GetNumUVsPerVertex(); ++i)
      69             :     {
      70           0 :         m_UVs[i].format = Renderer::Backend::Format::R32G32_SFLOAT;
      71           0 :         m_Array.AddAttribute(&m_UVs[i]);
      72             :     }
      73             : 
      74           0 :     m_Array.SetNumberOfVertices(numVertices);
      75           0 :     m_Array.Layout();
      76             : 
      77           0 :     for (size_t i = 0; i < mdef->GetNumUVsPerVertex(); ++i)
      78             :     {
      79           0 :         VertexArrayIterator<float[2]> UVit = m_UVs[i].GetIterator<float[2]>();
      80           0 :         ModelRenderer::BuildUV(mdef, UVit, i);
      81             :     }
      82             : 
      83           0 :     m_Array.Upload();
      84           0 :     m_Array.FreeBackingStore();
      85             : 
      86           0 :     m_IndexArray.SetNumberOfVertices(mdef->GetNumFaces()*3);
      87           0 :     m_IndexArray.Layout();
      88           0 :     ModelRenderer::BuildIndices(mdef, m_IndexArray.GetIterator());
      89           0 :     m_IndexArray.Upload();
      90           0 :     m_IndexArray.FreeBackingStore();
      91             : 
      92           0 :     const uint32_t stride = m_Array.GetStride();
      93             :     PS::StaticVector<Renderer::Backend::SVertexAttributeFormat, 4> attributes{
      94             :         {Renderer::Backend::VertexAttributeStream::UV0,
      95           0 :             m_UVs[0].format, m_UVs[0].offset, stride,
      96             :             Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
      97             :         {Renderer::Backend::VertexAttributeStream::POSITION,
      98             :             Renderer::Backend::Format::R32G32B32_SFLOAT,
      99             :             MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET, MODEL_VERTEX_ATTRIBUTE_STRIDE,
     100             :             Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1},
     101             :         {Renderer::Backend::VertexAttributeStream::NORMAL,
     102             :             Renderer::Backend::Format::R32G32B32_SFLOAT,
     103             :             MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET, MODEL_VERTEX_ATTRIBUTE_STRIDE,
     104             :             Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1}
     105           0 :     };
     106             : 
     107           0 :     if (mdef->GetNumUVsPerVertex() >= 2)
     108             :     {
     109           0 :         attributes.push_back({
     110             :             Renderer::Backend::VertexAttributeStream::UV1,
     111           0 :             m_UVs[1].format, m_UVs[1].offset, stride,
     112             :             Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0});
     113             :     }
     114             : 
     115           0 :     m_VertexInputLayout = g_Renderer.GetVertexInputLayout({attributes.begin(), attributes.end()});
     116           0 : }
     117             : 
     118             : 
     119           0 : struct ShaderModel : public CModelRData
     120             : {
     121             :     /// Dynamic per-CModel vertex array
     122             :     VertexArray m_Array;
     123             : 
     124             :     /// Position and normals/lighting are recalculated on CPU every frame
     125             :     VertexArray::Attribute m_Position;
     126             :     VertexArray::Attribute m_Normal;
     127             : 
     128           0 :     ShaderModel(const void* key)
     129           0 :         : CModelRData(key),
     130           0 :         m_Array(Renderer::Backend::IBuffer::Type::VERTEX, true)
     131           0 :     {}
     132             : };
     133             : 
     134             : 
     135             : struct ShaderModelVertexRenderer::ShaderModelRendererInternals
     136             : {
     137             :     /// Previously prepared modeldef
     138             :     ShaderModelDef* shadermodeldef;
     139             : };
     140             : 
     141             : 
     142             : // Construction and Destruction
     143           0 : ShaderModelVertexRenderer::ShaderModelVertexRenderer()
     144             : {
     145           0 :     m = new ShaderModelRendererInternals;
     146           0 :     m->shadermodeldef = nullptr;
     147           0 : }
     148             : 
     149           0 : ShaderModelVertexRenderer::~ShaderModelVertexRenderer()
     150             : {
     151           0 :     delete m;
     152           0 : }
     153             : 
     154             : 
     155             : // Build model data (and modeldef data if necessary)
     156           0 : CModelRData* ShaderModelVertexRenderer::CreateModelData(const void* key, CModel* model)
     157             : {
     158           0 :     CModelDefPtr mdef = model->GetModelDef();
     159           0 :     ShaderModelDef* shadermodeldef = (ShaderModelDef*)mdef->GetRenderData(m);
     160             : 
     161           0 :     if (!shadermodeldef)
     162             :     {
     163           0 :         shadermodeldef = new ShaderModelDef(mdef);
     164           0 :         mdef->SetRenderData(m, shadermodeldef);
     165             :     }
     166             : 
     167             :     // Build the per-model data
     168           0 :     ShaderModel* shadermodel = new ShaderModel(key);
     169             : 
     170             :     // Positions and normals must be 16-byte aligned for SSE writes.
     171             : 
     172           0 :     shadermodel->m_Position.format = Renderer::Backend::Format::R32G32B32A32_SFLOAT;
     173           0 :     shadermodel->m_Array.AddAttribute(&shadermodel->m_Position);
     174             : 
     175           0 :     shadermodel->m_Normal.format = Renderer::Backend::Format::R32G32B32A32_SFLOAT;
     176           0 :     shadermodel->m_Array.AddAttribute(&shadermodel->m_Normal);
     177             : 
     178           0 :     shadermodel->m_Array.SetNumberOfVertices(mdef->GetNumVertices());
     179           0 :     shadermodel->m_Array.Layout();
     180             : 
     181             :     // Verify alignment
     182           0 :     ENSURE(shadermodel->m_Position.offset % 16 == 0);
     183           0 :     ENSURE(shadermodel->m_Normal.offset % 16 == 0);
     184           0 :     ENSURE(shadermodel->m_Array.GetStride() % 16 == 0);
     185             : 
     186             :     // We assume that the vertex input layout is the same for all models with the
     187             :     // same ShaderModelDef.
     188             :     // TODO: we need a more strict way to guarantee that.
     189           0 :     ENSURE(shadermodel->m_Array.GetStride() == MODEL_VERTEX_ATTRIBUTE_STRIDE);
     190           0 :     ENSURE(shadermodel->m_Position.offset == MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET);
     191           0 :     ENSURE(shadermodel->m_Normal.offset == MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET);
     192             : 
     193           0 :     return shadermodel;
     194             : }
     195             : 
     196             : 
     197             : // Fill in and upload dynamic vertex array
     198           0 : void ShaderModelVertexRenderer::UpdateModelData(CModel* model, CModelRData* data, int updateflags)
     199             : {
     200           0 :     ShaderModel* shadermodel = static_cast<ShaderModel*>(data);
     201             : 
     202           0 :     if (updateflags & RENDERDATA_UPDATE_VERTICES)
     203             :     {
     204             :         // build vertices
     205           0 :         VertexArrayIterator<CVector3D> Position = shadermodel->m_Position.GetIterator<CVector3D>();
     206           0 :         VertexArrayIterator<CVector3D> Normal = shadermodel->m_Normal.GetIterator<CVector3D>();
     207             : 
     208           0 :         ModelRenderer::BuildPositionAndNormals(model, Position, Normal);
     209             : 
     210             :         // upload everything to vertex buffer
     211           0 :         shadermodel->m_Array.Upload();
     212             :     }
     213             : 
     214           0 :     shadermodel->m_Array.PrepareForRendering();
     215           0 : }
     216             : 
     217           0 : void ShaderModelVertexRenderer::UploadModelData(
     218             :     Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
     219             :     CModel* model, CModelRData* data)
     220             : {
     221           0 :     ShaderModelDef* shaderModelDef = static_cast<ShaderModelDef*>(model->GetModelDef()->GetRenderData(m));
     222           0 :     ENSURE(shaderModelDef);
     223             : 
     224           0 :     shaderModelDef->m_Array.UploadIfNeeded(deviceCommandContext);
     225           0 :     shaderModelDef->m_IndexArray.UploadIfNeeded(deviceCommandContext);
     226             : 
     227           0 :     ShaderModel* shaderModel = static_cast<ShaderModel*>(data);
     228             : 
     229           0 :     shaderModel->m_Array.UploadIfNeeded(deviceCommandContext);
     230           0 : }
     231             : 
     232             : // Prepare UV coordinates for this modeldef
     233           0 : void ShaderModelVertexRenderer::PrepareModelDef(
     234             :     Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
     235             :     const CModelDef& def)
     236             : {
     237           0 :     m->shadermodeldef = (ShaderModelDef*)def.GetRenderData(m);
     238             : 
     239           0 :     ENSURE(m->shadermodeldef);
     240             : 
     241           0 :     deviceCommandContext->SetVertexInputLayout(m->shadermodeldef->m_VertexInputLayout);
     242             : 
     243           0 :     const uint32_t stride = m->shadermodeldef->m_Array.GetStride();
     244           0 :     const uint32_t firstVertexOffset = m->shadermodeldef->m_Array.GetOffset() * stride;
     245             : 
     246           0 :     deviceCommandContext->SetVertexBuffer(
     247           0 :         0, m->shadermodeldef->m_Array.GetBuffer(), firstVertexOffset);
     248           0 : }
     249             : 
     250             : // Render one model
     251           0 : void ShaderModelVertexRenderer::RenderModel(
     252             :     Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
     253             :     Renderer::Backend::IShaderProgram* UNUSED(shader), CModel* model, CModelRData* data)
     254             : {
     255           0 :     const CModelDefPtr& mdldef = model->GetModelDef();
     256           0 :     ShaderModel* shadermodel = static_cast<ShaderModel*>(data);
     257             : 
     258           0 :     const uint32_t stride = shadermodel->m_Array.GetStride();
     259           0 :     const uint32_t firstVertexOffset = shadermodel->m_Array.GetOffset() * stride;
     260             : 
     261           0 :     deviceCommandContext->SetVertexBuffer(
     262           0 :         1, shadermodel->m_Array.GetBuffer(), firstVertexOffset);
     263           0 :     deviceCommandContext->SetIndexBuffer(m->shadermodeldef->m_IndexArray.GetBuffer());
     264             : 
     265             :     // Render the lot.
     266           0 :     const size_t numberOfFaces = mdldef->GetNumFaces();
     267             : 
     268           0 :     deviceCommandContext->DrawIndexedInRange(
     269           0 :         m->shadermodeldef->m_IndexArray.GetOffset(), numberOfFaces * 3, 0, mdldef->GetNumVertices() - 1);
     270             : 
     271             :     // Bump stats.
     272           0 :     g_Renderer.m_Stats.m_DrawCalls++;
     273           0 :     g_Renderer.m_Stats.m_ModelTris += numberOfFaces;
     274           3 : }
     275             : 

Generated by: LCOV version 1.13