Skip to content

Commit

Permalink
#5567: Implement adding frob stages
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Apr 2, 2021
1 parent f2b17e6 commit 33fcbc4
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 10 deletions.
68 changes: 61 additions & 7 deletions libs/materials/FrobStageSetup.h
@@ -1,5 +1,6 @@
#pragma once

#include "i18n.h"
#include "ishaders.h"
#include "ishaderlayer.h"

Expand All @@ -26,6 +27,14 @@ namespace shaders
* rgb 0.15 * parm11
* }
*/

constexpr const char* const FrobCondition = "(parm11 > 0.0)";
constexpr const char* const AdditiveRgbExpression = "0.15 * parm11";
constexpr const char* const WhiteBlendRgbExpression = "0.4 * parm11";
constexpr const char* const WhiteBlendFuncSrc = "gl_dst_color";
constexpr const char* const WhiteBlendFuncDest = "gl_one";
constexpr const char* const WhiteBlendMap = "_white";

class FrobStageSetup
{
public:
Expand All @@ -34,27 +43,27 @@ class FrobStageSetup
for (const auto& layer : material->getAllLayers())
{
// if ( parm11 > 0 )
if (!layer->getConditionExpression() || layer->getConditionExpression()->getExpressionString() != "(parm11 > 0.0)")
if (!layer->getConditionExpression() || layer->getConditionExpression()->getExpressionString() != FrobCondition)
{
continue;
}

// blend gl_dst_color, gl_one
if (layer->getBlendFuncStrings().first != "gl_dst_color" || layer->getBlendFuncStrings().second != "gl_one")
if (layer->getBlendFuncStrings().first != WhiteBlendFuncSrc || layer->getBlendFuncStrings().second != WhiteBlendFuncDest)
{
continue;
}

// map _white
if (!layer->getMapExpression() || layer->getMapExpression()->getExpressionString() != "_white")
if (!layer->getMapExpression() || layer->getMapExpression()->getExpressionString() != WhiteBlendMap)
{
continue;
}

// rgb 0.40 * parm11
auto rgb = layer->getColourExpression(IShaderLayer::COMP_RGB);

if (rgb && rgb->getExpressionString() == "0.4 * parm11")
if (rgb && rgb->getExpressionString() == WhiteBlendRgbExpression)
{
return true;
}
Expand All @@ -72,7 +81,7 @@ class FrobStageSetup
for (const auto& layer : material->getAllLayers())
{
// if ( parm11 > 0 )
if (!layer->getConditionExpression() || layer->getConditionExpression()->getExpressionString() != "(parm11 > 0.0)")
if (!layer->getConditionExpression() || layer->getConditionExpression()->getExpressionString() != FrobCondition)
{
continue;
}
Expand All @@ -92,7 +101,7 @@ class FrobStageSetup
// rgb 0.15 * parm11
auto rgb = layer->getColourExpression(IShaderLayer::COMP_RGB);

if (rgb && rgb->getExpressionString() == "0.15 * parm11")
if (rgb && rgb->getExpressionString() == AdditiveRgbExpression)
{
return true;
}
Expand All @@ -111,7 +120,22 @@ class FrobStageSetup
return !diffuse.empty() && HasWhiteBlendStage(material) && HasAdditiveDiffuseStage(material);
}

private:
// Add the needed frob stages to this material
static void AddToMaterial(const MaterialPtr& material)
{
if (!material) return;

if (!HasAdditiveDiffuseStage(material))
{
AddAdditiveDiffuseStage(material);
}

if (!HasWhiteBlendStage(material))
{
AddWhiteBlendStage(material);
}
}

static std::string GetDiffuseMap(const MaterialPtr& material)
{
for (const auto& layer : material->getAllLayers())
Expand All @@ -124,6 +148,36 @@ class FrobStageSetup

return std::string();
}

private:
static void AddAdditiveDiffuseStage(const MaterialPtr& material)
{
auto index = material->addLayer(IShaderLayer::BLEND);
auto stage = material->getEditableLayer(index);

auto diffuse = GetDiffuseMap(material);

if (diffuse.empty())
{
throw std::runtime_error(_("No diffusemap present, cannot add the frob stages."));
}

stage->setConditionExpressionFromString(FrobCondition);
stage->setBlendFuncStrings({ "add", "" });
stage->setMapExpressionFromString(diffuse);
stage->setColourExpressionFromString(IShaderLayer::COMP_RGB, AdditiveRgbExpression);
}

static void AddWhiteBlendStage(const MaterialPtr& material)
{
auto index = material->addLayer(IShaderLayer::BLEND);
auto stage = material->getEditableLayer(index);

stage->setConditionExpressionFromString(FrobCondition);
stage->setBlendFuncStrings({ WhiteBlendFuncSrc, WhiteBlendFuncDest });
stage->setMapExpressionFromString(WhiteBlendMap);
stage->setColourExpressionFromString(IShaderLayer::COMP_RGB, WhiteBlendRgbExpression);
}
};

}
30 changes: 27 additions & 3 deletions radiant/ui/materials/editor/MaterialEditor.cpp
Expand Up @@ -1624,7 +1624,8 @@ void MaterialEditor::updateBasicFrobStageControls()
bool hasFrobStages = shaders::FrobStageSetup::IsPresent(_material);
bool materialCanBeModified = _material && GlobalMaterialManager().materialCanBeModified(_material->getName());

