Implemented shader-side recoloring in HSV and added more material tags

dev
Tomasz Kapuściński 2022-06-18 22:18:25 +02:00
parent 7d31b1e55d
commit a88d9cdd39
11 changed files with 179 additions and 15 deletions

View File

@ -74,6 +74,8 @@ struct Material
CullFace cullFace = CullFace::BACK;
// Special tag
std::string tag = "";
// Recolor reference color
Color recolorReference = { 0.0f, 0.0f, 0.0f, 0.0f };
// Legacy functionality
//! Variable detail texture
@ -95,6 +97,7 @@ struct Material
&& alphaThreshold == other.alphaThreshold
&& cullFace == other.cullFace
&& tag == other.tag
&& recolorReference == other.recolorReference
&& variableDetail == other.variableDetail
&& detailTexture == other.detailTexture;
}

View File

@ -198,6 +198,9 @@ public:
//! Sets alpha scissor
virtual void SetAlphaScissor(float alpha) = 0;
//! Sets recolor parameters
virtual void SetRecolor(bool enabled, const glm::vec3& from = {}, const glm::vec3& to = {}, float threshold = {}) = 0;
//! Sets depth test
virtual void SetDepthTest(bool enabled) = 0;
//! Sets depth mask

View File

@ -2374,11 +2374,6 @@ 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;
@ -2946,9 +2941,54 @@ void CEngine::Draw3DScene()
Color color = data.material.albedoColor;
bool recolor = false;
Color recolorFrom = {};
Color recolorTo = {};
float recolorTreshold = 0.0;
if (data.material.tag == "team")
{
color = m_teamColors[m_objects[objRank].team];
color = CRobotMain::GetInstance().GetTeamColor(m_objects[objRank].team);
}
else if (data.material.tag == "vehicle")
{
color = CRobotMain::GetInstance().GetVehicleColor();
}
else if (data.material.tag == "plant")
{
color = CRobotMain::GetInstance().GetGreeneryColor();
}
else if (data.material.tag == "alien")
{
color = CRobotMain::GetInstance().GetAlienColor();
}
else if (data.material.tag == "recolor_team")
{
recolor = true;
recolorFrom = data.material.recolorReference;
recolorTo = CRobotMain::GetInstance().GetTeamColor(m_objects[objRank].team);
recolorTreshold = 0.1;
}
else if (data.material.tag == "recolor_vehicle")
{
recolor = true;
recolorFrom = data.material.recolorReference;
recolorTo = CRobotMain::GetInstance().GetVehicleColor();
recolorTreshold = 0.1;
}
else if (data.material.tag == "recolor_plant")
{
recolor = true;
recolorFrom = data.material.recolorReference;
recolorTo = CRobotMain::GetInstance().GetGreeneryColor();
recolorTreshold = 0.1;
}
else if (data.material.tag == "recolor_alien")
{
recolor = true;
recolorFrom = data.material.recolorReference;
recolorTo = CRobotMain::GetInstance().GetAlienColor();
recolorTreshold = 0.1;
}
objectRenderer->SetAlbedoColor(color);
@ -2961,6 +3001,8 @@ void CEngine::Draw3DScene()
objectRenderer->SetMaterialParams(data.material.roughness, data.material.metalness, data.material.aoStrength);
objectRenderer->SetMaterialTexture(data.materialTexture);
objectRenderer->SetRecolor(recolor, recolorFrom, recolorTo, recolorTreshold);
objectRenderer->SetCullFace(data.material.cullFace);
objectRenderer->SetUVTransform(data.uvOffset, data.uvScale);
objectRenderer->DrawObject(data.buffer);

View File

@ -827,8 +827,6 @@ 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

View File

