Advertisement
Zgragselus

SCTEX

Sep 17th, 2023
1,109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 30.56 KB | None | 0 0
  1. #include "Main.h"
  2. #include "SkyeCuillin/ImguiSubsystem.h"
  3. #include "SkyeCuillin/RenderPassGUI.h"
  4. #include "Game/Loader/DevIL.h"
  5. #include "Game/Loader/Sctex.h"
  6. #include "Graphics/Common/Texture/TextureCompressor.h"
  7. #include "Core/Math/Numeric/Mat3.h"
  8.  
  9. class Main : public Engine::System
  10. {
  11. private:
  12.     SkyeCuillin::ImguiSubsystem* mImgui;
  13.     SkyeCuillin::RenderPassGUI* mTexturesPass;
  14.  
  15.     Engine::Log* mLog;
  16.     Engine::Window* mWindow;
  17.     Engine::Constants* mOptions;
  18.     Engine::D3DRenderer* mRenderer;
  19.     Engine::D3DSwapChain* mSwapChain;
  20.  
  21.     Engine::Texture* mUncompressed;
  22.     Engine::Texture* mCompressed;
  23.  
  24.     float mUncompressedMiplevel = 0.0f;
  25.     float mNumUncompressedMiplevels = 1.0f;
  26.     float mCompressedMiplevel = 0.0f;
  27.     float mNumCompressedMiplevels = 1.0f;
  28.     float mCurrentMiplevel = 0.0f;
  29.  
  30.     Engine::mat3 mTransform;
  31.  
  32. private:
  33.     Engine::LoaderDevIL::Image* mImage = nullptr;
  34.  
  35.     size_t* mCompressedWidth;
  36.     size_t* mCompressedHeight;
  37.     size_t mCompressedLevels;
  38.     unsigned char** mCompressedData;
  39.     Engine::Graphics::Format mCompressedFormat;
  40.  
  41.     void LoadTexture(const std::string& filename)
  42.     {
  43.         if (filename.find(".sctex") != std::string::npos)
  44.         {
  45.             Engine::LoaderSctex* loader = new Engine::LoaderSctex(mLog);
  46.  
  47.             if (mCompressed != nullptr)
  48.             {
  49.                 delete mCompressed;
  50.             }
  51.             mCompressed = loader->Load(filename, mRenderer, "Compressed");
  52.  
  53.             if (mImage != nullptr)
  54.             {
  55.                 delete mImage;
  56.                 mImage = nullptr;
  57.             }
  58.  
  59.             // Now, load the same image - but only into helper data, these must be de-compressed
  60.             // and setup as original image (and therefore also uncompressed image.
  61.             Engine::LoaderSctex::HelperImageData* imageData = loader->Load(filename);
  62.  
  63.             mImage = new Engine::LoaderDevIL::Image();
  64.             mImage->mUseAlphaMipmap = true;
  65.             mImage->mChannels = 4;
  66.             mImage->mBpp = 4;
  67.             mImage->mWidth = imageData->mImageRecord[0].mWidth;
  68.             mImage->mHeight = imageData->mImageRecord[0].mHeight;
  69.             mImage->mData = new unsigned char[imageData->mImageRecord[0].mWidth * imageData->mImageRecord[0].mHeight * 4];
  70.             mImage->mMipLevels = imageData->mHeader.mNumImages;
  71.             mImage->mMipmaps = new unsigned char*[mImage->mMipLevels];
  72.             mImage->mMipmaps[0] = mImage->mData;
  73.  
  74.             Engine::TextureCompressor::Decompress(imageData->mImageRecord[0].mWidth, imageData->mImageRecord[0].mHeight, mImage->mData, imageData->mImageData[0].mData, (Engine::TextureCompressor::Format)imageData->mHeader.mFormat);
  75.            
  76.             for (size_t i = 1; i < mImage->mMipLevels; i++)
  77.             {
  78.                 mImage->mMipmaps[i] = new unsigned char[imageData->mImageRecord[i].mWidth * imageData->mImageRecord[i].mHeight * 4];
  79.                 Engine::TextureCompressor::Decompress(imageData->mImageRecord[i].mWidth, imageData->mImageRecord[i].mHeight, mImage->mMipmaps[i], imageData->mImageData[i].mData, (Engine::TextureCompressor::Format)imageData->mHeader.mFormat);
  80.             }
  81.  
  82.             // Check for BC5 format - those hold normal map. Add blue channel.
  83.             if ((Engine::TextureCompressor::Format)imageData->mHeader.mFormat == Engine::TextureCompressor::Format::BC5)
  84.             {
  85.                 for (size_t i = 0; i < mImage->mMipLevels; i++)
  86.                 {
  87.                     unsigned char* ptr = mImage->mMipmaps[i];
  88.  
  89.                     for (size_t j = 0; j < imageData->mImageRecord[i].mWidth * imageData->mImageRecord[i].mHeight; j++)
  90.                     {
  91.                         float x = (float)ptr[0] / 255.0f * 2.0f - 1.0f;
  92.                         float y = (float)ptr[1] / 255.0f * 2.0f - 1.0f;
  93.                         float z = 1.0f - x * x - y * y;
  94.                         if (z < 0.0f)
  95.                         {
  96.                             z = 0.0f;
  97.                         }
  98.                         else
  99.                         {
  100.                             z = sqrtf(z);
  101.                         }
  102.  
  103.                         ptr[0] = (unsigned char)((x * 0.5f + 0.5f) * 255.0f);
  104.                         ptr[1] = (unsigned char)((y * 0.5f + 0.5f) * 255.0f);
  105.                         ptr[2] = (unsigned char)((z * 0.5f + 0.5f) * 255.0f);
  106.                         ptr[3] = 255;
  107.  
  108.                         ptr += 4;
  109.                     }
  110.                 }
  111.             }
  112.  
  113.             if (mImage != nullptr)
  114.             {
  115.                 mNumUncompressedMiplevels = (float)mImage->mMipLevels;
  116.  
  117.                 if (mUncompressed != nullptr)
  118.                 {
  119.                     delete mUncompressed;
  120.                 }
  121.                 mUncompressed = new Engine::Texture("Uncompressed");
  122.                 mUncompressed->InitMipmaps(mRenderer, mImage->mWidth, mImage->mHeight, 1, mImage->mMipLevels, Engine::Graphics::RGBA8, (const void**)mImage->mMipmaps);
  123.                 mUncompressed->SetName("Uncompressed");
  124.             }
  125.  
  126.             delete imageData;
  127.  
  128.             delete loader;
  129.         }
  130.         else
  131.         {
  132.             Engine::LoaderDevIL* loader = new Engine::LoaderDevIL(mLog);
  133.  
  134.             if (mImage != nullptr)
  135.             {
  136.                 delete mImage;
  137.                 mImage = nullptr;
  138.             }
  139.  
  140.             mImage = loader->Load(filename, true, true);
  141.             if (mImage != nullptr)
  142.             {
  143.                 loader->GenerateMipmaps(mImage);
  144.  
  145.                 mNumUncompressedMiplevels = (float)mImage->mMipLevels;
  146.  
  147.                 if (mUncompressed != nullptr)
  148.                 {
  149.                     delete mUncompressed;
  150.                 }
  151.                 mUncompressed = new Engine::Texture("Uncompressed");
  152.                 mUncompressed->InitMipmaps(mRenderer, mImage->mWidth, mImage->mHeight, 1, mImage->mMipLevels, mImage->mBpp <= 4 ? Engine::Graphics::RGBA8 : Engine::Graphics::RGBA32F, (const void**)mImage->mMipmaps);
  153.                 mUncompressed->SetName("Uncompressed");
  154.  
  155.                 delete mCompressed;
  156.                 mCompressed = nullptr;
  157.             }
  158.  
  159.             delete loader;
  160.         }
  161.     }
  162.  
  163.     void CompressTexture(Engine::TextureCompressor::Format format, bool dithering, bool generateMipmaps, bool alphaMipmap, bool normalMipmap, float exposure)
  164.     {
  165.         if (mImage != nullptr)
  166.         {
  167.             switch (format)
  168.             {
  169.             case Engine::TextureCompressor::Format::BC1:
  170.                 mCompressedFormat = Engine::Graphics::BC1;
  171.                 break;
  172.  
  173.             case Engine::TextureCompressor::Format::BC2:
  174.                 mCompressedFormat = Engine::Graphics::BC2;
  175.                 break;
  176.  
  177.             case Engine::TextureCompressor::Format::BC3:
  178.                 mCompressedFormat = Engine::Graphics::BC3;
  179.                 break;
  180.  
  181.             case Engine::TextureCompressor::Format::BC4:
  182.                 mCompressedFormat = Engine::Graphics::BC4;
  183.                 break;
  184.  
  185.             case Engine::TextureCompressor::Format::BC5:
  186.                 mCompressedFormat = Engine::Graphics::BC5;
  187.                 break;
  188.  
  189.             case Engine::TextureCompressor::Format::BC6H:
  190.                 mCompressedFormat = Engine::Graphics::BC6H;
  191.                 break;
  192.             }
  193.  
  194.             Engine::LoaderDevIL* loader = new Engine::LoaderDevIL(mLog);
  195.             mImage->mUseAlphaMipmap = alphaMipmap;
  196.             if (normalMipmap)
  197.             {
  198.                 loader->GenerateMipmapsNormal(mImage);
  199.             }
  200.             else
  201.             {
  202.                 loader->GenerateMipmaps(mImage);
  203.             }
  204.  
  205.             if (mUncompressed != nullptr)
  206.             {
  207.                 delete mUncompressed;
  208.             }
  209.             mUncompressed = new Engine::Texture("Uncompressed");
  210.             mUncompressed->InitMipmaps(mRenderer, mImage->mWidth, mImage->mHeight, 1, mImage->mMipLevels, mImage->mBpp <= 4 ? Engine::Graphics::RGBA8 : Engine::Graphics::RGBA32F, (const void**)mImage->mMipmaps);
  211.             mUncompressed->SetName("Uncompressed");
  212.  
  213.             delete loader;
  214.  
  215.             if (mCompressed != nullptr)
  216.             {
  217.                 delete mCompressed;
  218.             }
  219.             mCompressed = new Engine::Texture("Compressed");
  220.  
  221.             if (mCompressedData)
  222.             {
  223.                 for (int i = 0; i < mCompressedLevels; i++)
  224.                 {
  225.                     delete mCompressedData[i];
  226.                 }
  227.  
  228.                 delete[] mCompressedData;
  229.             }
  230.  
  231.             if (mCompressedWidth)
  232.             {
  233.                 delete[] mCompressedWidth;
  234.             }
  235.  
  236.             if (mCompressedHeight)
  237.             {
  238.                 delete[] mCompressedHeight;
  239.             }
  240.  
  241.             if (generateMipmaps)
  242.             {
  243.                 size_t width = mImage->mWidth;
  244.                 size_t height = mImage->mHeight;
  245.                 mCompressedLevels = 1;
  246.  
  247.                 while (width > 4 && height > 4)
  248.                 {
  249.                     width /= 2;
  250.                     height /= 2;
  251.  
  252.                     if ((width % 4 == 0) && (height % 4 == 0))
  253.                     {
  254.                         mCompressedLevels++;
  255.                     }
  256.                     else
  257.                     {
  258.                         break;
  259.                     }
  260.                 }
  261.  
  262.                 mCompressedWidth = new size_t[mCompressedLevels];
  263.                 mCompressedHeight = new size_t[mCompressedLevels];
  264.  
  265.                 width = mImage->mWidth;
  266.                 height = mImage->mHeight;
  267.  
  268.                 mCompressedData = new unsigned char*[mCompressedLevels];
  269.                 for (int i = 0; i < mCompressedLevels; i++)
  270.                 {
  271.                     mCompressedWidth[i] = width;
  272.                     mCompressedHeight[i] = height;
  273.  
  274.                     mCompressedData[i] = new unsigned char[mCompressedWidth[i] * mCompressedHeight[i] * Engine::Graphics::GetFormatSize(mCompressedFormat) / (Engine::Graphics::GetBlockSize(mCompressedFormat) * Engine::Graphics::GetBlockSize(mCompressedFormat))];
  275.  
  276.                     Engine::TextureCompressor::Compress(mCompressedWidth[i], mCompressedHeight[i], mCompressedData[i], mImage->mMipmaps[i], format, 4, true, dithering, mImage->mBpp == 16 ? true : false, exposure);
  277.  
  278.                     width /= 2;
  279.                     height /= 2;
  280.                 }
  281.  
  282.                 mNumCompressedMiplevels = (float)mCompressedLevels;
  283.  
  284.                 mCompressed->InitMipmaps(mRenderer, mCompressedWidth[0], mCompressedHeight[0], 1, mCompressedLevels, mCompressedFormat, (const void**)mCompressedData);
  285.             }
  286.             else
  287.             {
  288.                 mCompressedLevels = 1;
  289.                 mCompressedWidth = new size_t[mCompressedLevels];
  290.                 mCompressedHeight = new size_t[mCompressedLevels];
  291.                 mCompressedWidth[0] = mImage->mWidth;
  292.                 mCompressedHeight[0] = mImage->mHeight;
  293.  
  294.                 mCompressedData = new unsigned char*[mCompressedLevels];
  295.  
  296.                 mCompressedData[0] = new unsigned char[mCompressedWidth[0] * mCompressedHeight[0] * Engine::Graphics::GetFormatSize(mCompressedFormat) / (Engine::Graphics::GetBlockSize(mCompressedFormat) * Engine::Graphics::GetBlockSize(mCompressedFormat))];
  297.  
  298.                 Engine::TextureCompressor::Compress(mCompressedWidth[0], mCompressedHeight[0], mCompressedData[0], mImage->mData, format, 4, true, dithering, mImage->mBpp == 16 ? true : false, exposure);
  299.  
  300.                 mNumCompressedMiplevels = 1.0f;
  301.  
  302.                 mCompressed->Init(mRenderer, mCompressedWidth[0], mCompressedHeight[0], 1, mCompressedFormat, (const void*)mCompressedData[0]);
  303.             }
  304.  
  305.             mCompressed->SetName("Compressed");
  306.         }
  307.     }
  308.  
  309. public:
  310.     /// <summary>
  311.     /// Headless compression of input image into output image based on input parameters
  312.     ///
  313.     /// <para>Format types:</para>
  314.     /// <para>0 - BC1</para>
  315.     /// <para>1 - BC2</para>
  316.     /// <para>2 - BC3</para>
  317.     /// <para>3 - BC4</para>
  318.     /// <para>4 - BC5</para>
  319.     /// </summary>
  320.     /// <param name="log">Log to write errors/info into</param>
  321.     /// <param name="input">Input image filename</param>
  322.     /// <param name="output">Output image filename</param>
  323.     /// <param name="format">Format type</param>
  324.     /// <param name="dithering">Use dithering?</param>
  325.     /// <param name="generateMipmaps">Generate mipmaps?</param>
  326.     /// <param name="alphaMipmap">Use alpha conservation when generating mipmaps?</param>
  327.     /// <param name="normalMipmap">Generate normal-map mipmaps (renormalize each level)?</param>
  328.     /// <param name="exposure">Exposure value to pre-multiply original image with</param>
  329.     static void CompressHeadless(Engine::Log* log, const std::string& input, const std::string& output, int format, bool dithering, bool generateMipmaps, bool alphaMipmap, bool normalMipmap, float exposure)
  330.     {
  331.         Engine::LoaderDevIL* loader = new Engine::LoaderDevIL(log);
  332.  
  333.         Engine::LoaderDevIL::Image* image = loader->Load(input, true, true);
  334.         if (image != nullptr)
  335.         {
  336.  
  337.             Engine::TextureCompressor::Format compressFormat = (Engine::TextureCompressor::Format)format;
  338.  
  339.             Engine::Graphics::Format compressedFormat;
  340.             switch (compressFormat)
  341.             {
  342.             case Engine::TextureCompressor::Format::BC1:
  343.                 compressedFormat = Engine::Graphics::BC1;
  344.                 break;
  345.  
  346.             case Engine::TextureCompressor::Format::BC2:
  347.                 compressedFormat = Engine::Graphics::BC2;
  348.                 break;
  349.  
  350.             case Engine::TextureCompressor::Format::BC3:
  351.                 compressedFormat = Engine::Graphics::BC3;
  352.                 break;
  353.  
  354.             case Engine::TextureCompressor::Format::BC4:
  355.                 compressedFormat = Engine::Graphics::BC4;
  356.                 break;
  357.  
  358.             case Engine::TextureCompressor::Format::BC5:
  359.                 compressedFormat = Engine::Graphics::BC5;
  360.                 break;
  361.  
  362.             case Engine::TextureCompressor::Format::BC6H:
  363.                 compressedFormat = Engine::Graphics::BC6H;
  364.                 break;
  365.             }
  366.  
  367.             image->mUseAlphaMipmap = alphaMipmap;
  368.             if (normalMipmap)
  369.             {
  370.                 loader->GenerateMipmapsNormal(image);
  371.             }
  372.             else
  373.             {
  374.                 loader->GenerateMipmaps(image);
  375.             }
  376.  
  377.             size_t compressedLevels = 0;
  378.             size_t* compressedWidth = nullptr;
  379.             size_t* compressedHeight = nullptr;
  380.             unsigned char** compressedData = nullptr;
  381.  
  382.             if (generateMipmaps)
  383.             {
  384.                 size_t width = image->mWidth;
  385.                 size_t height = image->mHeight;
  386.                 compressedLevels = 1;
  387.  
  388.                 while (width > 4 && height > 4)
  389.                 {
  390.                     width /= 2;
  391.                     height /= 2;
  392.  
  393.                     if ((width % 4 == 0) && (height % 4 == 0))
  394.                     {
  395.                         compressedLevels++;
  396.                     }
  397.                     else
  398.                     {
  399.                         break;
  400.                     }
  401.                 }
  402.  
  403.                 compressedWidth = new size_t[compressedLevels];
  404.                 compressedHeight = new size_t[compressedLevels];
  405.  
  406.                 width = image->mWidth;
  407.                 height = image->mHeight;
  408.  
  409.                 compressedData = new unsigned char* [compressedLevels];
  410.                 for (int i = 0; i < compressedLevels; i++)
  411.                 {
  412.                     compressedWidth[i] = width;
  413.                     compressedHeight[i] = height;
  414.  
  415.                     compressedData[i] = new unsigned char[compressedWidth[i] * compressedHeight[i] * Engine::Graphics::GetFormatSize(compressedFormat) / (Engine::Graphics::GetBlockSize(compressedFormat) * Engine::Graphics::GetBlockSize(compressedFormat))];
  416.  
  417.                     Engine::TextureCompressor::Compress(compressedWidth[i], compressedHeight[i], compressedData[i], image->mMipmaps[i], compressFormat, 4, true, dithering, image->mBpp == 16 ? true : false, exposure);
  418.  
  419.                     width /= 2;
  420.                     height /= 2;
  421.                 }
  422.             }
  423.             else
  424.             {
  425.                 compressedLevels = 1;
  426.                 compressedWidth = new size_t[compressedLevels];
  427.                 compressedHeight = new size_t[compressedLevels];
  428.                 compressedWidth[0] = image->mWidth;
  429.                 compressedHeight[0] = image->mHeight;
  430.  
  431.                 compressedData = new unsigned char* [compressedLevels];
  432.  
  433.                 compressedData[0] = new unsigned char[compressedWidth[0] * compressedHeight[0] * Engine::Graphics::GetFormatSize(compressedFormat) / (Engine::Graphics::GetBlockSize(compressedFormat) * Engine::Graphics::GetBlockSize(compressedFormat))];
  434.  
  435.                 Engine::TextureCompressor::Compress(compressedWidth[0], compressedHeight[0],compressedData[0], image->mData, compressFormat, 4, true, dithering, image->mBpp == 16 ? true : false, exposure);
  436.             }
  437.  
  438.             // Save the image
  439.             Engine::LoaderSctex* sctexLoader = new Engine::LoaderSctex(log);
  440.  
  441.             std::vector<Engine::LoaderSctex::Image> data;
  442.  
  443.             for (size_t i = 0; i < compressedLevels; i++)
  444.             {
  445.                 Engine::LoaderSctex::Image image;
  446.                 image.mWidth = compressedWidth[i];
  447.                 image.mHeight = compressedHeight[i];
  448.                 image.mData = compressedData[i];
  449.  
  450.                 data.push_back(image);
  451.             }
  452.  
  453.             sctexLoader->Save(output, compressedFormat, data);
  454.  
  455.             delete sctexLoader;
  456.  
  457.             for (size_t i = 0; i < compressedLevels; i++)
  458.             {
  459.                 delete[] compressedData[i];
  460.             }
  461.  
  462.             delete compressedWidth;
  463.             delete compressedHeight;
  464.             delete compressedData;
  465.  
  466.             delete image;
  467.         }
  468.  
  469.         delete loader;
  470.     }
  471.  
  472.     Main(Engine::Log* log, Engine::Constants* options) : Engine::System("Main")
  473.     {
  474.         EnableUpdater();
  475.  
  476.         mLog = log;
  477.         mOptions = options;
  478.  
  479.         mWindow = new Engine::Window(log, options);
  480.         mWindow->Create();
  481.  
  482.         mRenderer = new Engine::D3DRenderer(mWindow, log, options);
  483.         mSwapChain = new Engine::D3DSwapChain(mRenderer, mWindow, log, options);
  484.  
  485.         static Engine::EventChannel chan;
  486.         chan.Add<Engine::Keyboard::KeyPressed>(*this);
  487.         chan.Add<Engine::Keyboard::KeyReleased>(*this);
  488.         chan.Add<Engine::Keyboard::KeyChar>(*this);
  489.         chan.Add<Engine::Mouse::MouseMove>(*this);
  490.         chan.Add<Engine::Mouse::ButtonPressed>(*this);
  491.         chan.Add<Engine::Mouse::ButtonReleased>(*this);
  492.         chan.Add<Engine::Mouse::MouseWheel>(*this);
  493.         chan.Add<Engine::Window::Resize>(*this);
  494.     }
  495.  
  496.     virtual ~Main()
  497.     {
  498.         for (int i = 0; i < mCompressedLevels; i++)
  499.         {
  500.             delete mCompressedData[i];
  501.         }
  502.         delete[] mCompressedData;
  503.  
  504.         delete[] mCompressedWidth;
  505.         delete[] mCompressedHeight;
  506.  
  507.         delete mImage;
  508.         delete mCompressed;
  509.         delete mUncompressed;
  510.  
  511.         delete mSwapChain;
  512.         delete mRenderer;
  513.         delete mWindow;
  514.     }
  515.  
  516.     virtual bool Init()
  517.     {
  518.         int w;
  519.         int h;
  520.         this->mWindow->GetSize(&w, &h);
  521.  
  522.         mTexturesPass = new SkyeCuillin::RenderPassGUI(mRenderer, w, h);
  523.  
  524.         mImgui = new SkyeCuillin::ImguiSubsystem(mRenderer, w, h);
  525.         ImGui::GetStyle().WindowBorderSize = 0;
  526.  
  527.         LoadTexture("../Data/Shared/Test.png");
  528.         CompressTexture(Engine::TextureCompressor::Format::BC1, true, true, false, false, 1.0f);
  529.  
  530.         return true;
  531.     }
  532.  
  533.     virtual void Shutdown()
  534.     {
  535.         mRenderer->Flush();
  536.  
  537.         delete mImgui;
  538.  
  539.         delete mTexturesPass;
  540.  
  541.         mWindow->Destroy();
  542.     }
  543.  
  544.     virtual void Update()
  545.     {
  546.         static bool compressionShow = false;
  547.  
  548.  
  549.         int w;
  550.         int h;
  551.         mWindow->GetSize(&w, &h);
  552.  
  553.         mWindow->Process();
  554.  
  555.         Engine::GraphicsContext* context = mRenderer->GetGraphicsContext();
  556.  
  557.         context->Begin();
  558.         context->SetDescriptorHeap(Engine::DescriptorHeap::CBV_SRV_UAV, mRenderer->Heap());
  559.         context->TransitionResource(mSwapChain->GetBackBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET, true);
  560.         context->SetRenderTargets(mSwapChain->GetBackBuffer(), mSwapChain->GetDepthBuffer());
  561.         context->SetViewport(0.0f, 0.0f, (float)w, (float)h);
  562.         context->SetScissorRect(0.0f, 0.0f, (float)w, (float)h);
  563.         context->ClearColor(mSwapChain->GetBackBuffer(), 0.0f, 0.0f, 0.0f, 1.0f);
  564.         context->ClearDepth(mSwapChain->GetDepthBuffer(), 1.0f, 0);
  565.  
  566.         static bool alphaMask = false;
  567.         static float exposure = 1.0f;
  568.         static int mode = 0;
  569.  
  570.         Engine::float3 mUV[2] = {
  571.             mTransform * Engine::float3(-1.0f, -1.0f, 1.0f),
  572.             mTransform * Engine::float3(1.0f, 1.0f, 1.0f)
  573.         };
  574.  
  575.         mTexturesPass->Clear();
  576.         if (mUncompressed != nullptr)
  577.         {
  578.             mUncompressedMiplevel = mCurrentMiplevel;
  579.             if (mCurrentMiplevel >= mNumUncompressedMiplevels)
  580.             {
  581.                 mUncompressedMiplevel = mNumUncompressedMiplevels - 1.0f;
  582.             }
  583.             mTexturesPass->AddSprite(Engine::float2(0.0f, 0.0f),
  584.                 Engine::float2(0.5f, 1.0f),
  585.                 Engine::float2(mUV[0].x, mUV[0].y) * 0.5f + 0.5f,
  586.                 Engine::float2(mUV[1].x, mUV[1].y) * 0.5f + 0.5f,
  587.                 Engine::float4(exposure, exposure, exposure, 1.0f),
  588.                 mUncompressed,
  589.                 mUncompressedMiplevel,
  590.                 alphaMask ? mode + 5 : mode);
  591.         }
  592.         if (mCompressed != nullptr)
  593.         {
  594.             mCompressedMiplevel = mCurrentMiplevel;
  595.             if (mCurrentMiplevel >= mNumCompressedMiplevels)
  596.             {
  597.                 mCompressedMiplevel = mNumCompressedMiplevels - 1.0f;
  598.             }
  599.             mTexturesPass->AddSprite(Engine::float2(0.5f, 0.0f),
  600.                 Engine::float2(0.5f, 1.0f),
  601.                 Engine::float2(mUV[0].x, mUV[0].y) * 0.5f + 0.5f,
  602.                 Engine::float2(mUV[1].x, mUV[1].y) * 0.5f + 0.5f,
  603.                 Engine::float4(exposure, exposure, exposure, 1.0f),
  604.                 mCompressed,
  605.                 mCompressedMiplevel,
  606.                 alphaMask ? mode + 5 : mode);
  607.         }
  608.  
  609.         mTexturesPass->Render(mRenderer->Heap(), context);
  610.  
  611.         bool loadTexture = false;
  612.         std::string textureFilename;
  613.  
  614.         mImgui->Update(context);
  615.         mImgui->NewFrame();
  616.         ImGui::SetNextWindowSize(ImVec2((float)w, 20.0f), ImGuiCond_Always);
  617.         ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f));
  618.         ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
  619.         if (ImGui::Begin("Menu", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_MenuBar))
  620.         {
  621.             if (ImGui::BeginMenuBar())
  622.             {
  623.                 if (ImGui::BeginMenu("File"))
  624.                 {
  625.                     if (ImGui::MenuItem("Open", "CTRL+O", nullptr))
  626.                     {
  627.                         std::string filename;
  628.                         bool open = Engine::FileDialog::Show(mLog, "Open Image", "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.tga;*.dds;*.tif;*.gif;*.sctex\0All Files\0*.*\0", Engine::FileDialog::Type::OPEN_FILE_DIALOG, filename);
  629.                         if (open)
  630.                         {
  631.                             textureFilename = filename;
  632.                             loadTexture = true;
  633.  
  634.                             // Reset miplevel, view and exposure when loading a new image
  635.                             mCurrentMiplevel = 0.0f;
  636.                             mTransform = Engine::mat3();
  637.                             exposure = 1.0f;
  638.                         }
  639.                     }
  640.  
  641.                     if (ImGui::MenuItem("Save", "CTRL+S", nullptr))
  642.                     {
  643.                         std::string filename;
  644.                         bool save = Engine::FileDialog::Show(mLog, "Save Compressed Image", "Skye Cuillin Texture\0*.sctex\0All Files\0*.*\0", Engine::FileDialog::Type::SAVE_FILE_DIALOG, filename);
  645.                         if (save)
  646.                         {
  647.                             Engine::LoaderSctex* sctexLoader = new Engine::LoaderSctex(mLog);
  648.  
  649.                             std::vector<Engine::LoaderSctex::Image> data;
  650.  
  651.                             for (size_t i = 0; i < mCompressedLevels; i++)
  652.                             {
  653.                                 Engine::LoaderSctex::Image image;
  654.                                 image.mWidth = mCompressedWidth[i];
  655.                                 image.mHeight = mCompressedHeight[i];
  656.                                 image.mData = mCompressedData[i];
  657.  
  658.                                 data.push_back(image);
  659.                             }
  660.  
  661.                             sctexLoader->Save(filename, mCompressedFormat, data);
  662.  
  663.                             delete sctexLoader;
  664.                         }
  665.                     }
  666.  
  667.                     if (ImGui::MenuItem("Exit"))
  668.                     {
  669.                         static Engine::EventChannel chan;
  670.                         chan.Broadcast(Engine::Scheduler::StopEvent());
  671.                     }
  672.  
  673.                     ImGui::EndMenu();
  674.                 }
  675.  
  676.                 if (ImGui::BeginMenu("Edit"))
  677.                 {
  678.                     if (ImGui::MenuItem("Compress"))
  679.                     {
  680.                         compressionShow = true;
  681.                     }
  682.  
  683.                     ImGui::EndMenu();
  684.                 }
  685.  
  686.                 if (ImGui::BeginMenu("View"))
  687.                 {
  688.                     if (ImGui::MenuItem("Mip Level Up"))
  689.                     {
  690.                         mCurrentMiplevel = mCurrentMiplevel - 1.0f;
  691.                         if (mCurrentMiplevel < 0.0f)
  692.                         {
  693.                             mCurrentMiplevel = 0.0f;
  694.                         }
  695.                     }
  696.  
  697.                     if (ImGui::MenuItem("Mip Level Down"))
  698.                     {
  699.                         mCurrentMiplevel = mCurrentMiplevel + 1.0f;
  700.                         float maxLevel = Engine::Math::Max(mNumCompressedMiplevels, mNumUncompressedMiplevels);
  701.                         if (mCurrentMiplevel >= maxLevel)
  702.                         {
  703.                             mCurrentMiplevel = maxLevel - 1.0f;
  704.                         }
  705.                     }
  706.  
  707.                     if (ImGui::MenuItem("Reset View"))
  708.                     {
  709.                         mTransform = Engine::mat3();
  710.                     }
  711.  
  712.                     if (ImGui::MenuItem("Reset Exposure"))
  713.                     {
  714.                         exposure = 1.0f;
  715.                     }
  716.  
  717.                     ImGui::EndMenu();
  718.                 }
  719.  
  720.                 ImGui::RadioButton("C", &mode, 0);
  721.                 ImGui::RadioButton("R", &mode, 1);
  722.                 ImGui::RadioButton("G", &mode, 2);
  723.                 ImGui::RadioButton("B", &mode, 3);
  724.                 ImGui::RadioButton("A", &mode, 4);
  725.  
  726.                 ImGui::Checkbox("Alpha Mask", &alphaMask);
  727.  
  728.                 ImGui::SliderFloat("Exposure", &exposure, 0.0f, 10.0f);
  729.  
  730.                 ImGui::EndMenuBar();
  731.             }
  732.         }
  733.         ImGui::End();
  734.         ImGui::PopStyleVar();
  735.  
  736.         if (compressionShow)
  737.         {
  738.             if (ImGui::Begin("Compress", nullptr, ImGuiWindowFlags_NoCollapse))
  739.             {
  740.                 const char* compression[] = { "BC1", "BC2", "BC3", "BC4", "BC5", "BC6H"};
  741.                 static int compressionSelected = 0;
  742.                 ImGui::Combo("Compression Type", &compressionSelected, compression, IM_ARRAYSIZE(compression));
  743.  
  744.                 static bool dithering = false;
  745.                 ImGui::Checkbox("Use Dithering", &dithering);
  746.  
  747.                 static bool generateMipmaps = false;
  748.                 ImGui::Checkbox("Generate Mipmaps", &generateMipmaps);
  749.  
  750.                 static bool alphaMipmaps = false;
  751.                 ImGui::Checkbox("Alpha Mipmaps", &alphaMipmaps);
  752.  
  753.                 static bool normalMipmaps = false;
  754.                 ImGui::Checkbox("Normal Mipmaps", &normalMipmaps);
  755.  
  756.                 if (ImGui::Button("Compress"))
  757.                 {
  758.                     CompressTexture((Engine::TextureCompressor::Format)compressionSelected, dithering, generateMipmaps, alphaMipmaps, normalMipmaps, exposure);
  759.                     compressionShow = false;
  760.                 }
  761.                 ImGui::SameLine();
  762.                 if (ImGui::Button("Cancel"))
  763.                 {
  764.                     compressionShow = false;
  765.                 }
  766.             }
  767.             ImGui::End();
  768.         }
  769.  
  770.         ImGui::SetNextWindowSize(ImVec2((float)w, 24.0f), ImGuiCond_Always);
  771.         ImGui::SetNextWindowPos(ImVec2(0.0f, (float)h - 24.0f));
  772.         ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
  773.         if (ImGui::Begin("StatusBar", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse))
  774.         {
  775.             ImGui::Text("Mip Level %2f    Position (%4f, %4f)", mCurrentMiplevel, (mUV[0].x + mUV[1].x) * 0.5f, (mUV[1].y + mUV[1].y) * 0.5f);
  776.         }
  777.         ImGui::End();
  778.         ImGui::PopStyleVar();
  779.  
  780.         mImgui->Render();
  781.  
  782.         context->TransitionResource(mSwapChain->GetBackBuffer(), D3D12_RESOURCE_STATE_PRESENT, true);
  783.         uint64_t fence = context->Finish();
  784.  
  785.         mSwapChain->SwapBuffers();
  786.  
  787.         if (loadTexture)
  788.         {
  789.             LoadTexture(textureFilename);
  790.         }
  791.     }
  792.  
  793.     void Handle(const Engine::Keyboard::KeyChar& kc)
  794.     {
  795.         ImGuiIO& io = ImGui::GetIO();
  796.  
  797.         if (kc.mKey < 256)
  798.         {
  799.             io.AddInputCharacter((ImWchar)kc.mKey);
  800.         }
  801.     }
  802.  
  803.     void Handle(const Engine::Keyboard::KeyPressed& kp)
  804.     {
  805.         ImGuiIO& io = ImGui::GetIO();
  806.         io.KeysDown[kp.mKey] = 1;
  807.  
  808.         Engine::Input* input = (Engine::Input*)Engine::Core::Instance()->Get("Input");
  809.         /*if (input->GetKeyboard()->GetKeyState(Engine::Keyboard::KEY_CONTROL_L))
  810.         {
  811.             io.AddInputCharacter((ImWchar)kp.mKey);
  812.         }*/
  813.  
  814.         switch (kp.mKey)
  815.         {
  816.         case Engine::Keyboard::KEY_CONTROL_L:
  817.             io.KeyCtrl = true;
  818.             break;
  819.  
  820.         case Engine::Keyboard::KEY_ALT_L:
  821.             io.KeyAlt = true;
  822.             break;
  823.  
  824.         case Engine::Keyboard::KEY_SHIFT_L:
  825.             io.KeyShift = true;
  826.             break;
  827.         }
  828.  
  829.         switch (kp.mKey)
  830.         {
  831.         case Engine::Keyboard::KEY_PAGE_UP:
  832.             mCurrentMiplevel = mCurrentMiplevel - 1.0f;
  833.             if (mCurrentMiplevel < 0.0f)
  834.             {
  835.                 mCurrentMiplevel = 0.0f;
  836.             }
  837.             break;
  838.  
  839.         case Engine::Keyboard::KEY_PAGE_DOWN:
  840.             mCurrentMiplevel = mCurrentMiplevel + 1.0f;
  841.             float maxLevel = Engine::Math::Max(mNumCompressedMiplevels, mNumUncompressedMiplevels);
  842.             if (mCurrentMiplevel >= maxLevel)
  843.             {
  844.                 mCurrentMiplevel = maxLevel - 1.0f;
  845.             }
  846.             break;
  847.         }
  848.     }
  849.  
  850.     void Handle(const Engine::Keyboard::KeyReleased& kp)
  851.     {
  852.         ImGuiIO& io = ImGui::GetIO();
  853.         io.KeysDown[kp.mKey] = 0;
  854.  
  855.         switch (kp.mKey)
  856.         {
  857.         case Engine::Keyboard::KEY_CONTROL_L:
  858.             io.KeyCtrl = false;
  859.             break;
  860.  
  861.         case Engine::Keyboard::KEY_ALT_L:
  862.             io.KeyAlt = false;
  863.             break;
  864.  
  865.         case Engine::Keyboard::KEY_SHIFT_L:
  866.             io.KeyShift = false;
  867.             break;
  868.         }
  869.     }
  870.  
  871.     bool mMousing = false;
  872.    
  873.     float mPrevMouse[2];
  874.  
  875.     void Handle(const Engine::Mouse::MouseMove& m)
  876.     {
  877.         ImGuiIO& io = ImGui::GetIO();
  878.         io.MousePos.x = (float)m.mX;
  879.         io.MousePos.y = (float)m.mY;
  880.  
  881.         // Check whether we're moving with mouse and whether mouse isn't over ImGUI panels/windows - if both apply, update viewport transform
  882.         if (mMousing && !io.WantCaptureMouse)
  883.         {
  884.             float mDeltaMouse[2];
  885.             mDeltaMouse[0] = mPrevMouse[0] - (float)m.mX;
  886.             mDeltaMouse[1] = mPrevMouse[1] - (float)m.mY;
  887.  
  888.             int w = 0;
  889.             int h = 0;
  890.             mWindow->GetSize(&w, &h);
  891.  
  892.             Engine::float3 transform = Engine::float3(mDeltaMouse[0] * 1.0f / (float)w, mDeltaMouse[1] * 1.0f / (float)h, 1.0f);
  893.  
  894.             mTransform = mTransform * Engine::mat3(transform);
  895.         }
  896.  
  897.         mPrevMouse[0] = (float)m.mX;
  898.         mPrevMouse[1] = (float)m.mY;
  899.     }
  900.  
  901.     void Handle(const Engine::Mouse::MouseWheel& m)
  902.     {
  903.         ImGuiIO& io = ImGui::GetIO();
  904.         io.MouseWheel = (float)m.mDelta / 120.0f;
  905.  
  906.         // Check whether mouse isn't over ImGUI panels/windows - if it isn't, zoom in/out viewport
  907.         if (!io.WantCaptureMouse)
  908.         {
  909.             if (m.mDelta < 0)
  910.             {
  911.                 mTransform = mTransform * Engine::mat3(1.1f, 0.0f, 0.0f, 0.0f, 1.1f, 0.0f, 0.0f, 0.0f, 1.0f);
  912.             }
  913.             else if (m.mDelta > 0)
  914.             {
  915.                 mTransform = mTransform * Engine::mat3(0.9f, 0.0f, 0.0f, 0.0f, 0.9f, 0.0f, 0.0f, 0.0f, 1.0f);
  916.             }
  917.         }
  918.     }
  919.  
  920.     void Handle(const Engine::Mouse::ButtonPressed& bp)
  921.     {
  922.         ImGuiIO& io = ImGui::GetIO();
  923.         io.MouseDown[bp.mButton] = true;
  924.  
  925.         if (bp.mButton == 0)
  926.         {
  927.             mMousing = true;
  928.         }
  929.     }
  930.  
  931.     void Handle(const Engine::Mouse::ButtonReleased& br)
  932.     {
  933.         ImGuiIO& io = ImGui::GetIO();
  934.         io.MouseDown[br.mButton] = false;
  935.  
  936.         if (br.mButton == 0)
  937.         {
  938.             mMousing = false;
  939.         }
  940.     }
  941.  
  942.     void Handle(const Engine::Window::Resize& r)
  943.     {
  944.         mSwapChain->Resize(r.mWidth, r.mHeight);
  945.         mImgui->Resize(r.mWidth, r.mHeight);
  946.         mTexturesPass->Resize(r.mWidth, r.mHeight);
  947.     }
  948. };
  949.  
  950. int main(int argc, char** argv)
  951. {
  952.     Engine::Log* log = new Engine::Log();
  953.     log->AddOutput(new std::ofstream("Output.log"), Engine::Log::LOG_DEFAULT);
  954.  
  955.     if (argc > 1)
  956.     {
  957.         int inputIndex = -1;
  958.         std::string input;
  959.         int outputIndex = -1;
  960.         std::string output;
  961.         int formatIndex = -1;
  962.         int format = 0;
  963.         bool dithering = false;
  964.         bool mipmaps = false;
  965.         bool alphaMipmaps = false;
  966.         bool normalMipmaps = false;
  967.         bool useExposure = false;
  968.         int exposureIndex = -1;
  969.         float exposure = 1.0f;
  970.  
  971.         for (int i = 0; i < argc; i++)
  972.         {
  973.             std::string arg = std::string(argv[i]);
  974.  
  975.             if ((arg == "--input" || arg == "-i") && argc >(i + 1) && inputIndex == -1)
  976.             {
  977.                 inputIndex = i + 1;
  978.             }
  979.             else if ((arg == "--output" || arg == "-o") && argc > (i + 1) && outputIndex == -1)
  980.             {
  981.                 outputIndex = i + 1;
  982.             }
  983.             else if ((arg == "--format" || arg == "-f") && argc > (i + 1) && formatIndex == -1)
  984.             {
  985.                 formatIndex = i + 1;
  986.             }
  987.             else if (arg == "--dithering" || arg == "-d")
  988.             {
  989.                 dithering = true;
  990.             }
  991.             else if (arg == "--mipmaps" || arg == "-m")
  992.             {
  993.                 mipmaps = true;
  994.             }
  995.             else if (arg == "--alpha" || arg == "-a")
  996.             {
  997.                 alphaMipmaps = true;
  998.             }
  999.             else if (arg == "--normals" || arg == "-n")
  1000.             {
  1001.                 normalMipmaps = true;
  1002.             }
  1003.             else if ((arg == "--exposure" || arg == "-e") && argc > (i + 1) && exposureIndex == -1)
  1004.             {
  1005.                 useExposure = true;
  1006.                 exposureIndex = i + 1;
  1007.             }
  1008.         }
  1009.  
  1010.         input = argv[inputIndex];
  1011.         if (input[0] == '\"')
  1012.         {
  1013.             input = input.substr(1, input.length() - 2);
  1014.         }
  1015.  
  1016.         output = argv[outputIndex];
  1017.         if (output[0] == '\"')
  1018.         {
  1019.             output = output.substr(1, output.length() - 2);
  1020.         }
  1021.  
  1022.         format = std::atoi(argv[formatIndex]);
  1023.  
  1024.         if (exposureIndex > -1)
  1025.         {
  1026.             exposure = std::atof(argv[exposureIndex]);
  1027.         }
  1028.  
  1029.         if (inputIndex == -1 || outputIndex == -1 || formatIndex == -1 || input.length() == 0 || output.length() == 0 || format < 0 || format > 4)
  1030.         {
  1031.             std::cout << "Error: Invalid arguments, required arguments are:" << std::endl << std::endl;
  1032.             std::cout << "--input, -i" << std::endl;
  1033.             std::cout << "\tPath to input image file (*.*)" << std::endl;
  1034.             std::cout << "--output, -o" << std::endl;
  1035.             std::cout << "\tPath to output image file (*.sctex)" << std::endl;
  1036.             std::cout << "--format, -f" << std::endl;
  1037.             std::cout << "\tFormat to use for compression (0 - BC1, 1 - BC2, 2 - BC3, 3 - BC4, 4 - BC5)" << std::endl;
  1038.             std::cout << "--dithering, -d" << std::endl;
  1039.             std::cout << "\tUse dithering to improve" << std::endl;
  1040.             std::cout << "--mipmaps, -m" << std::endl;
  1041.             std::cout << "\tPath to input image file" << std::endl;
  1042.             std::cout << "--alpha, -a" << std::endl;
  1043.             std::cout << "\tPath to input image file" << std::endl;
  1044.             std::cout << "--normals, -n" << std::endl;
  1045.             std::cout << "\tPath to input image file" << std::endl;
  1046.             std::cout << "--exposure, -e" << std::endl;
  1047.             std::cout << "\tExposure value - decimal number, default is 1.0" << std::endl;
  1048.         }
  1049.         else
  1050.         {
  1051.             Main::CompressHeadless(log, input, output, format, dithering, mipmaps, alphaMipmaps, normalMipmaps, exposure);
  1052.         }
  1053.     }
  1054.     else
  1055.     {
  1056.         Engine::Constants* options = new Engine::Constants(log, "../Data/Config/ConfigTexture.conf");
  1057.  
  1058.         Engine::Input* input = new Engine::Input();
  1059.  
  1060.         Main* m = new Main(log, options);
  1061.  
  1062.         Engine::Core::Instance()->Add(input);
  1063.         Engine::Core::Instance()->Add(m);
  1064.         Engine::Core::Instance()->SetLog(log);
  1065.         Engine::Core::Instance()->SetOptions(options);
  1066.  
  1067.         Engine::Core::Instance()->Run();
  1068.  
  1069.         Engine::Core::Instance()->Dispose();
  1070.  
  1071.         delete m;
  1072.         delete input;
  1073.         delete options;
  1074.     }
  1075.  
  1076.     delete log;
  1077.  
  1078.     Engine::MemoryDump(std::cout);
  1079.  
  1080.     return 0;
  1081. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement