Skip to content

Commit

Permalink
#5532: rotate implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Mar 19, 2021
1 parent 9097ac5 commit 56a3568
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 114 deletions.
1 change: 1 addition & 0 deletions radiantcore/CMakeLists.txt
Expand Up @@ -266,6 +266,7 @@ add_library(radiantcore MODULE
shaders/ShaderLibrary.cpp
shaders/ShaderTemplate.cpp
shaders/TableDefinition.cpp
shaders/TextureMatrix.cpp
shaders/textures/GLTextureManager.cpp
shaders/textures/TextureManipulator.cpp
skins/Doom3SkinCache.cpp
Expand Down
5 changes: 5 additions & 0 deletions radiantcore/shaders/ShaderExpression.cpp
Expand Up @@ -455,4 +455,9 @@ IShaderExpression::Ptr ShaderExpression::createMultiplication(const IShaderExpre
return std::make_shared<expressions::MultiplyExpression>(a, b);
}

IShaderExpression::Ptr ShaderExpression::createTableLookup(const TableDefinitionPtr& table, const IShaderExpression::Ptr& lookup)
{
return std::make_shared<expressions::TableLookupExpression>(table, lookup);
}

} // namespace
1 change: 1 addition & 0 deletions radiantcore/shaders/ShaderExpression.h
Expand Up @@ -97,6 +97,7 @@ class ShaderExpression :
static IShaderExpression::Ptr createConstant(float constantValue);
static IShaderExpression::Ptr createAddition(const IShaderExpression::Ptr& a, const IShaderExpression::Ptr& b);
static IShaderExpression::Ptr createMultiplication(const IShaderExpression::Ptr& a, const IShaderExpression::Ptr& b);
static IShaderExpression::Ptr createTableLookup(const TableDefinitionPtr& table, const IShaderExpression::Ptr& lookup);

