Various improvements and fixes

* Added strength parameter for ambient occlusion
* Added proper support for material and emissive textures
* Added team-based recoloring, uses "team" tag
* Changed shadow ranges to make close-up shadows much better
* Fixed background coloring
* Added proper defaulting for glTF values
* Fixed parsing of emissive values
* Added normalization of normals in vertex shaders of object and terrain renderers
dev
Tomasz Kapuściński 2022-04-07 01:11:23 +02:00
parent 4b1b1763df
commit 640cde1653
16 changed files with 203 additions and 60 deletions

View File

@ -56,6 +56,8 @@ struct Material
float roughness = 1.0;
//! Metalness
float metalness = 0.0;
//! AO strength
float aoStrength = 0.0;
//! AO-roughness-metalness texture
std::string materialTexture = "";
//! Emissive color

View File

@ -110,7 +110,7 @@ public:
//! Sets emissive texture
virtual void SetEmissiveTexture(const Texture& texture) = 0;
//! Sets material parameters
virtual void SetMaterialParams(float roughness, float metalness) = 0;
virtual void SetMaterialParams(float roughness, float metalness, float aoStrength) = 0;
//! Sets material texture
virtual void SetMaterialTexture(const Texture& texture) = 0;
@ -162,7 +162,7 @@ public:
//! Sets emissive texture
virtual void SetEmissiveTexture(const Texture& texture) = 0;
//! Sets material parameters
virtual void SetMaterialParams(float roughness, float metalness) = 0;
virtual void SetMaterialParams(float roughness, float metalness, float aoStrength) = 0;
//! Sets material texture
virtual void SetMaterialTexture(const Texture& texture) = 0;

View File

