Changeset View
Changeset View
Standalone View
Standalone View
source/renderer/InstancingModelRenderer.cpp
Show First 20 Lines • Show All 289 Lines • ▼ Show 20 Lines | |||||
void InstancingModelRenderer::UpdateModelData(CModel* UNUSED(model), CModelRData* UNUSED(data), int UNUSED(updateflags)) | void InstancingModelRenderer::UpdateModelData(CModel* UNUSED(model), CModelRData* UNUSED(data), int UNUSED(updateflags)) | ||||
{ | { | ||||
// We have no per-CModel data | // We have no per-CModel data | ||||
} | } | ||||
// Setup one rendering pass. | // Setup one rendering pass. | ||||
void InstancingModelRenderer::BeginPass(int streamflags) | void InstancingModelRenderer::BeginPass() | ||||
{ | { | ||||
ENSURE(streamflags == (streamflags & (STREAM_POS|STREAM_NORMAL|STREAM_UV0|STREAM_UV1|STREAM_UV2|STREAM_UV3|STREAM_UV4))); | |||||
} | } | ||||
// Cleanup rendering pass. | // Cleanup rendering pass. | ||||
void InstancingModelRenderer::EndPass( | void InstancingModelRenderer::EndPass( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext)) | ||||
int UNUSED(streamflags)) | |||||
{ | { | ||||
CVertexBuffer::Unbind(deviceCommandContext); | |||||
} | } | ||||
// Prepare UV coordinates for this modeldef | // Prepare UV coordinates for this modeldef | ||||
void InstancingModelRenderer::PrepareModelDef( | void InstancingModelRenderer::PrepareModelDef( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | ||||
Renderer::Backend::GL::CShaderProgram* shader, int streamflags, const CModelDef& def) | Renderer::Backend::GL::CShaderProgram* UNUSED(shader), const CModelDef& def) | ||||
{ | { | ||||
m->imodeldef = (IModelDef*)def.GetRenderData(m); | m->imodeldef = (IModelDef*)def.GetRenderData(m); | ||||
ENSURE(m->imodeldef); | ENSURE(m->imodeldef); | ||||
m->imodeldef->m_Array.UploadIfNeeded(deviceCommandContext); | |||||
u8* base = m->imodeldef->m_Array.Bind(deviceCommandContext); | |||||
GLsizei stride = (GLsizei)m->imodeldef->m_Array.GetStride(); | |||||
m->imodeldef->m_IndexArray.UploadIfNeeded(deviceCommandContext); | m->imodeldef->m_IndexArray.UploadIfNeeded(deviceCommandContext); | ||||
deviceCommandContext->SetIndexBuffer(m->imodeldef->m_IndexArray.GetBuffer()); | deviceCommandContext->SetIndexBuffer(m->imodeldef->m_IndexArray.GetBuffer()); | ||||
if (streamflags & STREAM_POS) | const uint32_t stride = m->imodeldef->m_Array.GetStride(); | ||||
{ | const uint32_t firstVertexOffset = m->imodeldef->m_Array.GetOffset() * stride; | ||||
shader->VertexPointer( | |||||
m->imodeldef->m_Position.format, stride, | |||||
base + m->imodeldef->m_Position.offset); | |||||
} | |||||
if (streamflags & STREAM_NORMAL) | deviceCommandContext->SetVertexAttributeFormat( | ||||
{ | Renderer::Backend::VertexAttributeStream::POSITION, | ||||
shader->NormalPointer( | m->imodeldef->m_Position.format, | ||||
m->imodeldef->m_Normal.format, stride, | firstVertexOffset + m->imodeldef->m_Position.offset, stride, 0); | ||||
base + m->imodeldef->m_Normal.offset); | deviceCommandContext->SetVertexAttributeFormat( | ||||
Renderer::Backend::VertexAttributeStream::NORMAL, | |||||
m->imodeldef->m_Normal.format, | |||||
firstVertexOffset + m->imodeldef->m_Normal.offset, stride, 0); | |||||
constexpr size_t MAX_UV = 2; | |||||
for (size_t uv = 0; uv < std::min(MAX_UV, def.GetNumUVsPerVertex()); ++uv) | |||||
{ | |||||
const Renderer::Backend::VertexAttributeStream stream = | |||||
static_cast<Renderer::Backend::VertexAttributeStream>( | |||||
static_cast<int>(Renderer::Backend::VertexAttributeStream::UV0) + uv); | |||||
deviceCommandContext->SetVertexAttributeFormat( | |||||
stream, m->imodeldef->m_UVs[uv].format, | |||||
firstVertexOffset + m->imodeldef->m_UVs[uv].offset, stride, 0); | |||||
} | } | ||||
if (m->calculateTangents) | // GPU skinning requires extra attributes to compute positions/normals | ||||
if (m->gpuSkinning) | |||||
{ | { | ||||
shader->VertexAttribPointer( | deviceCommandContext->SetVertexAttributeFormat( | ||||
str_a_tangent, m->imodeldef->m_Tangent.format, | Renderer::Backend::VertexAttributeStream::UV2, | ||||
GL_FALSE, stride, base + m->imodeldef->m_Tangent.offset); | m->imodeldef->m_BlendJoints.format, | ||||
firstVertexOffset + m->imodeldef->m_BlendJoints.offset, stride, 0); | |||||
deviceCommandContext->SetVertexAttributeFormat( | |||||
Renderer::Backend::VertexAttributeStream::UV3, | |||||
m->imodeldef->m_BlendWeights.format, | |||||
firstVertexOffset + m->imodeldef->m_BlendWeights.offset, stride, 0); | |||||
} | } | ||||
for (size_t uv = 0; uv < 2; ++uv) | if (m->calculateTangents) | ||||
if (streamflags & (STREAM_UV0 << uv)) | |||||
{ | |||||
if (def.GetNumUVsPerVertex() >= uv + 1) | |||||
{ | { | ||||
shader->TexCoordPointer( | deviceCommandContext->SetVertexAttributeFormat( | ||||
GL_TEXTURE0 + uv, m->imodeldef->m_UVs[uv].format, stride, | Renderer::Backend::VertexAttributeStream::UV4, | ||||
base + m->imodeldef->m_UVs[uv].offset); | m->imodeldef->m_Tangent.format, | ||||
} | firstVertexOffset + m->imodeldef->m_Tangent.offset, stride, 0); | ||||
else | |||||
ONCE(LOGERROR("Model '%s' has no UV%d set.", def.GetName().string8().c_str(), uv)); | |||||
} | } | ||||
// GPU skinning requires extra attributes to compute positions/normals | deviceCommandContext->SetVertexBuffer(0, m->imodeldef->m_Array.GetBuffer()); | ||||
if (m->gpuSkinning) | |||||
{ | |||||
shader->VertexAttribPointer( | |||||
str_a_skinJoints, m->imodeldef->m_BlendJoints.format, GL_FALSE, | |||||
stride, base + m->imodeldef->m_BlendJoints.offset); | |||||
shader->VertexAttribPointer( | |||||
str_a_skinWeights, m->imodeldef->m_BlendWeights.format, GL_TRUE, | |||||
stride, base + m->imodeldef->m_BlendWeights.offset); | |||||
} | |||||
} | } | ||||
// Render one model | // Render one model | ||||
void InstancingModelRenderer::RenderModel( | void InstancingModelRenderer::RenderModel( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | ||||
Renderer::Backend::GL::CShaderProgram* shader, int UNUSED(streamflags), CModel* model, CModelRData* UNUSED(data)) | Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* UNUSED(data)) | ||||
{ | { | ||||
const CModelDefPtr& mdldef = model->GetModelDef(); | const CModelDefPtr& mdldef = model->GetModelDef(); | ||||
if (m->gpuSkinning) | if (m->gpuSkinning) | ||||
{ | { | ||||
// Bind matrices for current animation state. | // Bind matrices for current animation state. | ||||
// Add 1 to NumBones because of the special 'root' bone. | // Add 1 to NumBones because of the special 'root' bone. | ||||
// HACK: NVIDIA drivers return uniform name with "[0]", Intel Windows drivers without; | // HACK: NVIDIA drivers return uniform name with "[0]", Intel Windows drivers without; | ||||
// try uploading both names since one of them should work, and this is easier than | // try uploading both names since one of them should work, and this is easier than | ||||
// canonicalising the uniform names in CShaderProgramGLSL | // canonicalising the uniform names in CShaderProgramGLSL | ||||
shader->Uniform(str_skinBlendMatrices_0, mdldef->GetNumBones() + 1, model->GetAnimatedBoneMatrices()); | shader->Uniform(str_skinBlendMatrices_0, mdldef->GetNumBones() + 1, model->GetAnimatedBoneMatrices()); | ||||
shader->Uniform(str_skinBlendMatrices, mdldef->GetNumBones() + 1, model->GetAnimatedBoneMatrices()); | shader->Uniform(str_skinBlendMatrices, mdldef->GetNumBones() + 1, model->GetAnimatedBoneMatrices()); | ||||
} | } | ||||
// Render the lot. | // Render the lot. | ||||
const size_t numberOfFaces = mdldef->GetNumFaces(); | const size_t numberOfFaces = mdldef->GetNumFaces(); | ||||
deviceCommandContext->DrawIndexedInRange( | deviceCommandContext->DrawIndexedInRange( | ||||
m->imodeldef->m_IndexArray.GetOffset(), numberOfFaces * 3, 0, m->imodeldef->m_Array.GetNumberOfVertices() - 1); | m->imodeldef->m_IndexArray.GetOffset(), numberOfFaces * 3, 0, m->imodeldef->m_Array.GetNumberOfVertices() - 1); | ||||
// Bump stats. | // Bump stats. | ||||
g_Renderer.m_Stats.m_DrawCalls++; | g_Renderer.m_Stats.m_DrawCalls++; | ||||
g_Renderer.m_Stats.m_ModelTris += numberOfFaces; | g_Renderer.m_Stats.m_ModelTris += numberOfFaces; | ||||
} | } |
Wildfire Games · Phabricator