Sort translucent meshes per section.

This commit is contained in:
Leonardo Zide 2019-11-22 16:47:58 -08:00
parent 481d4e6e81
commit bd25c7f31a
6 changed files with 174 additions and 77 deletions

View file

@ -74,6 +74,7 @@ struct lcMeshSection;
struct lcRenderMesh; struct lcRenderMesh;
class lcTexture; class lcTexture;
class lcScene; class lcScene;
enum class lcRenderMeshState : int;
class lcFile; class lcFile;
class lcMemFile; class lcMemFile;

View file

@ -112,24 +112,5 @@ public:
int mIndexType; int mIndexType;
}; };
enum class lcRenderMeshState : int
{
NORMAL,
SELECTED,
FOCUSED,
DISABLED,
HIGHLIGHT
};
struct lcRenderMesh
{
lcMatrix44 WorldMatrix;
lcMesh* Mesh;
float Distance;
int ColorIndex;
int LodIndex;
lcRenderMeshState State;
};
extern lcMesh* gPlaceholderMesh; extern lcMesh* gPlaceholderMesh;

View file

@ -19,7 +19,6 @@
#define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x1000 // Can remove control points from focused piece #define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x1000 // Can remove control points from focused piece
class lcGLWidget; class lcGLWidget;
enum class lcRenderMeshState : int;
enum class lcSelectionMode enum class lcSelectionMode
{ {

View file

@ -43,9 +43,9 @@ void lcScene::End()
std::sort(mOpaqueMeshes.begin(), mOpaqueMeshes.end(), OpaqueMeshCompare); std::sort(mOpaqueMeshes.begin(), mOpaqueMeshes.end(), OpaqueMeshCompare);
auto TranslucentMeshCompare = [this](int Index1, int Index2) auto TranslucentMeshCompare = [this](const lcTranslucentMeshInstance& Mesh1, const lcTranslucentMeshInstance& Mesh2)
{ {
return mRenderMeshes[Index1].Distance > mRenderMeshes[Index2].Distance; return Mesh1.Distance > Mesh2.Distance;
}; };
std::sort(mTranslucentMeshes.begin(), mTranslucentMeshes.end(), TranslucentMeshCompare); std::sort(mTranslucentMeshes.begin(), mTranslucentMeshes.end(), TranslucentMeshCompare);
@ -59,8 +59,8 @@ void lcScene::AddMesh(lcMesh* Mesh, const lcMatrix44& WorldMatrix, int ColorInde
RenderMesh.Mesh = Mesh; RenderMesh.Mesh = Mesh;
RenderMesh.ColorIndex = ColorIndex; RenderMesh.ColorIndex = ColorIndex;
RenderMesh.State = State; RenderMesh.State = State;
RenderMesh.Distance = fabsf(lcMul31(WorldMatrix[3], mViewMatrix).z); float Distance = fabsf(lcMul31(WorldMatrix[3], mViewMatrix).z);
RenderMesh.LodIndex = RenderMesh.Mesh->GetLodIndex(RenderMesh.Distance); RenderMesh.LodIndex = RenderMesh.Mesh->GetLodIndex(Distance);
bool Translucent = lcIsColorTranslucent(ColorIndex); bool Translucent = lcIsColorTranslucent(ColorIndex);
lcMeshFlags Flags = Mesh->mFlags; lcMeshFlags Flags = Mesh->mFlags;
@ -69,21 +69,60 @@ void lcScene::AddMesh(lcMesh* Mesh, const lcMatrix44& WorldMatrix, int ColorInde
mOpaqueMeshes.Add(mRenderMeshes.GetSize() - 1); mOpaqueMeshes.Add(mRenderMeshes.GetSize() - 1);
if ((Flags & lcMeshFlag::HasTranslucent) || ((Flags & lcMeshFlag::HasDefault) && Translucent)) if ((Flags & lcMeshFlag::HasTranslucent) || ((Flags & lcMeshFlag::HasDefault) && Translucent))
mTranslucentMeshes.Add(mRenderMeshes.GetSize() - 1); {
const lcMeshLod& Lod = Mesh->mLods[RenderMesh.LodIndex];
for (int SectionIdx = 0; SectionIdx < Lod.NumSections; SectionIdx++)
{
const lcMeshSection* Section = &Lod.Sections[SectionIdx];
if ((Section->PrimitiveType & (LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES)) == 0)
continue;
int ColorIndex = Section->ColorIndex;
if (ColorIndex == gDefaultColor)
ColorIndex = RenderMesh.ColorIndex;
if (!lcIsColorTranslucent(ColorIndex))
continue;
lcVector3 Center = (Section->BoundingBox.Min + Section->BoundingBox.Max) / 2;
float Distance = fabsf(lcMul31(lcMul31(Center, WorldMatrix), mViewMatrix).z);
lcTranslucentMeshInstance& Instance = mTranslucentMeshes.Add();
Instance.Section = Section;
Instance.Distance = Distance;
Instance.RenderMeshIndex = mRenderMeshes.GetSize() - 1;
}
}
} }
void lcScene::DrawPass(lcContext* Context, lcRenderPass RenderPass, int PrimitiveTypes) const void lcScene::DrawDebugNormals(lcContext* Context, lcMesh* Mesh) const
{ {
bool IsTranslucent = (RenderPass == lcRenderPass::UnlitTranslucent || RenderPass == lcRenderPass::LitTranslucent); lcVertex* VertexBuffer = (lcVertex*)Mesh->mVertexData;
const lcArray<int>& Meshes = IsTranslucent ? mTranslucentMeshes : mOpaqueMeshes; lcVector3* Vertices = (lcVector3*)malloc(Mesh->mNumVertices * 2 * sizeof(lcVector3));
if (Meshes.IsEmpty()) for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++)
{
Vertices[VertexIdx * 2] = VertexBuffer[VertexIdx].Position;
Vertices[VertexIdx * 2 + 1] = VertexBuffer[VertexIdx].Position + lcUnpackNormal(VertexBuffer[VertexIdx].Normal);
}
Context->SetVertexBufferPointer(Vertices);
Context->SetVertexFormatPosition(3);
Context->DrawPrimitives(GL_LINES, 0, Mesh->mNumVertices * 2);
free(Vertices);
}
void lcScene::DrawOpaqueMeshes(lcContext* Context, bool DrawLit, int PrimitiveTypes) const
{
if (mOpaqueMeshes.IsEmpty())
return; return;
bool IsLit = (RenderPass == lcRenderPass::LitOpaque || RenderPass == lcRenderPass::LitTranslucent);
lcMaterialType FlatMaterial, TexturedMaterial; lcMaterialType FlatMaterial, TexturedMaterial;
if (IsLit) if (DrawLit)
{ {
FlatMaterial = LC_MATERIAL_FAKELIT_COLOR; FlatMaterial = LC_MATERIAL_FAKELIT_COLOR;
TexturedMaterial = LC_MATERIAL_FAKELIT_TEXTURE_DECAL; TexturedMaterial = LC_MATERIAL_FAKELIT_TEXTURE_DECAL;
@ -94,16 +133,9 @@ void lcScene::DrawPass(lcContext* Context, lcRenderPass RenderPass, int Primitiv
TexturedMaterial = LC_MATERIAL_UNLIT_TEXTURE_DECAL; TexturedMaterial = LC_MATERIAL_UNLIT_TEXTURE_DECAL;
} }
if (IsTranslucent) Context->SetPolygonOffset(LC_POLYGON_OFFSET_OPAQUE);
{
glEnable(GL_BLEND);
Context->SetDepthWrite(false);
Context->SetPolygonOffset(LC_POLYGON_OFFSET_TRANSLUCENT);
}
else
Context->SetPolygonOffset(LC_POLYGON_OFFSET_OPAQUE);
for (int MeshIndex : Meshes) for (int MeshIndex : mOpaqueMeshes)
{ {
const lcRenderMesh& RenderMesh = mRenderMeshes[MeshIndex]; const lcRenderMesh& RenderMesh = mRenderMeshes[MeshIndex];
const lcMesh* Mesh = RenderMesh.Mesh; const lcMesh* Mesh = RenderMesh.Mesh;
@ -126,7 +158,7 @@ void lcScene::DrawPass(lcContext* Context, lcRenderPass RenderPass, int Primitiv
if (ColorIndex == gDefaultColor) if (ColorIndex == gDefaultColor)
ColorIndex = RenderMesh.ColorIndex; ColorIndex = RenderMesh.ColorIndex;
if (lcIsColorTranslucent(ColorIndex) != IsTranslucent) if (lcIsColorTranslucent(ColorIndex))
continue; continue;
switch (RenderMesh.State) switch (RenderMesh.State)
@ -184,7 +216,7 @@ void lcScene::DrawPass(lcContext* Context, lcRenderPass RenderPass, int Primitiv
int IndexBufferOffset = Mesh->mIndexCacheOffset != -1 ? Mesh->mIndexCacheOffset : 0; int IndexBufferOffset = Mesh->mIndexCacheOffset != -1 ? Mesh->mIndexCacheOffset : 0;
int VertexBufferOffset = Mesh->mVertexCacheOffset != -1 ? Mesh->mVertexCacheOffset : 0; int VertexBufferOffset = Mesh->mVertexCacheOffset != -1 ? Mesh->mVertexCacheOffset : 0;
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 0, 0, IsLit); Context->SetVertexFormat(VertexBufferOffset, 3, 1, 0, 0, DrawLit);
if (Mesh->mIndexType == GL_UNSIGNED_SHORT) if (Mesh->mIndexType == GL_UNSIGNED_SHORT)
{ {
@ -227,13 +259,13 @@ void lcScene::DrawPass(lcContext* Context, lcRenderPass RenderPass, int Primitiv
if (!Texture) if (!Texture)
{ {
Context->SetMaterial(FlatMaterial); Context->SetMaterial(FlatMaterial);
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 0, 0, IsLit); Context->SetVertexFormat(VertexBufferOffset, 3, 1, 0, 0, DrawLit);
} }
else else
{ {
Context->SetMaterial(TexturedMaterial); Context->SetMaterial(TexturedMaterial);
VertexBufferOffset += Mesh->mNumVertices * sizeof(lcVertex); VertexBufferOffset += Mesh->mNumVertices * sizeof(lcVertex);
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 2, 0, IsLit); Context->SetVertexFormat(VertexBufferOffset, 3, 1, 2, 0, DrawLit);
Context->BindTexture2D(Texture->mTexture); Context->BindTexture2D(Texture->mTexture);
} }
@ -241,36 +273,102 @@ void lcScene::DrawPass(lcContext* Context, lcRenderPass RenderPass, int Primitiv
Context->DrawIndexedPrimitives(DrawPrimitiveType, Section->NumIndices, Mesh->mIndexType, IndexBufferOffset + Section->IndexOffset); Context->DrawIndexedPrimitives(DrawPrimitiveType, Section->NumIndices, Mesh->mIndexType, IndexBufferOffset + Section->IndexOffset);
} }
#ifdef QT_DEBUG #ifdef LC_DEBUG_NORMALS
const bool DrawNormals = false; DrawDebugNormals(Context, Mesh);
#endif
}
if (DrawNormals) Context->BindTexture2D(0);
Context->SetPolygonOffset(LC_POLYGON_OFFSET_NONE);
}
void lcScene::DrawTranslucentMeshes(lcContext* Context, bool DrawLit) const
{
if (mTranslucentMeshes.IsEmpty())
return;
lcMaterialType FlatMaterial, TexturedMaterial;
if (DrawLit)
{
FlatMaterial = LC_MATERIAL_FAKELIT_COLOR;
TexturedMaterial = LC_MATERIAL_FAKELIT_TEXTURE_DECAL;
}
else
{
FlatMaterial = LC_MATERIAL_UNLIT_COLOR;
TexturedMaterial = LC_MATERIAL_UNLIT_TEXTURE_DECAL;
}
glEnable(GL_BLEND);
Context->SetDepthWrite(false);
Context->SetPolygonOffset(LC_POLYGON_OFFSET_TRANSLUCENT);
for (const lcTranslucentMeshInstance& MeshInstance : mTranslucentMeshes)
{
const lcRenderMesh& RenderMesh = mRenderMeshes[MeshInstance.RenderMeshIndex];
const lcMesh* Mesh = RenderMesh.Mesh;
Context->BindMesh(Mesh);
Context->SetWorldMatrix(RenderMesh.WorldMatrix);
const lcMeshSection* Section = MeshInstance.Section;
int ColorIndex = Section->ColorIndex;
if (ColorIndex == gDefaultColor)
ColorIndex = RenderMesh.ColorIndex;
switch (RenderMesh.State)
{ {
lcVertex* VertexBuffer = (lcVertex*)Mesh->mVertexData; case lcRenderMeshState::NORMAL:
lcVector3* Vertices = (lcVector3*)malloc(Mesh->mNumVertices * 2 * sizeof(lcVector3)); case lcRenderMeshState::HIGHLIGHT:
Context->SetColorIndex(ColorIndex);
break;
for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++) case lcRenderMeshState::SELECTED:
{ Context->SetColorIndexTinted(ColorIndex, LC_COLOR_SELECTED, 0.5f);
Vertices[VertexIdx * 2] = VertexBuffer[VertexIdx].Position; break;
Vertices[VertexIdx * 2 + 1] = VertexBuffer[VertexIdx].Position + lcUnpackNormal(VertexBuffer[VertexIdx].Normal);
}
Context->SetVertexBufferPointer(Vertices); case lcRenderMeshState::FOCUSED:
Context->SetVertexFormatPosition(3); Context->SetColorIndexTinted(ColorIndex, LC_COLOR_FOCUSED, 0.5f);
Context->DrawPrimitives(GL_LINES, 0, Mesh->mNumVertices * 2); break;
free(Vertices);
case lcRenderMeshState::DISABLED:
Context->SetColorIndexTinted(ColorIndex, LC_COLOR_DISABLED, 0.25f);
break;
} }
lcTexture* Texture = Section->Texture;
int VertexBufferOffset = Mesh->mVertexCacheOffset != -1 ? Mesh->mVertexCacheOffset : 0;
int IndexBufferOffset = Mesh->mIndexCacheOffset != -1 ? Mesh->mIndexCacheOffset : 0;
if (!Texture)
{
Context->SetMaterial(FlatMaterial);
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 0, 0, DrawLit);
}
else
{
Context->SetMaterial(TexturedMaterial);
VertexBufferOffset += Mesh->mNumVertices * sizeof(lcVertex);
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 2, 0, DrawLit);
Context->BindTexture2D(Texture->mTexture);
}
GLenum DrawPrimitiveType = Section->PrimitiveType & (LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES) ? GL_TRIANGLES : GL_LINES;
Context->DrawIndexedPrimitives(DrawPrimitiveType, Section->NumIndices, Mesh->mIndexType, IndexBufferOffset + Section->IndexOffset);
#ifdef LC_DEBUG_NORMALS
DrawDebugNormals(Context, Mesh);
#endif #endif
} }
Context->BindTexture2D(0); Context->BindTexture2D(0);
Context->SetPolygonOffset(LC_POLYGON_OFFSET_NONE); Context->SetPolygonOffset(LC_POLYGON_OFFSET_NONE);
if (IsTranslucent) Context->SetDepthWrite(true);
{ glDisable(GL_BLEND);
Context->SetDepthWrite(true);
glDisable(GL_BLEND);
}
} }
void lcScene::Draw(lcContext* Context) const void lcScene::Draw(lcContext* Context) const
@ -295,7 +393,7 @@ void lcScene::Draw(lcContext* Context) const
if (DrawConditional) if (DrawConditional)
PrimitiveTypes |= LC_MESH_CONDITIONAL_LINES; PrimitiveTypes |= LC_MESH_CONDITIONAL_LINES;
DrawPass(Context, lcRenderPass::UnlitOpaque, PrimitiveTypes); DrawOpaqueMeshes(Context, false, PrimitiveTypes);
} }
else if (ShadingMode == LC_SHADING_FLAT) else if (ShadingMode == LC_SHADING_FLAT)
{ {
@ -311,8 +409,8 @@ void lcScene::Draw(lcContext* Context) const
PrimitiveTypes |= LC_MESH_CONDITIONAL_LINES; PrimitiveTypes |= LC_MESH_CONDITIONAL_LINES;
} }
DrawPass(Context, lcRenderPass::UnlitOpaque, PrimitiveTypes); DrawOpaqueMeshes(Context, false, PrimitiveTypes);
DrawPass(Context, lcRenderPass::UnlitTranslucent, LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES); DrawTranslucentMeshes(Context, false);
} }
else else
{ {
@ -325,11 +423,11 @@ void lcScene::Draw(lcContext* Context) const
if (DrawConditional) if (DrawConditional)
PrimitiveTypes |= LC_MESH_CONDITIONAL_LINES; PrimitiveTypes |= LC_MESH_CONDITIONAL_LINES;
DrawPass(Context, lcRenderPass::UnlitOpaque, PrimitiveTypes); DrawOpaqueMeshes(Context, false, PrimitiveTypes);
} }
DrawPass(Context, lcRenderPass::LitOpaque, LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES); DrawOpaqueMeshes(Context, true, LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES);
DrawPass(Context, lcRenderPass::LitTranslucent, LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES); DrawTranslucentMeshes(Context, true);
} }
} }