@ -963,6 +963,13 @@ void CEngine::SetObjectDrawWorld(int objRank, bool draw)
m_objects[objRank].drawWorld = draw;
}
void CEngine::SetObjectTeam(int objRank, int team)
{
assert(objRank >= 0 && objRank < static_cast<int>(m_objects.size()));
m_objects[objRank].team = team;
}
void CEngine::SetObjectDrawFront(int objRank, bool draw)
{
assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
@ -1977,6 +1984,28 @@ bool CEngine::LoadAllTextures()
if (!data.detailTexture.Valid())
ok = false;
}
if (!data.material.materialTexture.empty())
{
if (terrain)
data.materialTexture = LoadTexture("textures/" + data.material.materialTexture, m_terrainTexParams);
else
data.materialTexture = LoadTexture("textures/" + data.material.materialTexture);
if (!data.materialTexture.Valid())
ok = false;
}
if (!data.material.emissiveTexture.empty())
{
if (terrain)
data.emissiveTexture = LoadTexture("textures/" + data.material.emissiveTexture, m_terrainTexParams);
else
data.emissiveTexture = LoadTexture("textures/" + data.material.emissiveTexture);
if (!data.emissiveTexture.Valid())
ok = false;
}
}
}
@ -2323,6 +2352,11 @@ void CEngine::SetOverColor(const Color& color, TransparencyMode mode)
m_overMode = mode;
}
void CEngine::SetTeamColor(int team, const Color& color)
{
m_teamColors[team] = color;
}
void CEngine::SetParticleDensity(float value)
{
if (value < 0.0f) value = 0.0f;
@ -2798,7 +2832,7 @@ void CEngine::Draw3DScene()
terrainRenderer->SetEmissiveColor(data.material.emissiveColor);
terrainRenderer->SetEmissiveTexture(data.emissiveTexture);
terrainRenderer->SetMaterialParams(data.material.roughness, data.material.metalness);
terrainRenderer->SetMaterialParams(data.material.roughness, data.material.metalness, data.material.aoStrength);
terrainRenderer->SetMaterialTexture(data.materialTexture);
terrainRenderer->DrawObject(m_objects[objRank].transform, data.buffer);
@ -2888,14 +2922,21 @@ void CEngine::Draw3DScene()
objectRenderer->SetAlphaScissor(0.0f);
}
objectRenderer->SetAlbedoColor(data.material.albedoColor);
Color recolor = Color(1.0, 1.0, 1.0, 1.0);
if (data.material.tag == "team")
{
recolor = m_teamColors[m_objects[objRank].team];
}
objectRenderer->SetAlbedoColor(data.material.albedoColor * recolor);
objectRenderer->SetAlbedoTexture(data.albedoTexture);
objectRenderer->SetDetailTexture(data.detailTexture);
objectRenderer->SetEmissiveColor(data.material.emissiveColor);
objectRenderer->SetEmissiveTexture(data.emissiveTexture);
objectRenderer->SetMaterialParams(data.material.roughness, data.material.metalness);
objectRenderer->SetMaterialParams(data.material.roughness, data.material.metalness, data.material.aoStrength);
objectRenderer->SetMaterialTexture(data.materialTexture);
objectRenderer->SetCullFace(data.material.cullFace);
@ -3289,11 +3330,11 @@ void CEngine::RenderShadowMap()
m_shadowRegions = 4;
m_shadowParams[0].range = 32.0;
m_shadowParams[0].range = 16.0;
m_shadowParams[0].offset = { 0.0, 0.0 };
m_shadowParams[0].scale = { 0.5, 0.5 };
m_shadowParams[1].range = 96.0;
m_shadowParams[1].range = 64.0;
m_shadowParams[1].offset = { 0.5, 0.0 };
m_shadowParams[1].scale = { 0.5, 0.5 };
@ -4150,22 +4191,19 @@ void CEngine::DrawBackgroundGradient(const Color& up, const Color& down)
glm::vec2 p1(0.0f, 0.0f);
glm::vec2 p2(1.0f, 1.0f);
glm::u8vec4 color[3] =
{
{ up.r, up.g, up.b, up.a },
{ down.r, down.g, down.b, down.a },
{ 0, 0, 0, 0 }
};
auto up_int = ColorToIntColor(up);
auto down_int = ColorToIntColor(down);
auto renderer = m_device->GetUIRenderer();
renderer->SetTexture(Texture{});
renderer->SetColor({ 1, 1, 1, 1 });
renderer->SetTransparency(TransparencyMode::NONE);
auto vertices = renderer->BeginPrimitive(PrimitiveType::TRIANGLE_STRIP, 4);
vertices[0] = { { p1.x, p1.y }, {}, color[1] };
vertices[1] = { { p1.x, p2.y }, {}, color[0] };
vertices[2] = { { p2.x, p1.y }, {}, color[1] };
vertices[3] = { { p2.x, p2.y }, {}, color[0] };
vertices[0] = { { p1.x, p1.y }, {}, down_int };
vertices[1] = { { p1.x, p2.y }, {}, up_int };
vertices[2] = { { p2.x, p1.y }, {}, down_int };
vertices[3] = { { p2.x, p2.y }, {}, up_int };
renderer->EndPrimitive();
AddStatisticTriangle(2);
@ -4238,6 +4276,7 @@ void CEngine::DrawBackgroundImage()
}
auto renderer = m_device->GetUIRenderer();
renderer->SetColor({ 1, 1, 1, 1 });
renderer->SetTexture(m_backgroundTex);
renderer->SetTransparency(TransparencyMode::NONE);
auto vertices = renderer->BeginPrimitive(PrimitiveType::TRIANGLE_STRIP, 4);
@ -4602,7 +4641,15 @@ void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<Gfx::ModelT
vertices[2] = triangle.p3;
Material material = triangle.material;
material.albedoTexture = "objects/" + material.albedoTexture;
if (!material.albedoTexture.empty())
material.albedoTexture = "objects/" + material.albedoTexture;
if (!material.materialTexture.empty())
material.materialTexture = "objects/" + material.materialTexture;
if (!material.emissiveTexture.empty())
material.emissiveTexture = "objects/" + material.emissiveTexture;
if (material.variableDetail)
material.detailTexture = GetSecondTexture();

View File

