mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-10 06:31:48 +00:00
a76dba5cfb
- brightness-corrected ImGUI drawing - upgraded shader code to HLSL 2021 - vertex normals drawing
225 lines
7.9 KiB
C++
225 lines
7.9 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum
|
|
|
|
This file is part of Challenge Quake 3 (CNQ3).
|
|
|
|
Challenge Quake 3 is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
Challenge Quake 3 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|
===========================================================================
|
|
*/
|
|
// Cinematic Rendering Pipeline - vertex and index buffer management
|
|
|
|
|
|
#include "crp_local.h"
|
|
|
|
|
|
void GeoBuffers::Create(const char* name, uint32_t vertexCount, uint32_t indexCount)
|
|
{
|
|
baseVertexBuffers[BaseBufferId::Position].CreateVertexBuffer(
|
|
va("%s position", name), MemoryUsage::Upload, vertexCount, sizeof(vec3_t));
|
|
baseVertexBuffers[BaseBufferId::Normal].CreateVertexBuffer(
|
|
va("%s normal", name), MemoryUsage::Upload, vertexCount, sizeof(vec3_t));
|
|
stageVertexBuffers[StageBufferId::TexCoords].CreateVertexBuffer(
|
|
va("%s tc", name), MemoryUsage::Upload, vertexCount * MAX_SHADER_STAGES, sizeof(vec2_t));
|
|
stageVertexBuffers[StageBufferId::Color].CreateVertexBuffer(
|
|
va("%s color", name), MemoryUsage::Upload, vertexCount * MAX_SHADER_STAGES, sizeof(color4ub_t));
|
|
indexBuffer.Create(name, MemoryUsage::Upload, indexCount);
|
|
|
|
vertexBuffers[0] = baseVertexBuffers[BaseBufferId::Position].buffer;
|
|
vertexBuffers[1] = baseVertexBuffers[BaseBufferId::Normal].buffer;
|
|
vertexBuffers[2] = stageVertexBuffers[StageBufferId::TexCoords].buffer;
|
|
vertexBuffers[3] = stageVertexBuffers[StageBufferId::Color].buffer;
|
|
vertexBufferStrides[0] = sizeof(vec3_t);
|
|
vertexBufferStrides[1] = sizeof(vec3_t);
|
|
vertexBufferStrides[2] = sizeof(vec2_t);
|
|
vertexBufferStrides[3] = sizeof(color4ub_t);
|
|
}
|
|
|
|
void GeoBuffers::Rewind()
|
|
{
|
|
for(uint32_t b = 0; b < ARRAY_LEN(baseVertexBuffers); ++b)
|
|
{
|
|
baseVertexBuffers[b].Rewind();
|
|
}
|
|
for(uint32_t b = 0; b < ARRAY_LEN(stageVertexBuffers); ++b)
|
|
{
|
|
stageVertexBuffers[b].Rewind();
|
|
}
|
|
indexBuffer.Rewind();
|
|
}
|
|
|
|
void GeoBuffers::BeginUpload()
|
|
{
|
|
for(uint32_t b = 0; b < ARRAY_LEN(baseVertexBuffers); ++b)
|
|
{
|
|
baseVertexBuffers[b].BeginUpload();
|
|
}
|
|
for(uint32_t b = 0; b < ARRAY_LEN(stageVertexBuffers); ++b)
|
|
{
|
|
stageVertexBuffers[b].BeginUpload();
|
|
}
|
|
indexBuffer.BeginUpload();
|
|
}
|
|
|
|
void GeoBuffers::EndUpload()
|
|
{
|
|
for(uint32_t b = 0; b < ARRAY_LEN(baseVertexBuffers); ++b)
|
|
{
|
|
baseVertexBuffers[b].EndUpload();
|
|
}
|
|
for(uint32_t b = 0; b < ARRAY_LEN(stageVertexBuffers); ++b)
|
|
{
|
|
stageVertexBuffers[b].EndUpload();
|
|
}
|
|
indexBuffer.EndUpload();
|
|
}
|
|
|
|
void GeoBuffers::UploadBase()
|
|
{
|
|
indexBuffer.Upload();
|
|
|
|
const uint32_t batchOffset = baseVertexBuffers[0].batchFirst + baseVertexBuffers[0].batchCount;
|
|
|
|
float* pos = (float*)baseVertexBuffers[BaseBufferId::Position].mapped + 3 * batchOffset;
|
|
for(int v = 0; v < tess.numVertexes; ++v)
|
|
{
|
|
pos[0] = tess.xyz[v][0];
|
|
pos[1] = tess.xyz[v][1];
|
|
pos[2] = tess.xyz[v][2];
|
|
pos += 3;
|
|
}
|
|
|
|
float* nor = (float*)baseVertexBuffers[BaseBufferId::Normal].mapped + 3 * batchOffset;
|
|
for(int v = 0; v < tess.numVertexes; ++v)
|
|
{
|
|
nor[0] = tess.normal[v][0];
|
|
nor[1] = tess.normal[v][1];
|
|
nor[2] = tess.normal[v][2];
|
|
nor += 3;
|
|
}
|
|
}
|
|
|
|
void GeoBuffers::UploadStage(uint32_t svarsIndex)
|
|
{
|
|
const uint32_t batchOffset = stageVertexBuffers[0].batchFirst + stageVertexBuffers[0].batchCount;
|
|
const stageVars_t& sv = tess.svars[svarsIndex];
|
|
|
|
uint8_t* const tcBuffer = stageVertexBuffers[StageBufferId::TexCoords].mapped;
|
|
float* tc = (float*)tcBuffer + 2 * batchOffset;
|
|
memcpy(tc, &sv.texcoords[0], tess.numVertexes * sizeof(vec2_t));
|
|
|
|
uint8_t* const colBuffer = stageVertexBuffers[StageBufferId::Color].mapped;
|
|
uint32_t* col = (uint32_t*)colBuffer + batchOffset;
|
|
memcpy(col, &sv.colors[0], tess.numVertexes * sizeof(color4ub_t));
|
|
}
|
|
|
|
void GeoBuffers::EndBaseBatch(uint32_t vertexCount)
|
|
{
|
|
baseVertexBuffers[BaseBufferId::Position].EndBatch(vertexCount);
|
|
baseVertexBuffers[BaseBufferId::Normal].EndBatch(vertexCount);
|
|
indexBuffer.EndBatch(tess.numIndexes);
|
|
}
|
|
|
|
bool GeoBuffers::CanAdd(uint32_t vertexCount, uint32_t indexCount, uint32_t stageCount)
|
|
{
|
|
return
|
|
baseVertexBuffers[0].CanAdd(vertexCount) &&
|
|
stageVertexBuffers[0].CanAdd(vertexCount * stageCount) &&
|
|
indexBuffer.CanAdd(indexCount);
|
|
}
|
|
|
|
void GeoBuffers::DrawStage(uint32_t vertexCount, uint32_t indexCount)
|
|
{
|
|
const uint32_t vertexOffset = stageVertexBuffers[0].batchFirst - baseVertexBuffers[0].batchFirst;
|
|
uint32_t byteOffsets[BaseBufferId::Count + StageBufferId::Count] = {};
|
|
byteOffsets[BaseBufferId::Count + StageBufferId::TexCoords] = vertexOffset * sizeof(vec2_t);
|
|
byteOffsets[BaseBufferId::Count + StageBufferId::Color] = vertexOffset * sizeof(color4ub_t);
|
|
CmdBindVertexBuffers(ARRAY_LEN(vertexBuffers), vertexBuffers, vertexBufferStrides, byteOffsets);
|
|
|
|
CmdDrawIndexed(indexCount, indexBuffer.batchFirst, baseVertexBuffers[0].batchFirst);
|
|
|
|
// @NOTE: must happen after the final vertex buffer byte offsets have been computed
|
|
stageVertexBuffers[StageBufferId::TexCoords].EndBatch(vertexCount);
|
|
stageVertexBuffers[StageBufferId::Color].EndBatch(vertexCount);
|
|
}
|
|
|
|
void GeoBuffers::DrawPositionOnly(uint32_t vertexCount, uint32_t indexCount)
|
|
{
|
|
const HBuffer buffer = vertexBuffers[BaseBufferId::Position];
|
|
const uint32_t stride = vertexBufferStrides[BaseBufferId::Position];
|
|
const uint32_t byteOffset = 0;
|
|
CmdBindVertexBuffers(1, &buffer, &stride, &byteOffset);
|
|
CmdDrawIndexed(indexCount, indexBuffer.batchFirst, baseVertexBuffers[0].batchFirst);
|
|
}
|
|
|
|
void GeoBuffers::UploadAndDrawDebugNormals()
|
|
{
|
|
if(!baseVertexBuffers[0].CanAdd(tess.numVertexes * 2) ||
|
|
!indexBuffer.CanAdd(tess.numVertexes * 3))
|
|
{
|
|
return;
|
|
}
|
|
|
|
const uint32_t posBatchOffset = baseVertexBuffers[BaseBufferId::Position].batchFirst + baseVertexBuffers[BaseBufferId::Position].batchCount;
|
|
float* positions = (float*)baseVertexBuffers[BaseBufferId::Position].mapped + 3 * posBatchOffset;
|
|
for(uint32_t v = 0; v < tess.numVertexes; v++)
|
|
{
|
|
vec3_t newPoint;
|
|
VectorMA(tess.xyz[v], 4.0f, tess.normal[v], newPoint);
|
|
*positions++ = tess.xyz[v][0];
|
|
*positions++ = tess.xyz[v][1];
|
|
*positions++ = tess.xyz[v][2];
|
|
*positions++ = newPoint[0];
|
|
*positions++ = newPoint[1];
|
|
*positions++ = newPoint[2];
|
|
}
|
|
|
|
const uint32_t colBatchOffset = stageVertexBuffers[StageBufferId::Color].batchFirst + stageVertexBuffers[StageBufferId::Color].batchCount;
|
|
uint8_t* const colBuffer = stageVertexBuffers[StageBufferId::Color].mapped;
|
|
uint32_t* col = (uint32_t*)colBuffer + colBatchOffset;
|
|
for(uint32_t v = 0; v < tess.numVertexes; v++)
|
|
{
|
|
*col++ = 0xFF0000FF;
|
|
*col++ = 0xFFFF7F00;
|
|
}
|
|
|
|
uint32_t* indices = indexBuffer.GetCurrentAddress();
|
|
for(uint32_t i = 0; i < tess.numVertexes; i++)
|
|
{
|
|
*indices++ = i * 2 + 0;
|
|
*indices++ = i * 2 + 0;
|
|
*indices++ = i * 2 + 1;
|
|
}
|
|
|
|
const uint32_t vertexOffset = stageVertexBuffers[0].batchFirst - baseVertexBuffers[0].batchFirst;
|
|
const uint32_t byteOffsets[2] = { 0, vertexOffset * sizeof(color4ub_t) };
|
|
HBuffer vb[2];
|
|
vb[0] = vertexBuffers[BaseBufferId::Position];
|
|
vb[1] = vertexBuffers[BaseBufferId::Count + StageBufferId::Color];
|
|
uint32_t strides[2];
|
|
strides[0] = vertexBufferStrides[BaseBufferId::Position];
|
|
strides[1] = vertexBufferStrides[BaseBufferId::Count + StageBufferId::Color];
|
|
CmdBindVertexBuffers(ARRAY_LEN(vb), vb, strides, byteOffsets);
|
|
CmdDrawIndexed(tess.numVertexes * 3, indexBuffer.batchFirst, baseVertexBuffers[0].batchFirst);
|
|
|
|
for(int b = 0; b < ARRAY_LEN(baseVertexBuffers); b++)
|
|
{
|
|
baseVertexBuffers[b].EndBatch(tess.numVertexes * 2);
|
|
}
|
|
for(int b = 0; b < ARRAY_LEN(stageVertexBuffers); b++)
|
|
{
|
|
stageVertexBuffers[b].EndBatch(tess.numVertexes * 2);
|
|
}
|
|
indexBuffer.EndBatch(tess.numVertexes * 3);
|
|
}
|