diff --git a/src/textures/CMakeLists.txt b/src/textures/CMakeLists.txt index cde5a454..75afbc26 100644 --- a/src/textures/CMakeLists.txt +++ b/src/textures/CMakeLists.txt @@ -2,6 +2,8 @@ add_library(luisa-render-textures INTERFACE) luisa_render_add_plugin(constant CATEGORY texture SOURCES constant.cpp) luisa_render_add_plugin(image CATEGORY texture SOURCES image.cpp) luisa_render_add_plugin(swizzle CATEGORY texture SOURCES swizzle.cpp) +luisa_render_add_plugin(scale CATEGORY texture SOURCES scale.cpp) +luisa_render_add_plugin(multiply CATEGORY texture SOURCES multiply.cpp) luisa_render_add_plugin(checkerboard CATEGORY texture SOURCES checkerboard.cpp) luisa_render_add_plugin(concat CATEGORY texture SOURCES concat.cpp) @@ -13,3 +15,6 @@ set_target_properties(luisa-render-texture-sky-precompute PROPERTIES WINDOWS_EXP # Nishita sky texture luisa_render_add_plugin(nishitasky CATEGORY texture SOURCES nishita_sky.cpp) target_link_libraries(luisa-render-texture-nishitasky PRIVATE luisa-render-texture-sky-precompute) + +# bump to normal +luisa_render_add_plugin(bump2normal CATEGORY texture SOURCES bump2normal.cpp) diff --git a/src/textures/bump2normal.cpp b/src/textures/bump2normal.cpp new file mode 100644 index 00000000..8a77d3ba --- /dev/null +++ b/src/textures/bump2normal.cpp @@ -0,0 +1,28 @@ +// +// Created by mike on 4/17/24. +// +/** +* # bump_image = np.power( + # cv.imread(material_bump, cv.IMREAD_GRAYSCALE) / 255, 2.2 + # ) + # h, w = bump_image.shape[:2] + # scale = 4 + # bump_image = cv.resize(bump_image, (w * scale, h * scale), interpolation=cv.INTER_LANCZOS4) + # bump_image = cv.GaussianBlur(bump_image, (5, 5), 0) + # dx_image = cv.copyMakeBorder(bump_image, 0, 0, 1, 1, cv.BORDER_REPLICATE) + # dy_image = cv.copyMakeBorder(bump_image, 1, 1, 0, 0, cv.BORDER_REPLICATE) + # strength = min(w, h) / 50 * scale + # dx_image = np.clip(strength * (dx_image[:, 2:] - dx_image[:, :-2]), -5, 5) + # dy_image = np.clip(-strength * (dy_image[2:, :] - dy_image[:-2, :]), -5, 5) + # dx_image = cv.resize(dx_image, (w, h), interpolation=cv.INTER_AREA) + # dy_image = cv.resize(dy_image, (w, h), interpolation=cv.INTER_AREA) + # dz_image = np.ones_like(dx_image) + # norm = np.sqrt(dx_image**2 + dy_image**2 + dz_image**2) + # normal_image = np.dstack([dz_image, dy_image, dx_image]) + # normal_image = (normal_image / norm[:, :, np.newaxis]) * 0.5 + 0.5 + # # normal_image = cv.GaussianBlur(normal_image, (3, 3), 0) + # # normal_image = cv.resize(normal_image, (w, h), interpolation=cv.INTER_CUBIC) + # normal_image = np.uint8(np.clip(normal_image * 255, 0, 255)) + # save_name = f"lr_exported_textures/{material_bump.split('/')[-1]}" + # cv.imwrite(save_name, normal_image) +*/ \ No newline at end of file diff --git a/src/textures/image.cpp b/src/textures/image.cpp index baafd938..80ee8369 100644 --- a/src/textures/image.cpp +++ b/src/textures/image.cpp @@ -141,15 +141,17 @@ class ImageTextureInstance final : public Texture::Instance { auto encoding = texture->encoding(); auto scale = texture->scale(); if (encoding == ImageTexture::Encoding::SRGB) { + auto rgb = rgba.xyz(); auto linear = ite( - rgba <= 0.04045f, - rgba * (1.0f / 12.92f), - pow((rgba + 0.055f) * (1.0f / 1.055f), 2.4f)); - return make_float4(scale * linear); + rgb <= 0.04045f, + rgb * (1.0f / 12.92f), + pow((rgb + 0.055f) * (1.0f / 1.055f), 2.4f)); + return make_float4(scale * linear, rgba.w); } if (encoding == ImageTexture::Encoding::GAMMA) { + auto rgb = rgba.xyz(); auto gamma = texture->gamma(); - return scale * pow(rgba, gamma); + return make_float4(scale * pow(rgb, gamma), rgba.w); } return scale * rgba; } diff --git a/src/textures/multiply.cpp b/src/textures/multiply.cpp new file mode 100644 index 00000000..d3dff02e --- /dev/null +++ b/src/textures/multiply.cpp @@ -0,0 +1,69 @@ +// +// Created by mike on 4/17/24. +// + +#include +#include +#include + +namespace luisa::render { + +class MultiplyTexture final : public Texture { + +private: + Texture *_a; + Texture *_b; + +public: + MultiplyTexture(Scene *scene, const SceneNodeDesc *desc) noexcept + : Texture{scene, desc}, + _a{scene->load_texture(desc->property_node("a"))}, + _b{scene->load_texture(desc->property_node("b"))} {} + + [[nodiscard]] auto a() const noexcept { return _a; } + [[nodiscard]] auto b() const noexcept { return _b; } + [[nodiscard]] bool is_black() const noexcept override { return _a->is_black() || _b->is_black(); } + [[nodiscard]] bool is_constant() const noexcept override { return is_black() || (_a->is_constant() && _b->is_constant()); } + [[nodiscard]] luisa::optional evaluate_static() const noexcept override { + if (auto a = _a->evaluate_static(), + b = _b->evaluate_static(); + a && b) { + return a.value() * b.value(); + } + return nullopt; + } + [[nodiscard]] luisa::string_view impl_type() const noexcept override { return LUISA_RENDER_PLUGIN_NAME; } + [[nodiscard]] uint channels() const noexcept override { return std::min(_a->channels(), _b->channels()); } + [[nodiscard]] luisa::unique_ptr build( + Pipeline &pipeline, CommandBuffer &command_buffer) const noexcept override; +}; + +class MultiplyTextureInstance final : public Texture::Instance { + +private: + const Texture::Instance *_a; + const Texture::Instance *_b; + +public: + MultiplyTextureInstance(const Pipeline &pipeline, + const Texture *node, + const Texture::Instance *a, + const Texture::Instance *b) noexcept + : Texture::Instance{pipeline, node}, _a{a}, _b{b} {} + [[nodiscard]] Float4 evaluate(const Interaction &it, + const SampledWavelengths &swl, + Expr time) const noexcept override { + return _a->evaluate(it, swl, time) * _b->evaluate(it, swl, time); + } +}; + +luisa::unique_ptr MultiplyTexture::build( + Pipeline &pipeline, CommandBuffer &command_buffer) const noexcept { + auto a = pipeline.build_texture(command_buffer, _a); + auto b = pipeline.build_texture(command_buffer, _b); + return luisa::make_unique(pipeline, this, a, b); +} + +}// namespace luisa::render + +LUISA_RENDER_MAKE_SCENE_NODE_PLUGIN(luisa::render::MultiplyTexture) diff --git a/src/textures/scale.cpp b/src/textures/scale.cpp new file mode 100644 index 00000000..e45b34e3 --- /dev/null +++ b/src/textures/scale.cpp @@ -0,0 +1,79 @@ +// +// Created by mike on 4/17/24. +// + +#include +#include +#include + +namespace luisa::render { + +class ScaleTexture final : public Texture { + +private: + Texture *_base; + float4 _scale; + float4 _offset; + +public: + ScaleTexture(Scene *scene, const SceneNodeDesc *desc) noexcept + : Texture{scene, desc}, + _base{scene->load_texture(desc->property_node("base"))}, + _scale{[desc] { + auto s = desc->property_float_list_or_default("scale"); + if (s.size() == 1u) { return make_float4(s[0]); } + s.reserve(4u); + if (s.size() < 4u) { s.resize(4u, 1.f); } + s.resize(4u); + return make_float4(s[0], s[1], s[2], s[3]); + }()}, + _offset{[desc] { + auto o = desc->property_float_list_or_default("offset"); + if (o.size() == 1u) { return make_float4(o[0]); } + o.reserve(4u); + if (o.size() < 4u) { o.resize(4u, 0.f); } + o.resize(4u); + return make_float4(o[0], o[1], o[2], o[3]); + }()} {} + [[nodiscard]] auto base() const noexcept { return _base; } + [[nodiscard]] auto scale() const noexcept { return _scale; } + [[nodiscard]] auto offset() const noexcept { return _offset; } + [[nodiscard]] bool is_black() const noexcept override { return false; } + [[nodiscard]] bool is_constant() const noexcept override { return _base->is_constant(); } + [[nodiscard]] luisa::optional evaluate_static() const noexcept override { + if (auto v = _base->evaluate_static()) { + return v.value() * _scale; + } + return nullopt; + } + [[nodiscard]] luisa::string_view impl_type() const noexcept override { return LUISA_RENDER_PLUGIN_NAME; } + [[nodiscard]] uint channels() const noexcept override { return _base->channels(); } + [[nodiscard]] luisa::unique_ptr build( + Pipeline &pipeline, CommandBuffer &command_buffer) const noexcept override; +}; + +class ScaleTextureInstance final : public Texture::Instance { + +private: + const Texture::Instance *_base; + +public: + ScaleTextureInstance(const Pipeline &pipeline, const Texture *node, + const Texture::Instance *base) noexcept + : Texture::Instance{pipeline, node}, _base{base} {} + [[nodiscard]] Float4 evaluate(const Interaction &it, + const SampledWavelengths &swl, + Expr time) const noexcept override { + return _base->evaluate(it, swl, time) * node()->scale() + node()->offset(); + } +}; + +luisa::unique_ptr ScaleTexture::build( + Pipeline &pipeline, CommandBuffer &command_buffer) const noexcept { + auto base = pipeline.build_texture(command_buffer, _base); + return luisa::make_unique(pipeline, this, base); +} + +}// namespace luisa::render + +LUISA_RENDER_MAKE_SCENE_NODE_PLUGIN(luisa::render::ScaleTexture)