@ -136,6 +136,8 @@ struct EngineObject
int shadowRank = -1;
//! Ghost mode
bool ghost = false;
//! Team
int team = 0;
//! Loads default values
inline void LoadDefault()
@ -615,6 +617,8 @@ public:
//! Sets the transparency level for given object
void SetObjectGhostMode(int objRank, bool enabled);
//! Sets team for given object
void SetObjectTeam(int objRank, int team);
//! Returns the bounding box for an object
void GetObjectBBox(int objRank, glm::vec3& min, glm::vec3& max);
@ -817,6 +821,8 @@ public:
void SetOverFront(bool front);
//! Sets the foreground overlay color
void SetOverColor(const Color& color, TransparencyMode mode);
//! Sets color for a team
void SetTeamColor(int team, const Color& color);
//@{
//! Management of the particle density
@ -1156,6 +1162,8 @@ protected:
std::vector<EngineGroundSpot> m_groundSpots;
//! Ground mark
EngineGroundMark m_groundMark;
//! Team colors
std::map<int, Color> m_teamColors;
//! Location of camera
glm::vec3 m_eyePt{ 0, 0, 0 };

View File

@ -46,7 +46,7 @@ COldModelManager::~COldModelManager()
{
}
bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int variant)
bool COldModelManager::LoadModel(const std::string& name, bool mirrored, int team)
{
CModel model;
try
@ -108,7 +108,7 @@ skip:
if (mirrored)
Mirror(modelInfo.triangles);
FileInfo fileInfo(name, mirrored, variant);
FileInfo fileInfo(name, mirrored, team);
m_models[fileInfo] = modelInfo;
m_engine->AddBaseObjTriangles(modelInfo.baseObjRank, modelInfo.triangles);
@ -116,50 +116,52 @@ skip:
return true;
}
bool COldModelManager::AddModelReference(const std::string& fileName, bool mirrored, int objRank, int variant)
bool COldModelManager::AddModelReference(const std::string& fileName, bool mirrored, int objRank, int team)
{
auto it = m_models.find(FileInfo(fileName, mirrored, variant));
auto it = m_models.find(FileInfo(fileName, mirrored, team));
if (it == m_models.end())
{
if (!LoadModel(fileName, mirrored, variant))
if (!LoadModel(fileName, mirrored, team))
return false;
it = m_models.find(FileInfo(fileName, mirrored, variant));
it = m_models.find(FileInfo(fileName, mirrored, team));
}
m_engine->SetObjectBaseRank(objRank, (*it).second.baseObjRank);
m_engine->SetObjectTeam(objRank, team);
return true;
}
bool COldModelManager::AddModelCopy(const std::string& fileName, bool mirrored, int objRank, int variant)
bool COldModelManager::AddModelCopy(const std::string& fileName, bool mirrored, int objRank, int team)
{
auto it = m_models.find(FileInfo(fileName, mirrored, variant));
auto it = m_models.find(FileInfo(fileName, mirrored, team));
if (it == m_models.end())
{
if (!LoadModel(fileName, mirrored, variant))
if (!LoadModel(fileName, mirrored, team))
return false;
it = m_models.find(FileInfo(fileName, mirrored, variant));
it = m_models.find(FileInfo(fileName, mirrored, team));
}
int copyBaseObjRank = m_engine->CreateBaseObject();
m_engine->CopyBaseObject((*it).second.baseObjRank, copyBaseObjRank);
m_engine->SetObjectBaseRank(objRank, copyBaseObjRank);
m_engine->SetObjectTeam(objRank, team);
m_copiesBaseRanks.push_back(copyBaseObjRank);
return true;
}
bool COldModelManager::IsModelLoaded(const std::string& fileName, bool mirrored, int variant)
bool COldModelManager::IsModelLoaded(const std::string& fileName, bool mirrored, int team)
{
return m_models.count(FileInfo(fileName, mirrored, variant)) > 0;
return m_models.count(FileInfo(fileName, mirrored, team)) > 0;
}
int COldModelManager::GetModelBaseObjRank(const std::string& fileName, bool mirrored, int variant)
int COldModelManager::GetModelBaseObjRank(const std::string& fileName, bool mirrored, int team)
{
auto it = m_models.find(FileInfo(fileName, mirrored, variant));
auto it = m_models.find(FileInfo(fileName, mirrored, team));
if (it == m_models.end())
return -1;
@ -176,9 +178,9 @@ void COldModelManager::DeleteAllModelCopies()
m_copiesBaseRanks.clear();
}
void COldModelManager::UnloadModel(const std::string& fileName, bool mirrored, int variant)
void COldModelManager::UnloadModel(const std::string& fileName, bool mirrored, int team)
{
auto it = m_models.find(FileInfo(fileName, mirrored, variant));
auto it = m_models.find(FileInfo(fileName, mirrored, team));
if (it == m_models.end())
return;

View File

@ -58,19 +58,19 @@ public:
~COldModelManager();
//! Loads a model from given file
bool LoadModel(const std::string& fileName, bool mirrored, int variant = 0);
bool LoadModel(const std::string& fileName, bool mirrored, int team = 0);
//! Adds an instance of model to the given object rank as a reference to base object
bool AddModelReference(const std::string& fileName, bool mirrored, int objRank, int variant = 0);
bool AddModelReference(const std::string& fileName, bool mirrored, int objRank, int team = 0);
//! Adds an instance of model to the given object rank as a copy (copied base object)
bool AddModelCopy(const std::string& fileName, bool mirrored, int objRank, int variant = 0);
bool AddModelCopy(const std::string& fileName, bool mirrored, int objRank, int team = 0);
//! Returns true if given model is loaded
bool IsModelLoaded(const std::string& fileName, bool mirrored, int variant = 0);
bool IsModelLoaded(const std::string& fileName, bool mirrored, int team = 0);
//! Returns the rank of base engine object of given loaded model
int GetModelBaseObjRank(const std::string& fileName, bool mirrored, int variant = 0);
int GetModelBaseObjRank(const std::string& fileName, bool mirrored, int team = 0);
//! Deletes all copied objects
void DeleteAllModelCopies();

View File

@ -237,6 +237,38 @@ void GLTFLoader::ReadMaterials()
}
}
if (material.contains("emissiveFactor"))
{
const auto& color = material["emissiveFactor"];
mat.emissiveColor = {
color[0].get<float>(),
color[1].get<float>(),
color[2].get<float>(),
0.0
};
}
else
{
mat.emissiveColor = { 0.0, 0.0, 0.0, 0.0 };
}
if (material.contains("emissiveTexture"))
{
const auto& tex = material["emissiveTexture"];
if (tex.contains("index"))
{
int index = tex["index"].get<int>();
const auto& texture = m_textures[index];
const auto& image = m_images[texture.source];
mat.emissiveTexture = image.uri;
}
}
if (material.contains("pbrMetallicRoughness"))
{
const auto& pbr = material["pbrMetallicRoughness"];
@ -252,6 +284,10 @@ void GLTFLoader::ReadMaterials()
color[3].get<float>()
};
}
else
{
mat.albedoColor = { 1.0, 1.0, 1.0, 1.0 };
}
if (pbr.contains("baseColorTexture"))
{
@ -273,27 +309,23 @@ void GLTFLoader::ReadMaterials()
{
mat.metalness = pbr["metallicFactor"].get<float>();
}
else
{
mat.metalness = 1.0;
}
if (pbr.contains("roughnessFactor"))
{
mat.roughness = pbr["roughnessFactor"].get<float>();
}
if (pbr.contains("emissiveFactor"))
else
{
const auto& color = pbr["emissiveFactor"];
mat.emissiveColor = {
color[0].get<float>(),
color[1].get<float>(),
color[2].get<float>(),
0.0
};
mat.roughness = 1.0;
}
if (pbr.contains("emissiveTextue"))
if (pbr.contains("metallicRoughnessTexture"))
{
const auto& tex = pbr["emissiveTextue"];
const auto& tex = pbr["metallicRoughnessTexture"];
if (tex.contains("index"))
{
@ -303,9 +335,48 @@ void GLTFLoader::ReadMaterials()
const auto& image = m_images[texture.source];
mat.emissiveTexture = image.uri;
mat.materialTexture = image.uri;
}
}
if (pbr.contains("occlusionTexture"))
{
const auto& tex = pbr["occlusionTexture"];
if (tex.contains("index"))
{
int index = tex["index"].get<int>();
const auto& texture = m_textures[index];
const auto& image = m_images[texture.source];
if (tex.contains("strength"))
{
mat.aoStrength = tex["strength"].get<float>();
}
else
{
mat.aoStrength = 1.0f;
}
}
}
}
if (material.contains("normalTexture"))
{
const auto& tex = material["normalTexture"];
if (tex.contains("index"))
{
int index = tex["index"].get<int>();
const auto& texture = m_textures[index];
const auto& image = m_images[texture.source];
mat.normalTexture = image.uri;
}
}
if (material.contains("alphaMode"))

