Added fog to the collision shader, made changes to enable rendering different collision materials separately (also, murry crimmas)

This commit is contained in:
parax0 2016-12-25 14:47:59 -07:00
parent c0fb54888d
commit 78baa42bce
7 changed files with 118 additions and 34 deletions

View File

@ -9,8 +9,25 @@ out vec4 PixelColor;
// Uniforms
uniform vec4 TintColor;
// Functions
float InterpolateDecelerate(float Min, float Max, float t, float Factor)
{
float Alpha = (1.0 - pow(1.0 - t, Factor));
return mix(Min, Max, Alpha);
}
// Main
void main()
{
PixelColor = LightColor * TintColor;
const float kMaxDepth = 75.0; // Controls the max depth range that kDepthTintNear and kDepthTintFar are interpolated between
const float kDepthTintNear = 0.0; // Sets the pixel color offset for pixels close to the screen
const float kDepthTintFar = -0.2; // Sets the pixel color offset for pixels far from the screen
const float kDepthCurveFactor = 2; // Controls the strength of the interpolation curve (higher = color chabges faster from up close and slower from further away)
// Apply some fake fog so pixels closer to the camera appear slightly brighter
float Depth = ( (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) / (gl_DepthRange.far - gl_DepthRange.near) ) / gl_FragCoord.w;
float DepthAlpha = min(Depth, kMaxDepth) / kMaxDepth;
DepthAlpha = clamp(DepthAlpha, 0.0, 1.0);
float DepthTint = InterpolateDecelerate(kDepthTintNear, kDepthTintFar, DepthAlpha, kDepthCurveFactor);
PixelColor = (LightColor + vec4(DepthTint, DepthTint, DepthTint, 1.0)) * TintColor;
}

View File

@ -18,12 +18,17 @@ layout(std140) uniform MVPBlock
// Main
void main()
{
const vec3 kLightDir = normalize( vec3(0.3, 0, -1) ); // Sets the direction of the light
const float kLightColorMin = 0.5; // Sets the minimum light color (color of a vertex facing away from the light)
const float kLightColorMax = 0.9; // Sets the maximum light color (color of a vertex facing towards the light)
// Calculate vertex position
mat4 MVP = ModelMtx * ViewMtx * ProjMtx;
gl_Position = vec4(RawPosition, 1) * MVP;
// Fake lighting; render one white skylight pointing straight down with an ambient 0.5
float LightDot = dot(RawNormal, vec3(0, 0, -1));
// Apply some simple lighting
float LightDot = dot(RawNormal, kLightDir);
float Alpha = (-LightDot + 1.0) / 2;
float LightAlpha = mix(0.5, 0.9, Alpha);
float LightAlpha = mix(kLightColorMin, kLightColorMax, Alpha);
LightColor = vec4(LightAlpha, LightAlpha, LightAlpha, 1.0);
}

View File

