Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternative parameter to perform transformation on uv coordinates during a lookup #108

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions include/mitsuba/core/transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,24 @@ struct MTS_EXPORT_CORE Transform {
+ m_transform.m[3][2] * v.z + m_transform.m[3][3] * v.w;
}

inline Point2 transformUVs(const Point2 &v) const {
Float x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y
+ m_transform.m[0][2];
Float y = m_transform.m[1][0] * v.x + m_transform.m[1][1] * v.y
+ m_transform.m[1][2];
return Point2(x, y);
}

inline Vector2 transformUVsWithoutTranslation(const Point2 &v) const {
Float x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y;
Float y = m_transform.m[1][0] * v.x + m_transform.m[1][1] * v.y;
return Vector2(x, y);
}

inline Float get(int x, int y) const {
return m_transform.m[y][x];
}

/**
* \brief Transform a ray. Assumes that there is no scaling (no temporaries)
* \remark This function is not available in the Python bindings
Expand Down
3 changes: 1 addition & 2 deletions include/mitsuba/render/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,7 @@ class MTS_EXPORT_RENDER Texture2D : public Texture {

virtual ~Texture2D();
protected:
Point2 m_uvOffset;
Vector2 m_uvScale;
Transform m_uvTransform;
};

MTS_NAMESPACE_END
Expand Down
51 changes: 31 additions & 20 deletions src/librender/texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,53 +80,64 @@ void Texture::serialize(Stream *stream, InstanceManager *manager) const {

Texture2D::Texture2D(const Properties &props) : Texture(props) {
if (props.getString("coordinates", "uv") == "uv") {
m_uvOffset = Point2(
props.getFloat("uoffset", 0.0f),
props.getFloat("voffset", 0.0f)
);
Float uvscale = props.getFloat("uvscale", 1.0f);
m_uvScale = Vector2(
props.getFloat("uscale", uvscale),
props.getFloat("vscale", uvscale)
);
if (props.hasProperty("uvtransform")) {
if (props.hasProperty("uoffset") || props.hasProperty("voffset")
|| props.hasProperty("uscale") || props.hasProperty("vscale"))
SLog(EError, "Both the 'uvtransformation' parameter and uvoffset/uvscale "
"information were provided -- only one of them can be specified at a time!");

m_uvTransform = props.getTransform("uvtransform", Transform());
} else {
auto uvOffset = Point2(
props.getFloat("uoffset", 0.0f),
props.getFloat("voffset", 0.0f)
);
Float uvscale = props.getFloat("uvscale", 1.0f);
auto uvScale = Vector2(
props.getFloat("uscale", uvscale),
props.getFloat("vscale", uvscale)
);

m_uvTransform = Transform(Matrix4x4(uvScale.x, 0, uvOffset.x, 0, 0, uvScale.y, uvOffset.y, 0, 0, 0, 1, 0, 0, 0, 0, 1));
}

} else {
Log(EError, "Only UV coordinates are supported at the moment!");
}
}

Texture2D::Texture2D(Stream *stream, InstanceManager *manager)
: Texture(stream, manager) {
m_uvOffset = Point2(stream);
m_uvScale = Vector2(stream);
m_uvTransform = Transform(stream);
}

Texture2D::~Texture2D() {
}

void Texture2D::serialize(Stream *stream, InstanceManager *manager) const {
Texture::serialize(stream, manager);
m_uvOffset.serialize(stream);
m_uvScale.serialize(stream);
m_uvTransform.serialize(stream);
}

Spectrum Texture2D::eval(const Intersection &its, bool filter) const {
Point2 uv = Point2(its.uv.x * m_uvScale.x, its.uv.y * m_uvScale.y) + m_uvOffset;
Point2 uv = m_uvTransform.transformUVs(its.uv);
if (its.hasUVPartials && filter) {
return eval(uv,
Vector2(its.dudx * m_uvScale.x, its.dvdx * m_uvScale.y),
Vector2(its.dudy * m_uvScale.x, its.dvdy * m_uvScale.y));
auto uv3dx = m_uvTransform.transformUVsWithoutTranslation(Point2(its.dudx, its.dvdx));
auto uv3dy = m_uvTransform.transformUVsWithoutTranslation(Point2(its.dudy, its.dvdy));
return eval(uv, uv3dx, uv3dy);
} else {
return eval(uv);
}
}

void Texture2D::evalGradient(const Intersection &its, Spectrum *gradient) const {
Point2 uv = Point2(its.uv.x * m_uvScale.x, its.uv.y * m_uvScale.y) + m_uvOffset;
Point2 uv = m_uvTransform.transformUVs(its.uv);

evalGradient(uv, gradient);

gradient[0] *= m_uvScale.x;
gradient[1] *= m_uvScale.y;
auto gradient0 = (gradient[0] * m_uvTransform.get(0, 0)) + (gradient[1] * m_uvTransform.get(1, 0));
gradient[1] = (gradient[0] * m_uvTransform.get(0, 1)) + (gradient[1] * m_uvTransform.get(1, 1));
gradient[0] = gradient0;
}

void Texture2D::evalGradient(const Point2 &uv, Spectrum *gradient) const {
Expand Down
27 changes: 13 additions & 14 deletions src/textures/bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ MTS_NAMESPACE_BEGIN
* \parameter{uscale, vscale}{\Float}{
* Multiplicative factors that should be applied to UV lookups
* }
* \parameter{uvtransform}{\Transform}{
* Alternate parameter to uvscale/uvoffset parameters that applies a transformation to UV values before a lookup
* }
* \parameter{channel}{\String}{
* Create a monochromatic texture based on one of the image channels
* (e.g. \texttt{r}, \texttt{g}, \texttt{b}, \texttt{a}, \texttt{x},
Expand Down Expand Up @@ -596,11 +599,11 @@ class BitmapTextureShader : public Shader {
BitmapTextureShader(Renderer *renderer, const std::string &filename,
const BitmapTexture::MIPMap1* mipmap1,
const BitmapTexture::MIPMap3* mipmap3,
const Point2 &uvOffset, const Vector2 &uvScale,
const Transform &uvTransform,
ReconstructionFilter::EBoundaryCondition wrapModeU,
ReconstructionFilter::EBoundaryCondition wrapModeV,
Float maxAnisotropy)
: Shader(renderer, ETextureShader), m_uvOffset(uvOffset), m_uvScale(uvScale) {
: Shader(renderer, ETextureShader), m_uvTransform(uvTransform) {

ref<Bitmap> bitmap = mipmap1 ? mipmap1->toBitmap() : mipmap3->toBitmap();
m_gpuTexture = renderer->createGPUTexture(filename, bitmap);
Expand Down Expand Up @@ -653,28 +656,25 @@ class BitmapTextureShader : public Shader {
const std::string &evalName,
const std::vector<std::string> &depNames) const {
oss << "uniform sampler2D " << evalName << "_texture;" << endl
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
<< "uniform vec2 " << evalName << "_uvScale;" << endl
<< endl
<< "uniform mat4 " << evalName << "_uvTransform;" << endl
<< endl
<< "vec3 " << evalName << "(vec2 uv) {" << endl
<< " return texture2D(" << evalName << "_texture, vec2(" << endl
<< " uv.x * " << evalName << "_uvScale.x + " << evalName << "_uvOffset.x," << endl
<< " uv.y * " << evalName << "_uvScale.y + " << evalName << "_uvOffset.y)).rgb;" << endl
<< " uv.x * " << evalName << "_uvTransform[0][0] + uv.y * " << evalName << "_uvTransform[1][0] + " << evalName << "_uvTransform[2][0]," << endl
<< " uv.x * " << evalName << "_uvTransform[0][1] + uv.y * " << evalName << "_uvTransform[1][1] + " << evalName << "_uvTransform[2][1])).rgb;" << endl
<< "}" << endl;
}

void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> &parameterIDs) const {
parameterIDs.push_back(program->getParameterID(evalName + "_texture", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvTransform", false));
}

void bind(GPUProgram *program, const std::vector<int> &parameterIDs,
int &textureUnitOffset) const {
m_gpuTexture->bind(textureUnitOffset++);
program->setParameter(parameterIDs[0], m_gpuTexture.get());
program->setParameter(parameterIDs[1], m_uvOffset);
program->setParameter(parameterIDs[2], m_uvScale);
program->setParameter(parameterIDs[1], m_uvTransform);
}

void unbind() const {
Expand All @@ -684,13 +684,12 @@ class BitmapTextureShader : public Shader {
MTS_DECLARE_CLASS()
private:
ref<GPUTexture> m_gpuTexture;
Point2 m_uvOffset;
Vector2 m_uvScale;
Transform m_uvTransform;
};

Shader *BitmapTexture::createShader(Renderer *renderer) const {
return new BitmapTextureShader(renderer, m_filename.filename().string(),
m_mipmap1.get(), m_mipmap3.get(), m_uvOffset, m_uvScale,
m_mipmap1.get(), m_mipmap3.get(), m_uvTransform,
m_wrapModeU, m_wrapModeV, m_maxAnisotropy);
}

Expand Down
27 changes: 13 additions & 14 deletions src/textures/checkerboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ MTS_NAMESPACE_BEGIN
* \parameter{uscale, vscale}{\Float}{
* Multiplicative factors that should be applied to UV values before a lookup
* }
* \parameter{uvtransform}{\Transform}{
* Alternate parameter to uvscale/uvoffset parameters that applies a transformation to UV values before a lookup
* }
* }
* \renderings{
* \rendering{Checkerboard applied to the material test object
Expand Down Expand Up @@ -132,24 +135,23 @@ class Checkerboard : public Texture2D {
class CheckerboardShader : public Shader {
public:
CheckerboardShader(Renderer *renderer, const Spectrum &color0,
const Spectrum &color1, const Point2 &uvOffset,
const Vector2 &uvScale) : Shader(renderer, ETextureShader),
const Spectrum &color1,
const Transform &uvTransform) : Shader(renderer, ETextureShader),
m_color0(color0), m_color1(color1),
m_uvOffset(uvOffset), m_uvScale(uvScale) {
m_uvTransform(uvTransform) {
}

void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &depNames) const {
oss << "uniform vec3 " << evalName << "_color0;" << endl
<< "uniform vec3 " << evalName << "_color1;" << endl
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
<< "uniform vec2 " << evalName << "_uvScale;" << endl
<< "uniform mat4 " << evalName << "_uvTransform;" << endl
<< endl
<< "vec3 " << evalName << "(vec2 uv) {" << endl
<< " uv = vec2(" << endl
<< " uv.x * " << evalName << "_uvScale.x + " << evalName << "_uvOffset.x," << endl
<< " uv.y * " << evalName << "_uvScale.y + " << evalName << "_uvOffset.y);" << endl
<< " uv.x * " << evalName << "_uvTransform[0][0] + uv.y * " << evalName << "_uvTransform[1][0] + " << evalName << "_uvTransform[2][0]," << endl
<< " uv.x * " << evalName << "_uvTransform[0][1] + uv.y * " << evalName << "_uvTransform[1][1] + " << evalName << "_uvTransform[2][1]);" << endl
<< " float x = 2*(mod(int(uv.x*2), 2)) - 1, y = 2*(mod(int(uv.y*2), 2)) - 1;" << endl
<< " if (x*y == 1)" << endl
<< " return " << evalName << "_color0;" << endl
Expand All @@ -161,29 +163,26 @@ class CheckerboardShader : public Shader {
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> &parameterIDs) const {
parameterIDs.push_back(program->getParameterID(evalName + "_color0", false));
parameterIDs.push_back(program->getParameterID(evalName + "_color1", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvTransform", false));
}

void bind(GPUProgram *program, const std::vector<int> &parameterIDs,
int &textureUnitOffset) const {
program->setParameter(parameterIDs[0], m_color0);
program->setParameter(parameterIDs[1], m_color1);
program->setParameter(parameterIDs[2], m_uvOffset);
program->setParameter(parameterIDs[3], m_uvScale);
program->setParameter(parameterIDs[2], m_uvTransform);
}

MTS_DECLARE_CLASS()
private:
Spectrum m_color0;
Spectrum m_color1;
Point2 m_uvOffset;
Vector2 m_uvScale;
Transform m_uvTransform;
};

Shader *Checkerboard::createShader(Renderer *renderer) const {
return new CheckerboardShader(renderer, m_color0, m_color1,
m_uvOffset, m_uvScale);
m_uvTransform);
}

MTS_IMPLEMENT_CLASS(CheckerboardShader, false, Shader)
Expand Down
27 changes: 13 additions & 14 deletions src/textures/gridtexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ MTS_NAMESPACE_BEGIN
* \parameter{uoffset, voffset}{\Float}{
* Numerical offset that should be applied to UV values before a lookup
* }
* \parameter{uvtransform}{\Transform}{
* Alternate parameter to uvscale/uvoffset parameters that applies a transformation to UV values before a lookup
* }
* }
* \renderings{
* \rendering{Grid texture applied to the material test object}{tex_gridtexture}
Expand Down Expand Up @@ -145,10 +148,10 @@ class GridTexture : public Texture2D {
class GridTextureShader : public Shader {
public:
GridTextureShader(Renderer *renderer, const Spectrum &color0,
const Spectrum &color1, Float lineWidth, const Point2 &uvOffset,
const Vector2 &uvScale) : Shader(renderer, ETextureShader),
const Spectrum &color1, Float lineWidth,
const Transform &uvTransform) : Shader(renderer, ETextureShader),
m_color0(color0), m_color1(color1),
m_lineWidth(lineWidth), m_uvOffset(uvOffset), m_uvScale(uvScale) {
m_lineWidth(lineWidth), m_uvTransform(uvTransform) {
}

void generateCode(std::ostringstream &oss,
Expand All @@ -157,13 +160,12 @@ class GridTextureShader : public Shader {
oss << "uniform vec3 " << evalName << "_color0;" << endl
<< "uniform vec3 " << evalName << "_color1;" << endl
<< "uniform float " << evalName << "_lineWidth;" << endl
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
<< "uniform vec2 " << evalName << "_uvScale;" << endl
<< "uniform mat4 " << evalName << "_uvTransform;" << endl
<< endl
<< "vec3 " << evalName << "(vec2 uv) {" << endl
<< " uv = vec2(" << endl
<< " uv.x * " << evalName << "_uvScale.x + " << evalName << "_uvOffset.x," << endl
<< " uv.y * " << evalName << "_uvScale.y + " << evalName << "_uvOffset.y);" << endl
<< " uv.x * " << evalName << "_uvTransform[0][0] + uv.y * " << evalName << "_uvTransform[1][0] + " << evalName << "_uvTransform[2][0]," << endl
<< " uv.x * " << evalName << "_uvTransform[0][1] + uv.y * " << evalName << "_uvTransform[1][1] + " << evalName << "_uvTransform[2][1]);" << endl
<< " float x = uv.x - floor(uv.x);" << endl
<< " float y = uv.y - floor(uv.y);" << endl
<< " if (x > .5) x -= 1.0;" << endl
Expand All @@ -179,31 +181,28 @@ class GridTextureShader : public Shader {
parameterIDs.push_back(program->getParameterID(evalName + "_color0", false));
parameterIDs.push_back(program->getParameterID(evalName + "_color1", false));
parameterIDs.push_back(program->getParameterID(evalName + "_lineWidth", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvTransform", false));
}

void bind(GPUProgram *program, const std::vector<int> &parameterIDs,
int &textureUnitOffset) const {
program->setParameter(parameterIDs[0], m_color0);
program->setParameter(parameterIDs[1], m_color1);
program->setParameter(parameterIDs[2], m_lineWidth);
program->setParameter(parameterIDs[3], m_uvOffset);
program->setParameter(parameterIDs[4], m_uvScale);
program->setParameter(parameterIDs[3], m_uvTransform);
}

MTS_DECLARE_CLASS()
private:
Spectrum m_color0;
Spectrum m_color1;
Float m_lineWidth;
Point2 m_uvOffset;
Vector2 m_uvScale;
Transform m_uvTransform;
};

Shader *GridTexture::createShader(Renderer *renderer) const {
return new GridTextureShader(renderer, m_color0, m_color1,
m_lineWidth, m_uvOffset, m_uvScale);
m_lineWidth, m_uvTransform);
}

MTS_IMPLEMENT_CLASS(GridTextureShader, false, Shader)
Expand Down