View File

@ -92,6 +92,7 @@ CGL33ObjectRenderer::CGL33ObjectRenderer(CGL33Device* device)
m_emissiveColor = glGetUniformLocation(m_program, "uni_EmissiveColor");
m_roughness = glGetUniformLocation(m_program, "uni_Roughness");
m_metalness = glGetUniformLocation(m_program, "uni_Metalness");
m_aoStrength = glGetUniformLocation(m_program, "uni_AOStrength");
m_triplanarMode = glGetUniformLocation(m_program, "uni_TriplanarMode");
m_triplanarScale = glGetUniformLocation(m_program, "uni_TriplanarScale");
@ -207,6 +208,9 @@ void CGL33ObjectRenderer::CGL33ObjectRenderer::Begin()
SetUVTransform({ 0.0f, 0.0f }, { 1.0f, 1.0f });
SetAlphaScissor(0.0f);
SetFog(1e+6f, 1e+6, {});
SetEmissiveColor({ 0, 0, 0, 0 });
SetAlbedoColor({ 1, 1, 1, 1 });
SetMaterialParams(1.0, 0.0, 0.0);
}
void CGL33ObjectRenderer::CGL33ObjectRenderer::End()
@ -297,10 +301,11 @@ void CGL33ObjectRenderer::SetEmissiveTexture(const Texture& texture)
glBindTexture(GL_TEXTURE_2D, texture.id);
}
void CGL33ObjectRenderer::SetMaterialParams(float roughness, float metalness)
void CGL33ObjectRenderer::SetMaterialParams(float roughness, float metalness, float aoStrength)
{
glUniform1f(m_roughness, roughness);
glUniform1f(m_metalness, metalness);
glUniform1f(m_aoStrength, aoStrength);
}
void CGL33ObjectRenderer::SetMaterialTexture(const Texture& texture)