@ -1,6 +1,7 @@
#include "CCollisionMesh.h"
#include "Core/Render/CRenderer.h"
#include "Core/Render/CDrawUtil.h"
#include <Common/Assert.h>
CCollisionMesh::CCollisionMesh()
{
@ -31,20 +32,39 @@ void CCollisionMesh::BufferGL()
mBuffered = false;
}
// Add all the relevant indices to the IBO
mVBO.Reserve(mCollisionFaces.size() * 3);
mIBO.Reserve(mCollisionFaces.size() * 3);
// Create new list of collision faces sorted by material index
std::vector<CCollisionFace> SortedTris = mCollisionFaces;
std::sort(SortedTris.begin(), SortedTris.end(), [](CCollisionFace& rLeft, CCollisionFace& rRight) -> bool {
return rLeft.MaterialIdx < rRight.MaterialIdx;
});
for (u32 iVtx = 0; iVtx < mCollisionFaces.size(); iVtx++)
// Add all the relevant indices to the IBO
mVBO.Reserve(SortedTris.size() * 3);
mIBO.Reserve(SortedTris.size() * 3);
mMaterialOffsets.reserve(mMaterials.size());
u32 CurMat = 0;
for (u32 iTri = 0; iTri < SortedTris.size(); iTri++)
{
u16 Verts[3];
CCollisionFace *pFace = &mCollisionFaces[iVtx];
CCollisionFace *pFace = &SortedTris[iTri];
CCollisionLine *pLineA = GetLine(pFace->Lines[0]);
CCollisionLine *pLineB = GetLine(pFace->Lines[1]);
Verts[0] = pLineA->Vertices[0];
Verts[1] = pLineA->Vertices[1];
// Check if we've reached a new material
if (pFace->MaterialIdx != CurMat)
{
while (CurMat != pFace->MaterialIdx)
{
mMaterialOffsets.push_back(mIBO.GetSize());
CurMat++;
}
}
// We have two vertex indices; the last one is one of the ones on line B, but we're not sure which one
if ((pLineB->Vertices[0] != Verts[0]) &&
(pLineB->Vertices[0] != Verts[1]))
@ -53,7 +73,7 @@ void CCollisionMesh::BufferGL()
Verts[2] = pLineB->Vertices[1];
// Some faces have a property that indicates they need to be inverted
if (pFace->Properties.Invert)
if (GetMaterial(pFace->MaterialIdx).FlippedTri)
{
u16 V0 = Verts[0];
Verts[0] = Verts[2];
@ -79,6 +99,14 @@ void CCollisionMesh::BufferGL()
}
}
while (CurMat != mMaterials.size())
{
mMaterialOffsets.push_back(mIBO.GetSize());
CurMat++;
}
ASSERT(mMaterialOffsets.size() == mMaterials.size());
// Buffer, and done
mVBO.Buffer();
mIBO.Buffer();
@ -94,6 +122,18 @@ void CCollisionMesh::Draw()
mVBO.Unbind();
}
void CCollisionMesh::DrawMaterial(u32 MatIdx)
{
if (!mBuffered) BufferGL();
ASSERT(MatIdx < mMaterials.size());
mVBO.Bind();
u32 StartIdx = (MatIdx == 0 ? 0 : mMaterialOffsets[MatIdx - 1]);
u32 NumElements = mMaterialOffsets[MatIdx] - StartIdx;
mIBO.DrawElements(StartIdx, NumElements);
mVBO.Unbind();
}
void CCollisionMesh::DrawWireframe()
{
CDrawUtil::UseColorShader(CColor::skBlack);

View File

@ -6,6 +6,17 @@
#include "Core/OpenGL/CIndexBuffer.h"
#include <Math/CAABox.h>
struct SCollisionMaterial
{
// todo: figure out what the other properties are
u64 RawFlags;
bool AiWalkThru;
bool FlippedTri;
bool ShootThru;
bool CameraThru;
bool Solid;
};
class CCollisionMesh
{
friend class CCollisionLoader;
@ -30,30 +41,24 @@ class CCollisionMesh
SOctreeNode* mpRoot;
};
struct SCollisionProperties
{
// todo: figure out what the other properties are
bool Invert;
};
class CCollisionVertex
{
public:
SCollisionProperties Properties;
u32 MaterialIdx;
CVector3f Pos;
};
class CCollisionLine
{
public:
SCollisionProperties Properties;
u32 MaterialIdx;
u16 Vertices[2];
};
class CCollisionFace
{
public:
SCollisionProperties Properties;
u32 MaterialIdx;
u16 Lines[3];
};
@ -66,10 +71,11 @@ class CCollisionMesh
CAABox mAABox;
CCollisionOctree *mpOctree;
std::vector<u32> mFlags;
std::vector<SCollisionMaterial> mMaterials;
std::vector<CCollisionVertex> mCollisionVertices;
std::vector<CCollisionLine> mCollisionLines;
std::vector<CCollisionFace> mCollisionFaces;
std::vector<u32> mMaterialOffsets;
bool mOctreeLoaded;
CCollisionVertex *GetVertex(u16 Index);
@ -82,7 +88,11 @@ public:
void BufferGL();
void Draw();
void DrawMaterial(u32 MatIdx);
void DrawWireframe();
inline u32 NumMaterials() const { return mMaterials.size(); }
inline SCollisionMaterial& GetMaterial(u32 Index) { return mMaterials[Index]; }
};
#endif // CCOLLISIONMESH_H

