Skip to content

Commit

Permalink
#5532: IShaderExpression can reproduce a string expression. Better su…
Browse files Browse the repository at this point in the history
…pport for deform keywords in materials.
  • Loading branch information
codereader committed Feb 21, 2021
1 parent 666551c commit 863474b
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 45 deletions.
3 changes: 3 additions & 0 deletions include/ishaderexpression.h
Expand Up @@ -67,6 +67,9 @@ class IShaderExpression
* @returns: the register position the result will be written to.
*/
virtual std::size_t linkToRegister(Registers& registers) = 0;

// Returns the string this expression has been parsed from
virtual std::string getExpressionString() = 0;
};
typedef std::shared_ptr<IShaderExpression> IShaderExpressionPtr;

Expand Down
6 changes: 6 additions & 0 deletions include/ishaders.h
Expand Up @@ -249,6 +249,12 @@ class Material
*/
virtual DeformType getDeformType() const = 0;

// Returns the shader expression used to define the deform parameters (valid indices in [0..2])
virtual shaders::IShaderExpressionPtr getDeformExpression(std::size_t index) = 0;

// Used for Deform_Particle/Particle2 defines the name of the particle def
virtual std::string getDeformDeclName() = 0;

/**
* Returns the spectrum of this shader, 0 is the default value (even witout keyword in the material)
*/
Expand Down
10 changes: 10 additions & 0 deletions radiantcore/shaders/CShader.cpp
Expand Up @@ -167,6 +167,16 @@ Material::DeformType CShader::getDeformType() const
return _template->getDeformType();
}

IShaderExpressionPtr CShader::getDeformExpression(std::size_t index)
{
return _template->getDeformExpression(index);
}

std::string CShader::getDeformDeclName()
{
return _template->getDeformDeclName();
}

