Files
funnygame/game/client/worldrender.cpp
2026-02-24 21:38:34 +02:00

352 lines
9.7 KiB
C++

#include "worldrender.h"
#include "tier1/utlstring.h"
#include "engine.h"
#include "cglm/cglm.h"
#include "cglm/quat.h"
#include "cglm/mat4.h"
struct ViewBuffer_t
{
mat4 m_matCameraProjection;
vec4 m_vCameraPosition;
};
struct PerMeshData_t
{
mat4 m_matTranslation;
mat4 m_matRotation;
uint32_t m_uAlbedo;
};
class CFunnyMeshInstance;
class CFunnyMesh: public IMesh
{
public:
virtual void SetVertices( IVertexBuffer *pBuffer ) override;
virtual void SetIndicies( IIndexBuffer *pBuffer, EIndexFormat eIndexFormat ) override;
virtual void SetMaterial( IMaterial *pMaterial ) override;
CUtlString m_szName;
CUtlVector<CFunnyMeshInstance*> m_instances;
IMaterial *m_pMaterial;
IVertexBuffer *m_pVertexBuffer;
};
void CFunnyMesh::SetVertices( IVertexBuffer *pBuffer )
{
m_pVertexBuffer = pBuffer;
}
void CFunnyMesh::SetIndicies( IIndexBuffer *pBuffer, EIndexFormat eIndexFormat )
{
}
void CFunnyMesh::SetMaterial( IMaterial *pMaterial )
{
m_pMaterial = pMaterial;
}
class CFunnyMeshInstance: public IMeshInstance
{
public:
virtual void SetPosition( Vector vPosition ) override;
virtual void SetRotation( Quat vRotation ) override;
virtual void SetScale( Vector vScale ) override;
virtual void Frame();
PerMeshData_t m_data = {};
Quat m_vRotation = {};
Vector m_vPosition = {};
Vector m_vScale = { 1, 1, 1 };
};
void CFunnyMeshInstance::SetPosition( Vector vPosition )
{
m_vPosition = vPosition;
}
void CFunnyMeshInstance::SetRotation( Quat vRotation )
{
m_vRotation = vRotation;
}
void CFunnyMeshInstance::SetScale( Vector vScale )
{
m_vScale = vScale;
}
void CFunnyMeshInstance::Frame()
{
vec3 v;
versor q;
mat4 m;
glm_mat4_identity(m_data.m_matTranslation);
glm_mat4_identity(m_data.m_matRotation);
v[0] = m_vPosition.x;
v[1] = m_vPosition.y;
v[2] = m_vPosition.z;
glm_translate(m_data.m_matTranslation, v);
q[0] = m_vRotation.x;
q[1] = m_vRotation.y;
q[2] = m_vRotation.z;
q[3] = m_vRotation.w;
glm_quat_mat4(q, m);
glm_mat4_mul(m_data.m_matTranslation, m, m_data.m_matTranslation);
glm_mat4_mul(m_data.m_matRotation, m, m_data.m_matRotation);
v[0] = m_vScale.x;
v[1] = m_vScale.y;
v[2] = m_vScale.z;
glm_scale_make(m, v);
glm_mat4_mul(m_data.m_matTranslation, m, m_data.m_matTranslation);
m_data.m_uAlbedo = 1;
}
class CFunnyWorldRenderer: public IWorldRenderer
{
public:
virtual void Init() override;
virtual void Tick( float fDelta ) override;
virtual void Frame( float fDelta ) override;
virtual void Shutdown() override;
virtual void SetCameraRotation( Quat vRotation ) override;
virtual void SetCameraPosition( Vector vPosition ) override;
virtual IMesh *CreateMesh( const char *szName ) override;
virtual IMeshInstance *CreateInstance( IMesh *pMesh ) override;
virtual void ConfigureShader( IShader *pShader ) override;
private:
CUtlVector<CFunnyMesh*> m_pMeshes;
IImage *m_pOutputImage = NULL;
IImage *m_pResolvedOutputImage = NULL;
IImage *m_pDepthImage = NULL;
IImage *m_pNormalImage = NULL;
IImage *m_pWorldSpaceImage = NULL;
IRenderCommandList *m_pRasterCommandList = NULL;
IBuffer *m_pViewBuffer;
ViewBuffer_t *m_pViewBufferData;
ITextureArray *m_pTextures;
vec3 m_vPos;
versor m_vRot;
};
void CFunnyWorldRenderer::ConfigureShader( IShader *pShader )
{
pShader->AddLayout(0, 32);
pShader->AddAttribute(0, 0, VERTEX_FORMAT_XYZ32_SFLOAT, 0);
pShader->AddAttribute(0, 1, VERTEX_FORMAT_XY32_SFLOAT, 12);
pShader->AddAttribute(0, 2, VERTEX_FORMAT_XYZ32_SFLOAT, 20);
// albedo
pShader->AddOutputImage(0, IMAGE_FORMAT_RGBA8_UNORM);
pShader->AddOutputImage(1, IMAGE_FORMAT_RGBA16_SFLOAT);
pShader->AddOutputImage(2, IMAGE_FORMAT_RGBA32_SFLOAT);
pShader->SetMultisampling(MULTISAMPLE_TYPE_4_SAMPLES);
pShader->SetDepthImage(IMAGE_FORMAT_D32_SFLOAT);
}
static CFunnyWorldRenderer s_renderer;
IWorldRenderer *g_pWorldRenderer = &s_renderer;
void CFunnyWorldRenderer::Init()
{
m_pOutputImage = g_pRenderContext->CreateRenderTarget(
100,
100,
IMAGE_FORMAT_RGBA8_UNORM,
MULTISAMPLE_TYPE_4_SAMPLES
);
m_pResolvedOutputImage = g_pRenderContext->CreateRenderTarget(
100,
100,
IMAGE_FORMAT_RGBA8_UNORM,
MULTISAMPLE_TYPE_1_SAMPLES
);
m_pNormalImage = g_pRenderContext->CreateRenderTarget(
100,
100,
IMAGE_FORMAT_RGBA16_SFLOAT,
MULTISAMPLE_TYPE_4_SAMPLES
);
m_pWorldSpaceImage = g_pRenderContext->CreateRenderTarget(
100,
100,
IMAGE_FORMAT_RGBA32_SFLOAT,
MULTISAMPLE_TYPE_4_SAMPLES
);
m_pDepthImage = g_pRenderContext->CreateRenderTarget(
100,
100,
IMAGE_FORMAT_D32_SFLOAT,
MULTISAMPLE_TYPE_4_SAMPLES
);
g_pMainWindow->SetOutputImage(m_pResolvedOutputImage);
m_pRasterCommandList = g_pRenderContext->CreateCommandList();
m_pViewBuffer = g_pRenderContext->CreateConstantBuffer(sizeof(ViewBuffer_t));
m_pTextures = g_pRenderContext->CreateTextureArray();
}
void CFunnyWorldRenderer::Tick( float fDelta )
{
}
void CFunnyWorldRenderer::Frame( float fDelta )
{
uint32_t uWidth = g_pMainWindow->GetRenderWidth();
uint32_t uHeight = g_pMainWindow->GetRenderHeight();
mat4 matCamera;
glm_perspective(glm_rad(60), uWidth/(float)uHeight, 0.01, 10000, matCamera);
glm_translate(matCamera, m_vPos);
/*
V_printf("%f %f %f %f\n", matCamera[0][0], matCamera[0][1], matCamera[0][2], matCamera[0][3]);
V_printf("%f %f %f %f\n", matCamera[1][0], matCamera[1][1], matCamera[1][2], matCamera[1][3]);
V_printf("%f %f %f %f\n", matCamera[2][0], matCamera[2][1], matCamera[2][2], matCamera[2][3]);
V_printf("%f %f %f %f\n", matCamera[3][0], matCamera[3][1], matCamera[3][2], matCamera[3][3]);
*/
m_pViewBufferData = (ViewBuffer_t*)m_pViewBuffer->Map();
m_pViewBuffer->Lock();
V_memcpy(&m_pViewBufferData->m_matCameraProjection, matCamera, sizeof(matCamera));
V_memcpy(&m_pViewBufferData->m_vCameraPosition, m_vPos, sizeof(vec3));
m_pViewBuffer->Unlock();
m_pViewBuffer->Unmap();
if (g_pMainWindow->BRenderSizeUpdated())
{
g_pRenderContext->DestroyImage(m_pOutputImage);
g_pRenderContext->DestroyImage(m_pNormalImage);
g_pRenderContext->DestroyImage(m_pWorldSpaceImage);
g_pRenderContext->DestroyImage(m_pDepthImage);
m_pOutputImage = g_pRenderContext->CreateRenderTarget(
g_pMainWindow->GetRenderWidth(),
g_pMainWindow->GetRenderHeight(),
IMAGE_FORMAT_RGBA8_UNORM,
MULTISAMPLE_TYPE_4_SAMPLES);
m_pResolvedOutputImage = g_pRenderContext->CreateRenderTarget(
g_pMainWindow->GetRenderWidth(),
g_pMainWindow->GetRenderHeight(),
IMAGE_FORMAT_RGBA8_UNORM,
MULTISAMPLE_TYPE_1_SAMPLES);
m_pNormalImage = g_pRenderContext->CreateRenderTarget(
g_pMainWindow->GetRenderWidth(),
g_pMainWindow->GetRenderHeight(),
IMAGE_FORMAT_RGBA16_SFLOAT,
MULTISAMPLE_TYPE_4_SAMPLES
);
m_pWorldSpaceImage = g_pRenderContext->CreateRenderTarget(
g_pMainWindow->GetRenderWidth(),
g_pMainWindow->GetRenderHeight(),
IMAGE_FORMAT_RGBA32_SFLOAT,
MULTISAMPLE_TYPE_4_SAMPLES
);
m_pDepthImage = g_pRenderContext->CreateRenderTarget(
g_pMainWindow->GetRenderWidth(),
g_pMainWindow->GetRenderHeight(),
IMAGE_FORMAT_D32_SFLOAT,
MULTISAMPLE_TYPE_4_SAMPLES);
g_pMainWindow->SetOutputImage(m_pResolvedOutputImage);
}
m_pRasterCommandList->StartRecording();
m_pRasterCommandList->SetRenderResolution(uWidth, uHeight);
m_pRasterCommandList->SetRenderTarget(0, m_pOutputImage);
m_pRasterCommandList->SetRenderTarget(1, m_pNormalImage);
m_pRasterCommandList->SetRenderTarget(2, m_pWorldSpaceImage);
m_pRasterCommandList->SetDepthTarget(m_pDepthImage);
m_pRasterCommandList->SetViewport(0, 0, uWidth, uHeight, 0, 1);
m_pRasterCommandList->SetScissors(0, 0, uWidth, uHeight);
m_pRasterCommandList->SetClearColor(0, 0, 0, 0, 0);
m_pRasterCommandList->SetClearDepth(1);
for ( auto mesh: m_pMeshes)
{
if (mesh->m_instances.GetSize()==0)
continue;
CUtlVector<PerMeshData_t> data = {};
data.Reserve(mesh->m_instances.GetSize());
for ( auto instance: mesh->m_instances )
{
instance->Frame();
data.AppendTail(instance->m_data);
}
IBuffer *pDataBuffer = g_pRenderContext->CreateStorageBuffer(data.GetSize()*sizeof(PerMeshData_t));
pDataBuffer->Lock();
void *pData = pDataBuffer->Map();
for ( uint32_t i = 0; i < mesh->m_instances.GetSize(); i++ )
{
V_memcpy(&((PerMeshData_t*)pData)[i], &mesh->m_instances[i]->m_data, sizeof(PerMeshData_t));
}
pDataBuffer->Unmap();
pDataBuffer->Unlock();
mesh->m_pMaterial->VSSetConstantsBuffer(0, m_pViewBuffer);
mesh->m_pMaterial->VSSetConstantsBuffer(1, pDataBuffer);
mesh->m_pMaterial->PSSetTextureArray(1, m_pTextures);
g_pRenderContext->DestroyBuffer(pDataBuffer);
}
for ( auto mesh: m_pMeshes)
{
if (mesh->m_instances.GetSize()==0)
continue;
m_pRasterCommandList->SetMaterial(mesh->m_pMaterial);
m_pRasterCommandList->SetVertexBuffer(0, mesh->m_pVertexBuffer);
m_pRasterCommandList->DrawPrimitives(mesh->m_pVertexBuffer->GetSize()/32, 0, mesh->m_instances.GetSize(), 0);
}
m_pRasterCommandList->ResolveImage(m_pOutputImage, m_pResolvedOutputImage);
m_pRasterCommandList->EndRecording();
g_pRenderContext->SubmitCommandList(m_pRasterCommandList);
}
void CFunnyWorldRenderer::Shutdown()
{
}
void CFunnyWorldRenderer::SetCameraRotation( Quat vRotation )
{
m_vRot[0] = vRotation.x;
m_vRot[1] = vRotation.y;
m_vRot[2] = vRotation.z;
m_vRot[3] = vRotation.w;
}
void CFunnyWorldRenderer::SetCameraPosition( Vector vPosition )
{
m_vPos[0] = vPosition.x;
m_vPos[1] = vPosition.y;
m_vPos[2] = vPosition.z;
}
IMesh *CFunnyWorldRenderer::CreateMesh( const char *szName )
{
CFunnyMesh *pMesh = new CFunnyMesh;
pMesh->m_szName = szName;
m_pMeshes.AppendTail(pMesh);
return pMesh;
}
IMeshInstance *CFunnyWorldRenderer::CreateInstance( IMesh *pMesh )
{
CFunnyMesh *pFunnyMesh = (CFunnyMesh*)pMesh;
CFunnyMeshInstance *pInstance = new CFunnyMeshInstance;
pFunnyMesh->m_instances.AppendTail(pInstance);
return pInstance;
}