View File

@ -63,7 +63,7 @@ public:
//! Sets emissive texture
virtual void SetEmissiveTexture(const Texture& texture) override;
//! Sets material parameters
virtual void SetMaterialParams(float roughness, float metalness) override;
virtual void SetMaterialParams(float roughness, float metalness, float aoStrength) override;
//! Sets material texture
virtual void SetMaterialTexture(const Texture& texture) override;
@ -135,6 +135,7 @@ private:
GLint m_emissiveColor = -1;
GLint m_roughness = -1;
GLint m_metalness = -1;
GLint m_aoStrength = -1;
GLint m_triplanarMode = -1;
GLint m_triplanarScale = -1;

View File

@ -335,6 +335,7 @@ CGL33TerrainRenderer::CGL33TerrainRenderer(CGL33Device* device)
m_emissiveColor = glGetUniformLocation(m_program, "uni_EmissiveColor");
m_roughness = glGetUniformLocation(m_program, "uni_Roughness");
m_metalness = glGetUniformLocation(m_program, "uni_Metalness");
m_aoStrength = glGetUniformLocation(m_program, "uni_AOStrength");
m_shadowRegions = glGetUniformLocation(m_program, "uni_ShadowRegions");
@ -520,10 +521,11 @@ void CGL33TerrainRenderer::SetEmissiveTexture(const Texture& texture)
glBindTexture(GL_TEXTURE_2D, texture.id);
}
void CGL33TerrainRenderer::SetMaterialParams(float roughness, float metalness)
void CGL33TerrainRenderer::SetMaterialParams(float roughness, float metalness, float aoStrength)
{
glUniform1f(m_roughness, roughness);
glUniform1f(m_metalness, metalness);
glUniform1f(m_aoStrength, aoStrength);
}
void CGL33TerrainRenderer::SetMaterialTexture(const Texture& texture)