int CShader::getSpectrum() const
{
return _template->getSpectrum();
Expand Down
4 changes: 3 additions & 1 deletion radiantcore/shaders/CShader.h
Expand Up @@ -83,7 +83,9 @@ class CShader
SurfaceType getSurfaceType() const;

// Deform types
DeformType getDeformType() const;
DeformType getDeformType() const override;
IShaderExpressionPtr getDeformExpression(std::size_t index) override;
std::string getDeformDeclName() override;

// Get the spectrum, 0 is the default
int getSpectrum() const;
Expand Down
63 changes: 33 additions & 30 deletions radiantcore/shaders/ShaderExpression.cpp
Expand Up @@ -94,15 +94,15 @@ class ShaderExpressionParser
private:
ShaderExpressionTokeniser& _tokeniser;

typedef std::stack<IShaderExpressionPtr> OperandStack;
typedef std::stack<BinaryExpressionPtr> OperatorStack;
using OperandStack = std::stack<std::shared_ptr<ShaderExpression>>;
using OperatorStack = std::stack<BinaryExpressionPtr>;

public:
ShaderExpressionParser(ShaderExpressionTokeniser& tokeniser) :
_tokeniser(tokeniser)
{}

IShaderExpressionPtr getExpression()
std::shared_ptr<ShaderExpression> getExpression()
{
// The local variable and operator stack
OperandStack operands;
Expand All @@ -118,14 +118,17 @@ class ShaderExpressionParser
std::string token = _tokeniser.peek();

// Get a new term, push it on the stack
IShaderExpressionPtr term;
std::shared_ptr<ShaderExpression> term;

if (token == "(")
{
_tokeniser.nextToken(); // valid token, exhaust

// New scope, treat this as new expression
term = getExpression();

// Remember that this term had parentheses around it
term->setIsSurroundedByParentheses(true);
}
else if (token == ")" || token == "]")
{
Expand Down Expand Up @@ -171,8 +174,8 @@ class ShaderExpressionParser
else if (token == "-")
{
// A leading -, interpret it as -1 *
operands.push(IShaderExpressionPtr(new ConstantExpression(-1)));
operators.push(BinaryExpressionPtr(new MultiplyExpression));
operands.push(std::make_shared<ConstantExpression>(-1.0f));
operators.push(std::make_shared<MultiplyExpression>());

// Discard the - operator
continue;
Expand Down Expand Up @@ -219,7 +222,7 @@ class ShaderExpressionParser
throw parser::ParseException("Missing expression");
}

IShaderExpressionPtr rv = operands.top();
auto rv = operands.top();
operands.pop();

assert(operands.empty()); // there should be nothing left on the stack
Expand Down Expand Up @@ -254,7 +257,7 @@ class ShaderExpressionParser

// Try to get a valid expression from the token. If the token was found to be valid
// The token is actually pulled from the tokeniser using nextToken()
IShaderExpressionPtr getTerm(const std::string& token)
std::shared_ptr<ShaderExpression> getTerm(const std::string& token)
{
if (string::istarts_with(token, "parm"))
{
Expand All @@ -265,7 +268,7 @@ class ShaderExpressionParser

if (shaderParmNum >= 0 && shaderParmNum <= MAX_SHADERPARM_INDEX)
{
return IShaderExpressionPtr(new ShaderParmExpression(shaderParmNum));
return std::make_shared<ShaderParmExpression>(shaderParmNum);
}
else
{
Expand All @@ -281,7 +284,7 @@ class ShaderExpressionParser

if (shaderParmNum >= 0 && shaderParmNum <= MAX_GLOBAL_SHADERPARM_INDEX)
{
return IShaderExpressionPtr(new GlobalShaderParmExpression(shaderParmNum));
return std::make_shared<GlobalShaderParmExpression>(shaderParmNum);
}
else
{
Expand All @@ -292,21 +295,21 @@ class ShaderExpressionParser
{
_tokeniser.nextToken(); // valid token, exhaust

return IShaderExpressionPtr(new TimeExpression);
return std::make_shared<TimeExpression>();
}
else if (token == "sound")
{
_tokeniser.nextToken(); // valid token, exhaust

// No sound support so far
return IShaderExpressionPtr(new ConstantExpression(0));
return std::make_shared<ConstantExpression>(0.0f);
}
else if (string::iequals("fragmentprograms", token))
{
_tokeniser.nextToken(); // valid token, exhaust

// There's no fragmentPrograms option in DR, let's assume true
return IShaderExpressionPtr(new ConstantExpression(1));
return std::make_shared<ConstantExpression>(1.0f);
}
else
{
Expand All @@ -322,15 +325,15 @@ class ShaderExpressionParser
_tokeniser.assertNextToken("[");

// The lookup expression itself has to be parsed afresh, enter recursion
IShaderExpressionPtr lookupValue = getExpression();
auto lookupValue = getExpression();

if (lookupValue == NULL)
{
throw new parser::ParseException("Missing or invalid expression in table lookup operator[]");
}

// Construct a new table lookup expression and link them together
return IShaderExpressionPtr(new TableLookupExpression(table, lookupValue));
return std::make_shared<TableLookupExpression>(table, lookupValue);
}
else
{
Expand All @@ -341,70 +344,70 @@ class ShaderExpressionParser

_tokeniser.nextToken(); // valid token, exhaust

return IShaderExpressionPtr(new ConstantExpression(value));
return std::make_shared<ConstantExpression>(value);
}
catch (std::invalid_argument&)
{}
}
}

return IShaderExpressionPtr();
return std::shared_ptr<ShaderExpression>();
}

// Helper routines
BinaryExpressionPtr getOperatorForToken(const std::string& token)
{
if (token == "+")
{
return BinaryExpressionPtr(new AddExpression);
return std::make_shared<AddExpression>();
}
else if (token == "-")
{
return BinaryExpressionPtr(new SubtractExpression);
return std::make_shared<SubtractExpression>();
}
else if (token == "*")
{
return BinaryExpressionPtr(new MultiplyExpression);
return std::make_shared<MultiplyExpression>();
}
else if (token == "/")
{
return BinaryExpressionPtr(new DivideExpression);
return std::make_shared<DivideExpression>();
}
else if (token == "%")
{
return BinaryExpressionPtr(new ModuloExpression);
return std::make_shared<ModuloExpression>();
}
else if (token == "<")
{
return BinaryExpressionPtr(new LesserThanExpression);
return std::make_shared<LesserThanExpression>();
}
else if (token == "<=")
{
return BinaryExpressionPtr(new LesserThanOrEqualExpression);
return std::make_shared<LesserThanOrEqualExpression>();
}
else if (token == ">")
{
return BinaryExpressionPtr(new GreaterThanExpression);
return std::make_shared<GreaterThanExpression>();
}
else if (token == ">=")
{
return BinaryExpressionPtr(new GreaterThanOrEqualExpression);
return std::make_shared<GreaterThanOrEqualExpression>();
}
else if (token == "==")
{
return BinaryExpressionPtr(new EqualityExpression);
return std::make_shared<EqualityExpression>();
}
else if (token == "!=")
{
return BinaryExpressionPtr(new InequalityExpression);
return std::make_shared<InequalityExpression>();
}
else if (token == "&&")
{
return BinaryExpressionPtr(new LogicalAndExpression);
return std::make_shared<LogicalAndExpression>();
}
else if (token == "||")
{
return BinaryExpressionPtr(new LogicalOrExpression);
return std::make_shared<LogicalOrExpression>();
}

return BinaryExpressionPtr();
Expand Down

0 comments on commit 863474b

Please sign in to comment.