@ -209,6 +209,17 @@ void GLTFLoader::ReadMaterials()
mat.tag = extras["tag"].get<std::string>();
}
if (extras.contains("recolor_ref"))
{
const auto& color = extras["recolor_ref"];
float r = color[0];
float g = color[1];
float b = color[2];
mat.recolorReference = Color(r, g, b);
}
if (extras.contains("energy"))
{
if (extras["energy"].get<int>() != 0)

View File

@ -97,6 +97,12 @@ CGL33ObjectRenderer::CGL33ObjectRenderer(CGL33Device* device)
m_triplanarMode = glGetUniformLocation(m_program, "uni_TriplanarMode");
m_triplanarScale = glGetUniformLocation(m_program, "uni_TriplanarScale");
m_alphaScissor = glGetUniformLocation(m_program, "uni_AlphaScissor");
m_recolor = glGetUniformLocation(m_program, "uni_Recolor");
m_recolorFrom = glGetUniformLocation(m_program, "uni_RecolorFrom");
m_recolorTo = glGetUniformLocation(m_program, "uni_RecolorTo");
m_recolorThreshold = glGetUniformLocation(m_program, "uni_RecolorThreshold");
m_uvOffset = glGetUniformLocation(m_program, "uni_UVOffset");
m_uvScale = glGetUniformLocation(m_program, "uni_UVScale");
@ -211,6 +217,7 @@ void CGL33ObjectRenderer::CGL33ObjectRenderer::Begin()
SetEmissiveColor({ 0, 0, 0, 0 });
SetAlbedoColor({ 1, 1, 1, 1 });
SetMaterialParams(1.0, 0.0, 0.0);
SetRecolor(false);
}
void CGL33ObjectRenderer::CGL33ObjectRenderer::End()
@ -427,6 +434,21 @@ void CGL33ObjectRenderer::SetAlphaScissor(float alpha)
glUniform1f(m_alphaScissor, alpha);
}
void CGL33ObjectRenderer::SetRecolor(bool enabled, const glm::vec3& from, const glm::vec3& to, float threshold)
{
glUniform1i(m_recolor, enabled ? 1 : 0);
if (enabled)
{
auto fromHSV = RGB2HSV(Color(from.r, from.g, from.b, 1.0));
auto toHSV = RGB2HSV(Color(to.r, to.g, to.b, 1.0));
glUniform3f(m_recolorFrom, fromHSV.h, fromHSV.s, fromHSV.v);
glUniform3f(m_recolorTo, toHSV.h, toHSV.s, toHSV.v);
glUniform1f(m_recolorThreshold, threshold);
}
}
void CGL33ObjectRenderer::DrawObject(const CVertexBuffer* buffer)
{
auto b = dynamic_cast<const CGL33VertexBuffer*>(buffer);

View File

@ -86,6 +86,9 @@ public:
//! Sets alpha scissor
virtual void SetAlphaScissor(float alpha) override;
//! Sets recolor parameters
virtual void SetRecolor(bool enabled, const glm::vec3& from = {}, const glm::vec3& to = {}, float threshold = {}) override;
virtual void SetDepthTest(bool enabled) override;
virtual void SetDepthMask(bool enabled) override;
@ -141,6 +144,11 @@ private:
GLint m_triplanarScale = -1;
GLint m_alphaScissor = -1;
GLint m_recolor = -1;
GLint m_recolorFrom = -1;
GLint m_recolorTo = -1;
GLint m_recolorThreshold = -1;
GLint m_uvOffset = -1;
GLint m_uvScale = -1;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see http://gnu.org/licenses
*/
// FRAGMENT SHADER - TERRAIN RENDERER
// FRAGMENT SHADER - OBJECT RENDERER
uniform vec2 uni_FogRange;
uniform vec3 uni_FogColor;
@ -39,6 +39,11 @@ uniform float uni_TriplanarScale;
uniform float uni_AlphaScissor;
uniform bool uni_Recolor;
uniform vec3 uni_RecolorFrom;
uniform vec3 uni_RecolorTo;
uniform float uni_RecolorThreshold;
in VertexData
{
vec4 Color;
@ -64,11 +69,48 @@ vec3 Triplanar(vec3 position, vec3 normal)
return sum;
}
// All components are in the range [0...1], including hue.
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// All components are in the range [0...1], including hue.
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void main()
{
vec4 albedo = data.Color * uni_AlbedoColor;
albedo *= texture(uni_AlbedoTexture, data.TexCoord0);
vec4 texColor = texture(uni_AlbedoTexture, data.TexCoord0);
if (uni_Recolor)
{
vec3 hsv = rgb2hsv(texColor.rgb);
if (abs(hsv.x - uni_RecolorFrom.x) < uni_RecolorThreshold)
{
hsv += (uni_RecolorTo - uni_RecolorFrom);
if (hsv.x < 0.0) hsv.x += 1.0;
if (hsv.x > 1.0) hsv.x -= 1.0;
}
texColor.rgb = hsv2rgb(hsv);
}
albedo *= texColor;
vec3 dirty = vec3(0.0);

View File

@ -17,7 +17,7 @@
* along with this program. If not, see http://gnu.org/licenses
*/
// VERTEX SHADER - TERRAIN RENDERER
// VERTEX SHADER - OBJECT RENDERER
uniform mat4 uni_ProjectionMatrix;
uniform mat4 uni_ViewMatrix;

View File

@ -4036,10 +4036,6 @@ void CRobotMain::ChangeColor()
{
int team = it.first;
Gfx::Color newColor = it.second;
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);
@ -6000,6 +5996,34 @@ void CRobotMain::MarkResearchDone(ResearchType type, int team)
}
}
const Gfx::Color& CRobotMain::GetTeamColor(int team)
{
if (m_colorNewBot.count(team) > 0)
return m_colorNewBot.at(team);
else
return m_colorNewBot.at(0);
}
const Gfx::Color& CRobotMain::GetVehicleColor()
{
return m_colorNewBot.at(0);
}
const Gfx::Color& CRobotMain::GetAlienColor()
{
return m_colorNewAlien;
}
const Gfx::Color& CRobotMain::GetGreeneryColor()
{
return m_colorNewGreen;
}
const Gfx::Color& CRobotMain::GetWaterColor()
{
return m_colorNewWater;
}
Error CRobotMain::CanBuildError(ObjectType type, int team)
{
if(!IsBuildingEnabled(type)) return ERR_BUILD_DISABLED;

View File

@ -440,6 +440,17 @@ public:
//! \brief Mark given research as done
void MarkResearchDone(ResearchType type, int team);
//! \brief Returns a color associated with a team or vehicle color if none defined
const Gfx::Color& GetTeamColor(int team);
//! \brief Returns vehicle color
const Gfx::Color& GetVehicleColor();
//! \brief Returns alien color
const Gfx::Color& GetAlienColor();
//! \brief Returns plant color
const Gfx::Color& GetGreeneryColor();
//! \brief Returns water color
const Gfx::Color& GetWaterColor();
/**
* \brief Check if all requirements to build this object are met (EnableBuild + DoneResearch)
* \return true if the building can be built, false otherwise