addFrob->Enable(materialCanBeModified && !hasFrobStages);
// We can add the frob stage if a diffuse map is present
addFrob->Enable(materialCanBeModified && !hasFrobStages && !shaders::FrobStageSetup::GetDiffuseMap(_material).empty());
removeFrob->Enable(materialCanBeModified && hasFrobStages);

auto testFrob = getControl<wxButton>("BasicTestFrobStages");
Expand Down Expand Up @@ -2593,7 +2594,18 @@ void MaterialEditor::_onBasicAddFrobStages(wxCommandEvent& ev)
return;
}

// TODO
try
{
shaders::FrobStageSetup::AddToMaterial(_material);
}
catch (const std::runtime_error& ex)
{
wxutil::Messagebox::ShowError(ex.what(), this);
rError() << ex.what() << std::endl;
}

updateMaterialPropertiesFromMaterial();
onMaterialChanged();
}

void MaterialEditor::_onBasicRemoveFrobStages(wxCommandEvent& ev)
Expand All @@ -2603,7 +2615,19 @@ void MaterialEditor::_onBasicRemoveFrobStages(wxCommandEvent& ev)
return;
}

// TODO
try
{
// TODO
//shaders::FrobStageSetup::RemoveFromMaterial(_material);
}
catch (const std::runtime_error& ex)
{
wxutil::Messagebox::ShowError(ex.what(), this);
rError() << ex.what() << std::endl;
}

updateMaterialPropertiesFromMaterial();
onMaterialChanged();
}

void MaterialEditor::_onBasicTestFrobStages(wxMouseEvent& ev)
Expand Down
39 changes: 39 additions & 0 deletions test/Materials.cpp
Expand Up @@ -1435,4 +1435,43 @@ TEST_F(MaterialsTest, MaterialFrobStageDetection)
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));
}

TEST_F(MaterialsTest, MaterialFrobStageAddition)
{
auto material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing1");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));

shaders::FrobStageSetup::AddToMaterial(material);
EXPECT_TRUE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing2");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));

shaders::FrobStageSetup::AddToMaterial(material);
EXPECT_TRUE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing3");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));

shaders::FrobStageSetup::AddToMaterial(material);
EXPECT_TRUE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing4");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));

// Throws because there's no diffuse
EXPECT_THROW(shaders::FrobStageSetup::AddToMaterial(material), std::runtime_error);
EXPECT_FALSE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing5");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));

shaders::FrobStageSetup::AddToMaterial(material);
EXPECT_TRUE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));
}

}

0 comments on commit 33fcbc4

Please sign in to comment.