diff --git a/code/Mesh/Editor/MeshAssetRasterizer.cpp b/code/Mesh/Editor/MeshAssetRasterizer.cpp index b731e0a7c3..104a16a0fa 100644 --- a/code/Mesh/Editor/MeshAssetRasterizer.cpp +++ b/code/Mesh/Editor/MeshAssetRasterizer.cpp @@ -126,7 +126,7 @@ bool MeshAssetRasterizer::generate(const editor::IEditor* editor, const MeshAsse const Aabb3 boundingBox = model->getBoundingBox(); const Scalar maxExtent = (boundingBox.getExtent() * Vector4(1.0f, 1.0f, 0.0f, 0.0f)).max(); const Scalar invMaxExtent = 1.0_simd / maxExtent; - const Matrix44 modelView = translate(0.0f, 0.0f, 2.25f) * scale(invMaxExtent, invMaxExtent, invMaxExtent) * rotateY(asset->getPreviewAngle()) * translate(-boundingBox.getCenter()); + const Matrix44 modelView = translate(0.0f, 0.0f, 2.5f) * scale(invMaxExtent, invMaxExtent, invMaxExtent) * rotateY(asset->getPreviewAngle()) * translate(-boundingBox.getCenter()); return model::ModelRasterizer().generate(model, modelView, outImage); } diff --git a/code/Mesh/Editor/MeshBrowsePreview.cpp b/code/Mesh/Editor/MeshBrowsePreview.cpp index 8d8014c7bc..5fd6fb2fda 100644 --- a/code/Mesh/Editor/MeshBrowsePreview.cpp +++ b/code/Mesh/Editor/MeshBrowsePreview.cpp @@ -9,6 +9,7 @@ #include "Database/Instance.h" #include "Drawing/Image.h" #include "Drawing/PixelFormat.h" +#include "Drawing/Filters/GaussianBlurFilter.h" #include "Drawing/Filters/ScaleFilter.h" #include "Mesh/Editor/MeshAsset.h" #include "Mesh/Editor/MeshAssetRasterizer.h" @@ -37,7 +38,7 @@ Ref< ui::IBitmap > MeshBrowsePreview::generate(editor::IEditor* editor, db::Inst 128, 128 ); - meshThumb->clear(Color4f(0.4f, 0.4f, 0.6f, 0.0f)); + meshThumb->clear(Color4f(0.0f, 0.0f, 0.0f, 0.0f)); MeshAssetRasterizer().generate(editor, asset, meshThumb); @@ -49,6 +50,31 @@ Ref< ui::IBitmap > MeshBrowsePreview::generate(editor::IEditor* editor, db::Inst ); meshThumb->apply(&scaleFilter); + Ref< drawing::Image > shadow = meshThumb->clone(); + + drawing::GaussianBlurFilter blurFilter(16); + shadow->apply(&blurFilter); + + for (int32_t y = 0; y < 64; ++y) + { + const float vy = min(4.0f * min(y, 63 - y) / 32.0f, 1.0f); + + for (int32_t x = 0; x < 64; ++x) + { + const float vx = min(4.0f * min(x, 63 - x) / 32.0f, 1.0f); + const Scalar vignette(min(vx, vy)); + + Color4f alpha; + shadow->getPixelUnsafe(x, y, alpha); + + Color4f color; + meshThumb->getPixelUnsafe(x, y, color); + + color.setAlpha(max(color.getAlpha(), alpha.getAlpha() * 0.5_simd * vignette)); + meshThumb->setPixelUnsafe(x, y, color); + } + } + return new ui::Bitmap(meshThumb); } diff --git a/code/Model/Formats/Fbx/ModelFormatFbx.cpp b/code/Model/Formats/Fbx/ModelFormatFbx.cpp index a31e7bf4de..6b695e767c 100644 --- a/code/Model/Formats/Fbx/ModelFormatFbx.cpp +++ b/code/Model/Formats/Fbx/ModelFormatFbx.cpp @@ -1,5 +1,3 @@ -#pragma optimize( "", off ) - /* * TRAKTOR * Copyright (c) 2022-2024 Anders Pistol. @@ -127,6 +125,7 @@ Ref< Model > ModelFormatFbx::read(const Path& filePath, const std::wstring& filt if (!scene) return nullptr; +#if defined(_DEBUG) traverse(scene->root_node, L"", [](ufbx_node* node, int32_t depth) { for (int32_t i = 0; i < depth; ++i) log::info << L" "; @@ -134,6 +133,7 @@ Ref< Model > ModelFormatFbx::read(const Path& filePath, const std::wstring& filt ) << Endl; return true; }); +#endif const Matrix44 axisTransform = calculateAxisTransform(scene->settings.axes); diff --git a/code/Model/ModelRasterizer.cpp b/code/Model/ModelRasterizer.cpp index d94ffc67a8..d57c77df47 100644 --- a/code/Model/ModelRasterizer.cpp +++ b/code/Model/ModelRasterizer.cpp @@ -9,7 +9,6 @@ #include #include "Core/Math/Triangle.h" #include "Drawing/Image.h" -#include "Drawing/Filters/GammaFilter.h" #include "Model/Model.h" #include "Model/ModelRasterizer.h" @@ -18,12 +17,23 @@ namespace traktor::model namespace { +const Vector4 c_sunDirection = Vector4(0.0f, -0.5f, 1.0f).normalized(); + int32_t wrap(int32_t v, int32_t l) { const int32_t c = v % l; return (c < 0) ? c + l : c; } +Color4f lighting(const Vector4& p, const Vector4& n, const Color4f& materialColor) +{ + const Vector4 viewDirection = p.xyz0().normalized(); + const Vector4 halfWay = (c_sunDirection + viewDirection).normalized(); + const Scalar diffuse = clamp(dot3(c_sunDirection, -n), 0.4_simd, 1.0_simd) + 0.1_simd; + const Scalar specular = power(clamp(dot3(halfWay, -n), 0.0_simd, 1.0_simd), 2.0_simd) * 0.25_simd; + return materialColor * diffuse + Color4f(1.0f, 1.0f, 1.0f, 0.0f) * specular; +} + } @@ -106,14 +116,19 @@ bool ModelRasterizer::generate(const Model* model, const Matrix44& modelView, dr const int32_t tw = texture->getWidth(); const int32_t th = texture->getHeight(); + const bool textureLinear = (texture->getImageInfo() != nullptr) ? (std::abs(texture->getImageInfo()->getGamma() - 1.0f) < 0.1f) : false; + triangle(sp[0], sp[1], sp[2], [&, tw, th](int32_t x, int32_t y, float alpha, float beta, float gamma) { if (x < 0 || x >= outImage->getWidth() || y < 0 || y >= outImage->getHeight()) return; const int32_t offset = x + y * outImage->getWidth(); + const Scalar salpha(alpha); + const Scalar sbeta(beta); + const Scalar sgamma(gamma); - const float z = cp[0].z() * Scalar(alpha) + cp[1].z() * Scalar(beta) + cp[2].z() * Scalar(gamma); - if (z < zbuffer[offset]) + const Vector4 p = cp[0] * salpha + cp[1] * sbeta + cp[2] * sgamma; + if (p.z() < zbuffer[offset]) { Color4f color; const Vector2 tc = uv[0] * alpha + uv[1] * beta + uv[2] * gamma; @@ -121,11 +136,14 @@ bool ModelRasterizer::generate(const Model* model, const Matrix44& modelView, dr const int32_t tv = wrap((int32_t)(tc.y * th), th); texture->getPixel(tu, tv, color); - const Vector4 n = (nm[0] * Scalar(alpha) + nm[1] * Scalar(beta) + nm[2] * Scalar(gamma)).normalized(); - const Scalar d = -n.z() * 0.5_simd + 0.5_simd; + if (!textureLinear) + color = color.linear(); + + const Vector4 n = (nm[0] * salpha + nm[1] * sbeta + nm[2] * sgamma).normalized(); + const Color4f d = lighting(p, n, color); - outImage->setPixelUnsafe(x, y, (color * d * 2.0_simd).rgb1()); - zbuffer[offset] = z; + outImage->setPixelUnsafe(x, y, d.sRGB().rgb1()); + zbuffer[offset] = p.z(); } }); } @@ -136,25 +154,25 @@ bool ModelRasterizer::generate(const Model* model, const Matrix44& modelView, dr return; const int32_t offset = x + y * outImage->getWidth(); + const Scalar salpha(alpha); + const Scalar sbeta(beta); + const Scalar sgamma(gamma); - const float z = cp[0].z() * Scalar(alpha) + cp[1].z() * Scalar(beta) + cp[2].z() * Scalar(gamma); - if (z < zbuffer[offset]) + const Vector4 p = cp[0] * salpha + cp[1] * sbeta + cp[2] * sgamma; + if (p.z() < zbuffer[offset]) { - const Color4f& color = polygonMaterial.getColor(); - const Vector4 n = (nm[0] * Scalar(alpha) + nm[1] * Scalar(beta) + nm[2] * Scalar(gamma)).normalized(); - const Scalar d = -n.z() * 0.5_simd + 0.5_simd; + const Color4f color = polygonMaterial.getColor().linear(); - outImage->setPixelUnsafe(x, y, (color * d * 2.0_simd).rgb1()); - zbuffer[offset] = z; + const Vector4 n = (nm[0] * salpha + nm[1] * sbeta + nm[2] * sgamma).normalized(); + const Color4f d = lighting(p, n, color); + + outImage->setPixelUnsafe(x, y, d.sRGB().rgb1()); + zbuffer[offset] = p.z(); } }); } } - // Convert image from linear gamma to sRGB. - drawing::GammaFilter gammaFilter(1.0f, 2.2f); - outImage->apply(&gammaFilter); - return true; } diff --git a/code/Physics/Editor/MeshAssetRasterizer.cpp b/code/Physics/Editor/MeshAssetRasterizer.cpp index 4aafef3fab..6694d6abb4 100644 --- a/code/Physics/Editor/MeshAssetRasterizer.cpp +++ b/code/Physics/Editor/MeshAssetRasterizer.cpp @@ -47,7 +47,7 @@ bool MeshAssetRasterizer::generate(const editor::IEditor* editor, const MeshAsse const Aabb3 boundingBox = model->getBoundingBox(); const Scalar maxExtent = (boundingBox.getExtent() * Vector4(1.0f, 1.0f, 0.0f, 0.0f)).max(); const Scalar invMaxExtent = 1.0_simd / maxExtent; - const Matrix44 modelView = translate(0.0f, 0.0f, 2.25f) * scale(invMaxExtent, invMaxExtent, invMaxExtent) * rotateY(/*asset->getPreviewAngle()*/3.0f) * translate(-boundingBox.getCenter()); + const Matrix44 modelView = translate(0.0f, 0.0f, 2.5f) * scale(invMaxExtent, invMaxExtent, invMaxExtent) * rotateY(/*asset->getPreviewAngle()*/3.0f) * translate(-boundingBox.getCenter()); return model::ModelRasterizer().generate(model, modelView, outImage); } diff --git a/code/Physics/Editor/MeshBrowsePreview.cpp b/code/Physics/Editor/MeshBrowsePreview.cpp index 02e37b9388..a537ac3dc1 100644 --- a/code/Physics/Editor/MeshBrowsePreview.cpp +++ b/code/Physics/Editor/MeshBrowsePreview.cpp @@ -1,6 +1,6 @@ /* * TRAKTOR - * Copyright (c) 2022 Anders Pistol. + * Copyright (c) 2022-2024 Anders Pistol. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -9,6 +9,7 @@ #include "Database/Instance.h" #include "Drawing/Image.h" #include "Drawing/PixelFormat.h" +#include "Drawing/Filters/GaussianBlurFilter.h" #include "Drawing/Filters/ScaleFilter.h" #include "Physics/Editor/MeshAsset.h" #include "Physics/Editor/MeshAssetRasterizer.h" @@ -37,7 +38,7 @@ Ref< ui::IBitmap > MeshBrowsePreview::generate(editor::IEditor* editor, db::Inst 128, 128 ); - meshThumb->clear(Color4f(0.4f, 0.6f, 0.4f, 0.0f)); + meshThumb->clear(Color4f(0.0f, 0.0f, 0.0f, 0.0f)); MeshAssetRasterizer().generate(editor, asset, meshThumb); @@ -49,6 +50,31 @@ Ref< ui::IBitmap > MeshBrowsePreview::generate(editor::IEditor* editor, db::Inst ); meshThumb->apply(&scaleFilter); + Ref< drawing::Image > shadow = meshThumb->clone(); + + drawing::GaussianBlurFilter blurFilter(16); + shadow->apply(&blurFilter); + + for (int32_t y = 0; y < 64; ++y) + { + const float vy = min(4.0f * min(y, 63 - y) / 32.0f, 1.0f); + + for (int32_t x = 0; x < 64; ++x) + { + const float vx = min(4.0f * min(x, 63 - x) / 32.0f, 1.0f); + const Scalar vignette(min(vx, vy)); + + Color4f alpha; + shadow->getPixelUnsafe(x, y, alpha); + + Color4f color; + meshThumb->getPixelUnsafe(x, y, color); + + color.setAlpha(max(color.getAlpha(), alpha.getAlpha() * 0.5_simd * vignette)); + meshThumb->setPixelUnsafe(x, y, color); + } + } + return new ui::Bitmap(meshThumb); }