virtual std::string getExpressionString() override
{
Expand Down
168 changes: 168 additions & 0 deletions radiantcore/shaders/TextureMatrix.cpp
@@ -0,0 +1,168 @@
#include "TextureMatrix.h"

#include "ShaderExpression.h"
#include "Doom3ShaderSystem.h"

namespace shaders
{

struct TextureMatrix::TemporaryMatrix
{
IShaderExpression::Ptr xx;
IShaderExpression::Ptr yx;
IShaderExpression::Ptr tx;
IShaderExpression::Ptr xy;
IShaderExpression::Ptr yy;
IShaderExpression::Ptr ty;
};

TextureMatrix::TextureMatrix(ExpressionSlots& expressions, Registers& registers) :
_expressions(expressions),
_registers(registers)
{}

void TextureMatrix::setIdentity()
{
// Initialise the texture matrix to identity (set the diagonals to 1)
xx().registerIndex = REG_ONE;
yx().registerIndex = REG_ZERO;
tx().registerIndex = REG_ZERO;
xy().registerIndex = REG_ZERO;
yy().registerIndex = REG_ONE;
ty().registerIndex = REG_ZERO;
}

Matrix4 TextureMatrix::getMatrix4()
{
auto matrix = Matrix4::getIdentity();

matrix.xx() = _registers[xx().registerIndex];
matrix.yx() = _registers[yx().registerIndex];
matrix.tx() = _registers[tx().registerIndex];
matrix.xy() = _registers[xy().registerIndex];
matrix.yy() = _registers[yy().registerIndex];
matrix.ty() = _registers[ty().registerIndex];

return matrix;
}

void TextureMatrix::applyTransformation(const IShaderLayer::Transformation& transformation)
{
TemporaryMatrix matrix;

switch (transformation.type)
{
case IShaderLayer::TransformType::Translate:
matrix.xx = ShaderExpression::createConstant(1);
matrix.yx = ShaderExpression::createConstant(0);
matrix.tx = transformation.expression1;
matrix.xy = ShaderExpression::createConstant(0);
matrix.yy = ShaderExpression::createConstant(1);
matrix.ty = transformation.expression2;
break;
case IShaderLayer::TransformType::Scale:
matrix.xx = transformation.expression1;
matrix.yx = ShaderExpression::createConstant(0);
matrix.tx = ShaderExpression::createConstant(0);
matrix.xy = ShaderExpression::createConstant(0);
matrix.yy = transformation.expression2;
matrix.ty = ShaderExpression::createConstant(0);
break;
case IShaderLayer::TransformType::CenterScale:
matrix.xx = transformation.expression1;
matrix.yx = ShaderExpression::createConstant(0);
matrix.tx = ShaderExpression::createAddition(
ShaderExpression::createConstant(0.5),
ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), transformation.expression1)
);
matrix.xy = ShaderExpression::createConstant(0);
matrix.yy = transformation.expression2;
matrix.ty = ShaderExpression::createAddition(
ShaderExpression::createConstant(0.5),
ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), transformation.expression2)
);
break;
case IShaderLayer::TransformType::Shear:
matrix.xx = ShaderExpression::createConstant(1);
matrix.yx = transformation.expression1;
matrix.tx = ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), transformation.expression1);
matrix.xy = transformation.expression2;
matrix.yy = ShaderExpression::createConstant(1);
matrix.ty = ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), transformation.expression2);
break;
case IShaderLayer::TransformType::Rotate:
{
auto sinTable = GetShaderSystem()->getTableForName("sinTable");
auto cosTable = GetShaderSystem()->getTableForName("cosTable");

if (!sinTable || !cosTable)
{
rWarning() << "Cannot create rotate stage transform without sinTable and cosTable declarations" << std::endl;
break;
}

// sin(expr) and cos(expr) shortcuts
auto sinExpr = ShaderExpression::createTableLookup(sinTable, transformation.expression1);
auto cosExpr = ShaderExpression::createTableLookup(cosTable, transformation.expression1);

matrix.xx = ShaderExpression::createTableLookup(cosTable, transformation.expression1);
matrix.yx = ShaderExpression::createMultiplication(
ShaderExpression::createConstant(-1),
ShaderExpression::createTableLookup(sinTable, transformation.expression1)
);
matrix.tx = ShaderExpression::createAddition(
ShaderExpression::createConstant(0.5),
ShaderExpression::createAddition(
ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), cosExpr),
ShaderExpression::createMultiplication(ShaderExpression::createConstant(+0.5), sinExpr)
)
);
matrix.xy = ShaderExpression::createTableLookup(sinTable, transformation.expression1);
matrix.yy = ShaderExpression::createTableLookup(cosTable, transformation.expression1);
matrix.ty = ShaderExpression::createAddition(
ShaderExpression::createConstant(0.5),
ShaderExpression::createAddition(
ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), sinExpr),
ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), cosExpr)
)
);
break;
}
default:
return;
};

multiplyMatrix(matrix);
}

void TextureMatrix::multiplyMatrix(const TemporaryMatrix& matrix)
{
auto xx = add(multiply(matrix.xx, this->xx()), multiply(matrix.yx, this->xy()));
auto xy = add(multiply(matrix.xy, this->xx()), multiply(matrix.yy, this->xy()));
auto yx = add(multiply(matrix.xx, this->yx()), multiply(matrix.yx, this->yy()));
auto yy = add(multiply(matrix.xy, this->yx()), multiply(matrix.yy, this->yy()));
auto tx = add(add(multiply(matrix.xx, this->tx()), multiply(matrix.yx, this->ty())), matrix.tx);
auto ty = add(add(multiply(matrix.xy, this->tx()), multiply(matrix.yy, this->ty())), matrix.ty);

_expressions.assign(IShaderLayer::Expression::TextureMatrixRow0Col0, xx, REG_ONE);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow0Col1, yx, REG_ZERO);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow1Col1, yy, REG_ONE);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow1Col0, xy, REG_ZERO);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow0Col2, tx, REG_ZERO);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow1Col2, ty, REG_ZERO);
}

