diff --git a/library/phx/resources/types/lookup_table.cpp b/library/phx/resources/types/lookup_table.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7cf2b13b0995460147a509f00bbe85dd81d0f7be
--- /dev/null
+++ b/library/phx/resources/types/lookup_table.cpp
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//------------------------------------------------------------------------------
+
+#include "phx/resources/types/lookup_table.hpp"
+
+#include <memory>
+
+namespace phx {
+LookupTable::LookupTable(const TransferFunction& transfer_function,
+                         int num_colors)
+    : min_key_(transfer_function.GetEntries().front().scalar),
+      max_key_(transfer_function.GetEntries().back().scalar),
+      transfer_function_(transfer_function) {
+  Generate(num_colors);
+}
+
+void LookupTable::Generate(int num_colors) {
+  float step = (max_key_ - min_key_) / (num_colors - 1);
+  for (auto i = 0; i < num_colors; ++i) {
+    lookup_table_.push_back(
+        transfer_function_.Interpolate(min_key_ + i * step));
+  }
+}
+glm::vec4 LookupTable::GetColor(std::size_t index) const {
+  return lookup_table_.at(index);
+}
+
+std::size_t LookupTable::GetIndex(float key) const {
+  return static_cast<std::size_t>(
+      std::round((GetSize() - 1) * ((key - min_key_) / (max_key_ - min_key_))));
+}
+
+std::size_t LookupTable::GetSize() const { return lookup_table_.size(); }
+
+std::unique_ptr<gl::texture_1d> LookupTable::GetTexture1D() const {
+  auto lookup_texture = std::make_unique<gl::texture_1d>();
+  lookup_texture->set_storage(0, GL_RGBA,
+                              static_cast<GLsizei>(lookup_table_.size()));
+  lookup_texture->set_sub_image(0, 0,
+                                static_cast<GLsizei>(lookup_table_.size()),
+                                GL_RGBA8, GL_FLOAT, lookup_table_.data());
+  return lookup_texture;
+}
+
+}  // namespace phx
diff --git a/library/phx/resources/types/lookup_table.hpp b/library/phx/resources/types/lookup_table.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ef9a920a4d80e7d795beb6aa65a2ee22fea5dd3d
--- /dev/null
+++ b/library/phx/resources/types/lookup_table.hpp
@@ -0,0 +1,65 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//------------------------------------------------------------------------------
+
+#ifndef LIBRARY_PHX_RESOURCES_TYPES_LOOKUP_TABLE_HPP_
+#define LIBRARY_PHX_RESOURCES_TYPES_LOOKUP_TABLE_HPP_
+
+#include <memory>
+#include <vector>
+
+#include "phx/resources/types/shader_source.hpp"
+#include "phx/resources/types/transfer_function.hpp"
+#include "phx/suppress_warnings.hpp"
+
+SUPPRESS_WARNINGS_BEGIN
+#include "gl/texture.hpp"
+#include "glm/detail/type_vec4.hpp"
+SUPPRESS_WARNINGS_END
+
+namespace phx {
+
+class PHOENIX_EXPORT LookupTable {
+ public:
+  LookupTable(const TransferFunction& transfer_function, int num_colors);
+  LookupTable(const LookupTable&) = default;
+  LookupTable(LookupTable&&) = default;
+  ~LookupTable() = default;
+  LookupTable& operator=(const LookupTable&) = default;
+  LookupTable& operator=(LookupTable&&) = default;
+
+  std::size_t GetIndex(float key) const;
+  glm::vec4 GetColor(std::size_t index) const;
+  std::size_t GetSize() const;
+
+  std::unique_ptr<gl::texture_1d> GetTexture1D() const;
+
+ private:
+  void Generate(int num_colors);
+
+  float min_key_;
+  float max_key_;
+  std::vector<glm::vec4> lookup_table_;
+  const TransferFunction transfer_function_;
+};
+}  // namespace phx
+
+#endif  // LIBRARY_PHX_RESOURCES_TYPES_LOOKUP_TABLE_HPP_
diff --git a/library/phx/resources/types/transfer_function.cpp b/library/phx/resources/types/transfer_function.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8a29c2304eb477ed859fc29a00a159f20bf04522
--- /dev/null
+++ b/library/phx/resources/types/transfer_function.cpp
@@ -0,0 +1,142 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//------------------------------------------------------------------------------
+
+#include "phx/resources/types/transfer_function.hpp"
+
+#include <algorithm>
+#include <fstream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "phx/core/logger.hpp"
+
+#define GLM_ENABLE_EXPERIMENTAL
+#include "glm/gtx/compatibility.hpp"
+
+#include "json.hpp"
+
+namespace phx {
+TransferFunction::TransferFunction(const InterpolationMode mode)
+    : mode_(mode) {}
+
+glm::vec4 TransferFunction::Interpolate(float scalar) const {
+  if (entries_.empty()) {
+    phx::warn("TransferFunction is empty! Defaulting to black.");
+    return glm::vec4();
+  }
+
+  if (scalar > entries_.back().scalar) {
+    phx::warn(
+        "WARNING: Passed value is out of TransferFunction range! Setting to "
+        "maximum.");
+    return entries_.back().color;
+  }
+
+  if (scalar < entries_.front().scalar) {
+    phx::warn(
+        "WARNING: Passed value is out of TransferFunction range! Setting to "
+        "minimum.");
+    return entries_.front().color;
+  }
+
+  const auto iterator = std::find_if(
+      entries_.begin(), entries_.end(),
+      [=](const Entry& iteratee) { return iteratee.scalar > scalar; });
+  const std::size_t upper_index =
+      static_cast<std::size_t>(std::distance(entries_.begin(), iterator));
+  if (upper_index == 0) {
+    return entries_[upper_index].color;
+  }
+  if (upper_index == entries_.size()) {
+    return entries_.back().color;
+  }
+  const std::size_t lower_index = upper_index - 1;
+  const auto offset =
+      scalar - static_cast<float>(entries_[lower_index].scalar /
+                                      entries_[upper_index].scalar -
+                                  entries_[lower_index].scalar);
+
+  if (mode_ == InterpolationMode::NEAREST_NEIGHBOR) {
+    return offset >= 0.5f ? entries_[upper_index].color
+                          : entries_[lower_index].color;
+  }
+  if (mode_ == InterpolationMode::LINEAR) {
+    return glm::lerp(entries_[lower_index].color, entries_[upper_index].color,
+                     offset);
+  }
+  return glm::vec4();
+}
+
+void TransferFunction::Load(const std::string& filepath) {
+  std::ifstream file(filepath);
+
+  nlohmann::json json;
+  file >> json;
+
+  auto json_array = json["entries"];
+  for (auto& json_entry : json_array) {
+    float json_scalar = json_entry["scalar"];
+    std::vector<float> json_colors = json_entry["color"];
+    entries_.push_back(
+        {json_scalar,
+         {json_colors[0], json_colors[1], json_colors[2], json_colors[3]}});
+    std::sort(entries_.begin(), entries_.end(),
+              [](Entry a, Entry b) { return a.scalar <= b.scalar; });
+  }
+}
+
+void TransferFunction::Save(const std::string& filepath) const {
+  auto json_array = nlohmann::json::array();
+  for (auto& entry : entries_) {
+    nlohmann::json json_entry;
+    json_entry["scalar"] = entry.scalar;
+    json_entry["color"] = nlohmann::json::array(
+        {entry.color.r, entry.color.g, entry.color.b, entry.color.a});
+    json_array.push_back(json_entry);
+  }
+
+  nlohmann::json json;
+  json["entries"] = json_array;
+
+  std::ofstream file(filepath);
+  file << json;
+}
+
+const std::vector<TransferFunction::Entry>& TransferFunction::GetEntries()
+    const {
+  return entries_;
+}
+
+void TransferFunction::SetEntries(const std::vector<Entry>& entries) {
+  entries_ = entries;
+  std::sort(entries_.begin(), entries_.end(),
+            [](Entry a, Entry b) { return a.scalar <= b.scalar; });
+}
+
+TransferFunction::InterpolationMode TransferFunction::GetMode() const {
+  return mode_;
+}
+
+void TransferFunction::SetMode(InterpolationMode mode) { mode_ = mode; }
+
+}  // namespace phx
diff --git a/library/phx/resources/types/transfer_function.hpp b/library/phx/resources/types/transfer_function.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..79500cfdfaebd6b3ea7cb49912886d464176b4c4
--- /dev/null
+++ b/library/phx/resources/types/transfer_function.hpp
@@ -0,0 +1,83 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//------------------------------------------------------------------------------
+
+#ifndef LIBRARY_PHX_RESOURCES_TYPES_TRANSFER_FUNCTION_HPP_
+#define LIBRARY_PHX_RESOURCES_TYPES_TRANSFER_FUNCTION_HPP_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "phx/resources/types/shader_source.hpp"
+#include "phx/suppress_warnings.hpp"
+#include "phx/utility/epsilon_comparison.hpp"
+
+SUPPRESS_WARNINGS_BEGIN
+#include "gl/texture.hpp"
+#include "glm/detail/type_vec1.hpp"
+#include "glm/detail/type_vec4.hpp"
+SUPPRESS_WARNINGS_END
+
+namespace phx {
+
+class PHOENIX_EXPORT TransferFunction {
+ public:
+  enum class InterpolationMode { NEAREST_NEIGHBOR, LINEAR };
+  struct PHOENIX_EXPORT Entry {
+    float scalar;
+    glm::vec4 color;
+
+    bool operator==(const Entry& that) const {
+      return phx::equals<float>(scalar, that.scalar) && color == that.color;
+    }
+    bool operator!=(const Entry& that) const {
+      return !phx::equals<float>(scalar, that.scalar) || color != that.color;
+    }
+  };
+
+  explicit TransferFunction(
+      InterpolationMode interpolation_mode = InterpolationMode::LINEAR);
+  TransferFunction(const TransferFunction&) = default;
+  TransferFunction(TransferFunction&&) = default;
+  ~TransferFunction() = default;
+  TransferFunction& operator=(const TransferFunction&) = default;
+  TransferFunction& operator=(TransferFunction&&) = default;
+
+  glm::vec4 Interpolate(float scalar) const;
+
+  void Load(const std::string& filepath);
+  void Save(const std::string& filepath) const;
+
+  const std::vector<Entry>& GetEntries() const;
+  void SetEntries(const std::vector<Entry>& entries);
+
+  InterpolationMode GetMode() const;
+  void SetMode(InterpolationMode mode);
+
+ private:
+  std::vector<Entry> entries_;  // This is always sorted by scalar increasingly.
+  InterpolationMode mode_ = InterpolationMode::LINEAR;
+};
+
+}  // namespace phx
+
+#endif  // LIBRARY_PHX_RESOURCES_TYPES_TRANSFER_FUNCTION_HPP_
diff --git a/library/phx/utility/epsilon_comparison.hpp b/library/phx/utility/epsilon_comparison.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a3202823159f7797ddc046498fd8e4850265d1c8
--- /dev/null
+++ b/library/phx/utility/epsilon_comparison.hpp
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//------------------------------------------------------------------------------
+
+#ifndef LIBRARY_PHX_UTILITY_EPSILON_COMPARISON_HPP_
+#define LIBRARY_PHX_UTILITY_EPSILON_COMPARISON_HPP_
+
+#include <cmath>
+
+namespace phx {
+
+template <typename type>
+const type epsilon() {
+  return type(0.0001);
+}
+
+template <typename type>
+bool equals(const type& lhs, const type& rhs) {
+  return std::abs(lhs - rhs) < epsilon<type>();
+}
+
+}  // namespace phx
+
+#endif  // LIBRARY_PHX_UTILITY_EPSILON_COMPARISON_HPP_
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f63ed905d8e76ba508e35cf4c75092d0c56031d9..f8633caf777fe3f118dc1efe0890986fa4bd9df3 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -187,6 +187,7 @@ add_mocked_test(test_vr_controller                  LIBRARIES phoenix test_utili
 add_mocked_test(test_assimp_loader                  LIBRARIES phoenix test_utilities MOCKS opengl_mock)
 add_mocked_test(test_model                          LIBRARIES phoenix                MOCKS opengl_mock)
 add_mocked_test(test_scene_loader                   LIBRARIES phoenix                MOCKS opengl_mock)
+add_mocked_test(test_lookup_table                   LIBRARIES phoenix                MOCKS opengl_mock)
 
 add_mocked_test(integration_test_model_rendering             LIBRARIES phoenix test_utilities MOCKS openvr_mock)
 add_mocked_test(integration_test_opengl_buffer_data_download LIBRARIES phoenix test_utilities MOCKS openvr_mock)
diff --git a/tests/src/mocks/generation/Create_openGL_mock.py b/tests/src/mocks/generation/Create_openGL_mock.py
index 07c1944f1a3092d356c28ca23dee79d73bf1e640..cec127ab9145a30030fd965840ed33bc96956411 100644
--- a/tests/src/mocks/generation/Create_openGL_mock.py
+++ b/tests/src/mocks/generation/Create_openGL_mock.py
@@ -22,6 +22,7 @@
 import sys, getopt
 
 #functions you want to mock should be put in this list
+
 functions_to_mock = ['__glewBindAttribLocation',
                      '__glewBindBuffer', '__glewBindBufferBase',
                      '__glewBindBufferRange', '__glewBindFragDataLocation',
@@ -142,8 +143,9 @@ functions_to_mock = ['__glewBindAttribLocation',
                      '__glewReleaseShaderCompiler', '__glewShaderBinary',
                      '__glewShaderStorageBlockBinding',
                      '__glewSpecializeShader', '__glewStencilMaskSeparate',
-                     '__glewTextureParameteri', '__glewTextureStorage2D',
-                     '__glewTextureStorage3D', '__glewTextureSubImage2D',
+                     '__glewTextureParameteri', '__glewTextureStorage1D',
+                     '__glewTextureStorage2D', '__glewTextureStorage3D',
+                     '__glewTextureSubImage1D', '__glewTextureSubImage2D',
                      '__glewTextureSubImage3D',
                      '__glewTransformFeedbackVaryings',
                      '__glewUniformBlockBinding', '__glewUniformSubroutinesuiv',
diff --git a/tests/src/test_lookup_table.cpp b/tests/src/test_lookup_table.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..17d21d9878c998a0229c9d7bd1b614a6fbce39ea
--- /dev/null
+++ b/tests/src/test_lookup_table.cpp
@@ -0,0 +1,76 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//------------------------------------------------------------------------------
+
+#include "catch/catch.hpp"
+
+#include "phx/resources/types/lookup_table.hpp"
+#include "phx/resources/types/transfer_function.hpp"
+
+#include "trompeloeil.hpp"
+
+#include "mocks/opengl_mock.hpp"
+
+SCENARIO("Creating and accesing a Lookup Table", "[phx][phx::LookupTable]") {
+  OPENGL_MOCK_ALLOW_ANY_CALL
+  GIVEN("A test transfer function") {
+    phx::TransferFunction transfer_function;
+    glm::vec4 red_color{1.0f, 0.0f, 0.0f, 0.0f};
+    glm::vec4 black_color{0.0f, 0.0f, 0.0f, 0.0f};
+    transfer_function.SetEntries({{0.0f, red_color}, {1.0f, black_color}});
+
+    WHEN("We create Lookup Table with the given Transfer function") {
+      phx::LookupTable lut(transfer_function, 11);
+
+      THEN("The Lookup Table is generated correctly") {
+        REQUIRE(lut.GetColor(0) == red_color);
+        REQUIRE(lut.GetColor(2) == glm::vec4(0.8f, 0.0f, 0.0f, 0.0f));
+        REQUIRE(lut.GetColor(5) == glm::vec4(0.5f, 0.0f, 0.0f, 0.0f));
+        REQUIRE(lut.GetColor(7) == glm::vec4(0.3f, 0.0f, 0.0f, 0.0f));
+        REQUIRE(lut.GetColor(10) == black_color);
+      }
+
+      THEN("Keys can be converted indices") {
+        REQUIRE(lut.GetIndex(0.0f) == 0);
+        REQUIRE(lut.GetIndex(1.0f) == 10);
+        REQUIRE(lut.GetIndex(0.56f) == 6);
+      }
+
+      THEN("We can ask for a lookup table as texture1D") {
+        REQUIRE_CALL(open_gl_mock, glCreateTextures(_, _, _));
+        auto lookup_texture = lut.GetTexture1D();
+      }
+    }
+
+    WHEN("We ask for a nearest neighbor interpolated Lookup Table") {
+      transfer_function.SetMode(
+          phx::TransferFunction::InterpolationMode::NEAREST_NEIGHBOR);
+      phx::LookupTable lut(transfer_function, 11);
+      THEN("The Lookuptable is generated correctly") {
+        REQUIRE(lut.GetColor(0) == red_color);
+        REQUIRE(lut.GetColor(2) == red_color);
+        REQUIRE(lut.GetColor(5) == black_color);
+        REQUIRE(lut.GetColor(7) == black_color);
+        REQUIRE(lut.GetColor(10) == black_color);
+      }
+    }
+  }
+}
diff --git a/tests/src/test_transfer_function.cpp b/tests/src/test_transfer_function.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..38d2ef046f8fd64154020ac55ef23046189489ac
--- /dev/null
+++ b/tests/src/test_transfer_function.cpp
@@ -0,0 +1,104 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//------------------------------------------------------------------------------
+
+#include <memory>
+
+#include "phx/core/logger.hpp"
+#include "phx/resources/types/transfer_function.hpp"
+
+#include "test_utilities/glm_vec.hpp"
+
+#include "catch/catch.hpp"
+#include "test_utilities/log_capture.hpp"
+
+SCENARIO("Creating, saving and loading a transfer function",
+         "[phx][phx::TransferFunction]") {
+  GIVEN("A test transfer function") {
+    phx::TransferFunction transfer_function;
+    glm::vec4 red_color{1.0f, 0.0f, 0.0f, 0.0f};
+    glm::vec4 black_color{0.0f, 0.0f, 0.0f, 0.0f};
+    transfer_function.SetEntries({{0.0f, red_color}, {1.0f, black_color}});
+
+    WHEN("We save it and load it into a new one") {
+      transfer_function.Save("test_tranfer_function.json");
+      phx::TransferFunction loaded_function;
+      loaded_function.Load("test_tranfer_function.json");
+      THEN("The loaded one is identical to the original") {
+        for (auto i = 0u; i < transfer_function.GetEntries().size(); ++i) {
+          REQUIRE(transfer_function.GetEntries()[i] ==
+                  loaded_function.GetEntries()[i]);
+        }
+      }
+    }
+
+    WHEN("We query for a scalar between two transfer function entries") {
+      THEN("The color is interpolated correctly") {
+        REQUIRE(transfer_function.Interpolate(0.0f) == red_color);
+        REQUIRE(transfer_function.Interpolate(1.0f) == black_color);
+        REQUIRE(transfer_function.Interpolate(0.5f) ==
+                glm::vec4(0.5f, 0.0f, 0.0f, 0.0f));
+      }
+    }
+
+    WHEN("We query for a scalar outside of the transfer function range") {
+      THEN("The color is set to max/min and a warning is given.") {
+        auto log_capture = std::make_shared<test_utilities::LogCapture>();
+        phx::logger =
+            std::make_shared<spdlog::logger>("logcapture", log_capture);
+        REQUIRE(transfer_function.Interpolate(-1.0f) == red_color);
+        REQUIRE(*log_capture ==
+                "WARNING: Passed value is out of TransferFunction range! "
+                "Setting to minimum.");
+
+        log_capture = std::make_shared<test_utilities::LogCapture>();
+        phx::logger =
+            std::make_shared<spdlog::logger>("logcapture", log_capture);
+        REQUIRE(transfer_function.Interpolate(2.0f) == black_color);
+        REQUIRE(*log_capture ==
+                "WARNING: Passed value is out of TransferFunction range! "
+                "Setting to maximum.");
+      }
+    }
+
+    WHEN("Wechange the mode to nearest neighbor") {
+      transfer_function.SetMode(
+          phx::TransferFunction::InterpolationMode::NEAREST_NEIGHBOR);
+      THEN("The color is set correctly") {
+        REQUIRE(transfer_function.Interpolate(0.2f) == red_color);
+        REQUIRE(transfer_function.Interpolate(0.7f) == black_color);
+        REQUIRE(transfer_function.Interpolate(0.5f) == black_color);
+      }
+    }
+  }
+
+  GIVEN("A test transfer function with only one value") {
+    phx::TransferFunction transfer_function;
+    glm::vec4 black_color{0.0f, 0.0f, 0.0f, 0.0f};
+    transfer_function.SetEntries({{1.0f, black_color}});
+    WHEN("We ask for values out of its range") {
+      THEN("The color is set to the only given transformation") {
+        REQUIRE(transfer_function.Interpolate(0.0f) == black_color);
+        REQUIRE(transfer_function.Interpolate(2.0f) == black_color);
+      }
+    }
+  }
+}