#include "worldrender.h" #include "tier1/utlstring.h" #include "cglm/cglm.h" #include "cglm/quat.h" #include "cglm/mat4.h" #include "game.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 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 DestroyMeshInstance( IMesh *pMesh, IMeshInstance *pInstance ) override; virtual void DestroyMesh( IMesh *pMesh ) override; virtual void ConfigureShader( IShader *pShader ) override; private: CUtlVector 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; IShader *m_pRasterShader; IMaterial *m_pRasterMaterial; 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 ); m_pRasterShader = g_pRenderContext->CreateShader("game/core/shaders/mesh_raster.shader_c"); ConfigureShader(m_pRasterShader); m_pRasterShader->Build(); m_pRasterMaterial = g_pRenderContext->CreateMaterial(m_pRasterShader); 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; mat4 matCamera2; glm_mat4_identity(matCamera); glm_mat4_identity(matCamera2); glm_translate(matCamera2, m_vPos); glm_perspective(glm_rad(60), uWidth/(float)uHeight, 0.01, 10000, matCamera); glm_mul(matCamera, matCamera2, matCamera); /* 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 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(); m_pRasterMaterial->VSSetConstantsBuffer(0, m_pViewBuffer); m_pRasterMaterial->VSSetConstantsBuffer(1, pDataBuffer); m_pRasterMaterial->PSSetTextureArray(1, m_pTextures); g_pRenderContext->DestroyBuffer(pDataBuffer); } for ( auto mesh: m_pMeshes) { if (mesh->m_instances.GetSize()==0) continue; m_pRasterCommandList->SetMaterial(m_pRasterMaterial); 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; } void CFunnyWorldRenderer::DestroyMeshInstance( IMesh *pMesh, IMeshInstance *pInstance ) { if (!pMesh) return; CFunnyMesh *pFunnyMesh = (CFunnyMesh*)pMesh; for ( uint32_t i = 0; i < pFunnyMesh->m_instances.GetSize(); i++ ) { if ( pFunnyMesh->m_instances[i] != pInstance) continue; delete pFunnyMesh->m_instances[i]; pFunnyMesh->m_instances.RemoveAt(i, 1); break; } } void CFunnyWorldRenderer::DestroyMesh( IMesh *pMesh ) { }