IShaderExpression::Ptr TextureMatrix::add(const IShaderExpression::Ptr& a, const IShaderExpression::Ptr& b)
{
return ShaderExpression::createAddition(a, b);
}

IShaderExpression::Ptr TextureMatrix::multiply(const IShaderExpression::Ptr& a, ExpressionSlot& b)
{
// Create a constant if there's no expression in the slot yet
auto bExpr = b.expression ? b.expression : ShaderExpression::createConstant(_registers[b.registerIndex]);

return ShaderExpression::createMultiplication(a, bExpr);
}

}
126 changes: 12 additions & 114 deletions radiantcore/shaders/TextureMatrix.h
@@ -1,5 +1,6 @@
#pragma once

#include "itextstream.h"
#include "ExpressionSlots.h"

namespace shaders
Expand All @@ -23,130 +24,27 @@ class TextureMatrix
ExpressionSlots& _expressions;
Registers& _registers;

struct TemporaryMatrix
{
IShaderExpression::Ptr xx;
IShaderExpression::Ptr yx;
IShaderExpression::Ptr tx;
IShaderExpression::Ptr xy;
IShaderExpression::Ptr yy;
IShaderExpression::Ptr ty;
};
struct TemporaryMatrix;

public:
TextureMatrix(ExpressionSlots& expressions, Registers& registers) :
_expressions(expressions),
_registers(registers)
{}
TextureMatrix(ExpressionSlots& expressions, Registers& registers);

TextureMatrix(const TextureMatrix& other) = delete;

void setIdentity()
{
// Initialise the texture matrix to identity (set the diagonals to 1)
xx().registerIndex = REG_ONE;
yx().registerIndex = REG_ZERO;
tx().registerIndex = REG_ZERO;
xy().registerIndex = REG_ZERO;
yy().registerIndex = REG_ONE;
ty().registerIndex = REG_ZERO;
}
// Sets the expression slot bindings such that the matrix will evaluate to identity
void setIdentity();

Matrix4 getMatrix4()
{
auto matrix = Matrix4::getIdentity();
// Return the matrix as stored in the registers
Matrix4 getMatrix4();

matrix.xx() = _registers[xx().registerIndex];
matrix.yx() = _registers[yx().registerIndex];
matrix.tx() = _registers[tx().registerIndex];
matrix.xy() = _registers[xy().registerIndex];
matrix.yy() = _registers[yy().registerIndex];
matrix.ty() = _registers[ty().registerIndex];

return matrix;
}

void applyTransformation(const IShaderLayer::Transformation& transformation)
{
TemporaryMatrix matrix;

switch (transformation.type)
{
case IShaderLayer::TransformType::Translate:
matrix.xx = ShaderExpression::createConstant(1);
matrix.yx = ShaderExpression::createConstant(0);
matrix.tx = transformation.expression1;
matrix.xy = ShaderExpression::createConstant(0);
matrix.yy = ShaderExpression::createConstant(1);
matrix.ty = transformation.expression2;
break;
case IShaderLayer::TransformType::Scale:
matrix.xx = transformation.expression1;
matrix.yx = ShaderExpression::createConstant(0);
matrix.tx = ShaderExpression::createConstant(0);
matrix.xy = ShaderExpression::createConstant(0);
matrix.yy = transformation.expression2;
matrix.ty = ShaderExpression::createConstant(0);
break;
case IShaderLayer::TransformType::CenterScale:
matrix.xx = transformation.expression1;
matrix.yx = ShaderExpression::createConstant(0);
matrix.tx = ShaderExpression::createAddition(
ShaderExpression::createConstant(0.5),
ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), transformation.expression1)
);
matrix.xy = ShaderExpression::createConstant(0);
matrix.yy = transformation.expression2;
matrix.ty = ShaderExpression::createAddition(
ShaderExpression::createConstant(0.5),
ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), transformation.expression2)
);
break;
case IShaderLayer::TransformType::Shear:
matrix.xx = ShaderExpression::createConstant(1);
matrix.yx = transformation.expression1;
matrix.tx = ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), transformation.expression1);
matrix.xy = transformation.expression2;
matrix.yy = ShaderExpression::createConstant(1);
matrix.ty = ShaderExpression::createMultiplication(ShaderExpression::createConstant(-0.5), transformation.expression2);
break;
default:
return;
};