View File

@ -135,7 +135,7 @@ public:
//! Sets emissive texture
virtual void SetEmissiveTexture(const Texture& texture) override;
//! Sets material parameters
virtual void SetMaterialParams(float roughness, float metalness) override;
virtual void SetMaterialParams(float roughness, float metalness, float aoStrength) override;
//! Sets material texture
virtual void SetMaterialTexture(const Texture& texture) override;
@ -182,6 +182,7 @@ private:
GLint m_emissiveColor = -1;
GLint m_roughness = -1;
GLint m_metalness = -1;
GLint m_aoStrength = -1;
struct ShadowUniforms
{

View File

@ -28,6 +28,7 @@ uniform sampler2D uni_DetailTexture;
uniform float uni_Roughness;
uniform float uni_Metalness;
uniform float uni_AOStrength;
uniform sampler2D uni_MaterialTexture;
uniform vec3 uni_EmissiveColor;
@ -97,7 +98,7 @@ void main()
vec3 params = texture(uni_MaterialTexture, data.TexCoord0).xyz;
float ambientOcclusion = params.r;
float ambientOcclusion = 1.0 + uni_AOStrength * (params.r - 1.0);
float roughness = uni_Roughness * params.g;
float metalness = uni_Metalness * params.b;

View File

@ -54,7 +54,7 @@ void main()
data.Color = in_Color;
data.TexCoord0 = in_TexCoord0 * uni_UVScale + uni_UVOffset;
data.TexCoord1 = in_TexCoord1;
data.Normal = mat3(uni_NormalMatrix) * in_Normal;
data.Normal = normalize(mat3(uni_NormalMatrix) * in_Normal);
data.VertexCoord = in_VertexCoord.xyz;
data.VertexNormal = in_Normal;
data.Position = position.xyz;

View File

@ -28,6 +28,7 @@ uniform sampler2D uni_DetailTexture;
uniform float uni_Roughness;
uniform float uni_Metalness;
uniform float uni_AOStrength;
uniform sampler2D uni_MaterialTexture;
uniform vec3 uni_EmissiveColor;
@ -65,7 +66,7 @@ void main()
vec3 params = texture(uni_MaterialTexture, data.TexCoord0).xyz;
float ambientOcclusion = params.r;
float ambientOcclusion = 1.0 + uni_AOStrength * (params.r - 1.0);
float roughness = uni_Roughness * params.g;
float metalness = uni_Metalness * params.b;

View File

@ -49,7 +49,7 @@ void main()
data.Color = in_Color;
data.TexCoord0 = in_TexCoord0;
data.TexCoord1 = in_TexCoord1;
data.Normal = mat3(uni_NormalMatrix) * in_Normal;
data.Normal = normalize(mat3(uni_NormalMatrix) * in_Normal);
//data.Distance = abs(eyeSpace.z);
data.Position = position.xyz;
data.ShadowCoords = ProjectShadows(position.xyz);

View File

@ -4039,6 +4039,8 @@ void CRobotMain::ChangeColor()
std::string teamStr = StrUtils::ToString<int>(team);
if(team == 0) teamStr = "";
m_engine->SetTeamColor(team, newColor);
//m_engine->ChangeTextureColor("textures/objects/base1.png"+teamStr, "textures/objects/base1.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true);
//m_engine->ChangeTextureColor("textures/objects/convert.png"+teamStr, "textures/objects/convert.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true);
//m_engine->ChangeTextureColor("textures/objects/derrick.png"+teamStr, "textures/objects/derrick.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true);