View file

@ -3,12 +3,29 @@
#include "lc_mesh.h" #include "lc_mesh.h"
#include "lc_array.h" #include "lc_array.h"
enum class lcRenderPass enum class lcRenderMeshState : int
{ {
UnlitOpaque, NORMAL,
UnlitTranslucent, SELECTED,
LitOpaque, FOCUSED,
LitTranslucent DISABLED,
HIGHLIGHT
};
struct lcRenderMesh
{
lcMatrix44 WorldMatrix;
lcMesh* Mesh;
int ColorIndex;
int LodIndex;
lcRenderMeshState State;
};
struct lcTranslucentMeshInstance
{
const lcMeshSection* Section;
int RenderMeshIndex;
float Distance;
}; };
class lcScene class lcScene
@ -65,7 +82,9 @@ public:
void DrawInterfaceObjects(lcContext* Context) const; void DrawInterfaceObjects(lcContext* Context) const;
protected: protected:
void DrawPass(lcContext* Context, lcRenderPass RenderPass, int PrimitiveTypes) const; void DrawOpaqueMeshes(lcContext* Context, bool DrawLit, int PrimitiveTypes) const;
void DrawTranslucentMeshes(lcContext* Context, bool DrawLit) const;
void DrawDebugNormals(lcContext* Context, lcMesh* Mesh) const;
lcMatrix44 mViewMatrix; lcMatrix44 mViewMatrix;
lcMatrix44 mActiveSubmodelTransform; lcMatrix44 mActiveSubmodelTransform;
@ -75,6 +94,6 @@ protected:
lcArray<lcRenderMesh> mRenderMeshes; lcArray<lcRenderMesh> mRenderMeshes;
lcArray<int> mOpaqueMeshes; lcArray<int> mOpaqueMeshes;
lcArray<int> mTranslucentMeshes; lcArray<lcTranslucentMeshInstance> mTranslucentMeshes;
lcArray<const lcObject*> mInterfaceObjects; lcArray<const lcObject*> mInterfaceObjects;
}; };

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
class PieceInfo; class PieceInfo;
enum class lcRenderMeshState : int;
#include "object.h" #include "object.h"
#include "lc_colors.h" #include "lc_colors.h"