multiplyMatrix(matrix);
}
// pre-multiply the given transformation matrix to the existing one
void applyTransformation(const IShaderLayer::Transformation& transformation);

private:
void multiplyMatrix(const TemporaryMatrix& matrix)
{
auto xx = add(multiply(matrix.xx, this->xx()), multiply(matrix.yx, this->xy()));
auto xy = add(multiply(matrix.xy, this->xx()), multiply(matrix.yy, this->xy()));
auto yx = add(multiply(matrix.xx, this->yx()), multiply(matrix.yx, this->yy()));
auto yy = add(multiply(matrix.xy, this->yx()), multiply(matrix.yy, this->yy()));
auto tx = add(add(multiply(matrix.xx, this->tx()), multiply(matrix.yx, this->ty())), matrix.tx);
auto ty = add(add(multiply(matrix.xy, this->tx()), multiply(matrix.yy, this->ty())), matrix.ty);

_expressions.assign(IShaderLayer::Expression::TextureMatrixRow0Col0, xx, REG_ONE);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow0Col1, yx, REG_ZERO);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow1Col1, yy, REG_ONE);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow1Col0, xy, REG_ZERO);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow0Col2, tx, REG_ZERO);
_expressions.assign(IShaderLayer::Expression::TextureMatrixRow1Col2, ty, REG_ZERO);
}

IShaderExpression::Ptr add(const IShaderExpression::Ptr& a, const IShaderExpression::Ptr& b)
{
return ShaderExpression::createAddition(a, b);
}

IShaderExpression::Ptr multiply(const IShaderExpression::Ptr& a, ExpressionSlot& b)
{
// Create a constant if there's no expression in the slot yet
auto bExpr = b.expression ? b.expression : ShaderExpression::createConstant(_registers[b.registerIndex]);
void multiplyMatrix(const TemporaryMatrix& matrix);

return ShaderExpression::createMultiplication(a, bExpr);
}
IShaderExpression::Ptr add(const IShaderExpression::Ptr& a, const IShaderExpression::Ptr& b);
IShaderExpression::Ptr multiply(const IShaderExpression::Ptr& a, ExpressionSlot& b);

// Shortcut accessors
ExpressionSlot& xx() { return _expressions[IShaderLayer::Expression::TextureMatrixRow0Col0]; }
Expand Down
1 change: 1 addition & 0 deletions tools/msvc/DarkRadiantCore.vcxproj
Expand Up @@ -678,6 +678,7 @@
<ClCompile Include="..\..\radiantcore\shaders\ShaderLibrary.cpp" />
<ClCompile Include="..\..\radiantcore\shaders\ShaderTemplate.cpp" />
<ClCompile Include="..\..\radiantcore\shaders\TableDefinition.cpp" />
<ClCompile Include="..\..\radiantcore\shaders\TextureMatrix.cpp" />
<ClCompile Include="..\..\radiantcore\shaders\textures\GLTextureManager.cpp" />
<ClCompile Include="..\..\radiantcore\shaders\textures\TextureManipulator.cpp" />
<ClCompile Include="..\..\radiantcore\skins\Doom3SkinCache.cpp" />
Expand Down
3 changes: 3 additions & 0 deletions tools/msvc/DarkRadiantCore.vcxproj.filters
Expand Up @@ -1021,6 +1021,9 @@
<ClCompile Include="..\..\radiantcore\shaders\ExpressionSlots.cpp">
<Filter>src\shaders</Filter>
</ClCompile>
<ClCompile Include="..\..\radiantcore\shaders\TextureMatrix.cpp">
<Filter>src\shaders</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\radiantcore\modulesystem\ModuleLoader.h">
Expand Down

0 comments on commit 56a3568

Please sign in to comment.