View File

@ -38,27 +38,27 @@ void CCollisionLoader::ParseOBBNode(IInputStream& rDCLN)
void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc)
{
CCollisionMesh::SCollisionProperties Property;
SCollisionMaterial Material;
if (mVersion == ePrime)
{
u32 Flag = rSrc.ReadLong();
Property.Invert = (Flag >> 25) & 0x1;
Material.RawFlags = rSrc.ReadLong();
Material.FlippedTri = (Material.RawFlags >> 25) & 0x1;
}
else if (mVersion == eEchoes)
{
u64 Flag = rSrc.ReadLongLong();
Property.Invert = (Flag >> 24) & 0x1;
Material.RawFlags = rSrc.ReadLongLong();
Material.FlippedTri = (Material.RawFlags >> 24) & 0x1;
}
else if (mVersion == eReturns)
{
u64 Flag = rSrc.ReadLongLong();
Property.Invert = (Flag >> 28) & 0x1;
Material.RawFlags = rSrc.ReadLongLong();
Material.FlippedTri = (Material.RawFlags >> 28) & 0x1;
}
mProperties.push_back(Property);
mpMesh->mMaterials.push_back(Material);
}
void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox)
@ -89,7 +89,7 @@ void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox
CCollisionMesh::CCollisionLine *pLine = &mpMesh->mCollisionLines[iLine];
pLine->Vertices[0] = rFile.ReadShort();
pLine->Vertices[1] = rFile.ReadShort();
pLine->Properties = mProperties[LineIndices[iLine]];
pLine->MaterialIdx = LineIndices[iLine];
}
// Faces
@ -102,7 +102,7 @@ void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox
pFace->Lines[0] = rFile.ReadShort();
pFace->Lines[1] = rFile.ReadShort();
pFace->Lines[2] = rFile.ReadShort();
pFace->Properties = mProperties[FaceIndices[iFace]];
pFace->MaterialIdx = FaceIndices[iFace];
}
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
@ -121,7 +121,7 @@ void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox
{
CCollisionMesh::CCollisionVertex *pVtx = &mpMesh->mCollisionVertices[iVtx];
pVtx->Pos = CVector3f(rFile);
pVtx->Properties = mProperties[VtxIndices[iVtx]];
pVtx->MaterialIdx = VtxIndices[iVtx];
if (BuildAABox) Bounds.ExpandBounds(pVtx->Pos);
}
if (BuildAABox) mpMesh->mAABox = Bounds;

View File

@ -10,7 +10,6 @@ class CCollisionLoader
TResPtr<CCollisionMeshGroup> mpGroup;
CCollisionMesh *mpMesh;
EGame mVersion;
std::vector<CCollisionMesh::SCollisionProperties> mProperties;
CCollisionLoader();
CCollisionMesh::CCollisionOctree* ParseOctree(IInputStream& rSrc);

View File

@ -37,8 +37,21 @@ void CCollisionNode::Draw(FRenderOptions /*Options*/, int /*ComponentIndex*/, ER
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
CDrawUtil::UseCollisionShader(TintColor(rkViewInfo));
mpCollision->Draw();
CColor BaseTint = TintColor(rkViewInfo);
for (u32 iMesh = 0; iMesh < mpCollision->NumMeshes(); iMesh++)
{
CCollisionMesh *pMesh = mpCollision->MeshByIndex(iMesh);
for (u32 iMat = 0; iMat < pMesh->NumMaterials(); iMat++)
{
CDrawUtil::UseCollisionShader(BaseTint);
pMesh->DrawMaterial(iMat);
}
}
//CDrawUtil::UseColorShader(CColor::skTransparentBlack);
//mpCollision->DrawWireframe();
}
SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay& /*rkRay*/, u32 /*AssetID*/, const SViewInfo& /*rkViewInfo*/)