LUT interpolation
This commit is contained in:
@@ -4,12 +4,120 @@
|
||||
#include <wincodec.h>
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifndef GL_RGBA32F
|
||||
#define GL_RGBA32F 0x8814
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string LowercaseExtension(const std::filesystem::path& path)
|
||||
{
|
||||
std::string extension = path.extension().string();
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(),
|
||||
[](unsigned char value) { return static_cast<char>(std::tolower(value)); });
|
||||
return extension;
|
||||
}
|
||||
|
||||
bool LoadCubeTextureAsset(const ShaderTextureAsset& textureAsset, GLuint& textureId, std::string& error)
|
||||
{
|
||||
std::ifstream file(textureAsset.path);
|
||||
if (!file)
|
||||
{
|
||||
error = "Could not open shader LUT asset: " + textureAsset.path.string();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned lutSize = 0;
|
||||
std::vector<float> values;
|
||||
std::string line;
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
const std::size_t commentStart = line.find('#');
|
||||
if (commentStart != std::string::npos)
|
||||
line.resize(commentStart);
|
||||
|
||||
std::istringstream stream(line);
|
||||
std::string firstToken;
|
||||
if (!(stream >> firstToken))
|
||||
continue;
|
||||
|
||||
if (firstToken == "TITLE" || firstToken == "DOMAIN_MIN" || firstToken == "DOMAIN_MAX")
|
||||
continue;
|
||||
if (firstToken == "LUT_3D_SIZE")
|
||||
{
|
||||
stream >> lutSize;
|
||||
continue;
|
||||
}
|
||||
if (firstToken == "LUT_1D_SIZE")
|
||||
{
|
||||
error = "Only 3D .cube LUT assets are supported: " + textureAsset.path.string();
|
||||
return false;
|
||||
}
|
||||
|
||||
float red = 0.0f;
|
||||
float green = 0.0f;
|
||||
float blue = 0.0f;
|
||||
try
|
||||
{
|
||||
red = std::stof(firstToken);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "Unsupported .cube directive in shader LUT asset: " + firstToken;
|
||||
return false;
|
||||
}
|
||||
if (!(stream >> green >> blue))
|
||||
{
|
||||
error = "Malformed RGB entry in shader LUT asset: " + textureAsset.path.string();
|
||||
return false;
|
||||
}
|
||||
values.push_back(red);
|
||||
values.push_back(green);
|
||||
values.push_back(blue);
|
||||
values.push_back(1.0f);
|
||||
}
|
||||
|
||||
if (lutSize == 0)
|
||||
{
|
||||
error = "Shader LUT asset is missing LUT_3D_SIZE: " + textureAsset.path.string();
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::size_t expectedFloats = static_cast<std::size_t>(lutSize) * lutSize * lutSize * 4;
|
||||
if (values.size() != expectedFloats)
|
||||
{
|
||||
error = "Shader LUT asset entry count does not match LUT_3D_SIZE: " + textureAsset.path.string();
|
||||
return false;
|
||||
}
|
||||
|
||||
const GLsizei atlasWidth = static_cast<GLsizei>(lutSize * lutSize);
|
||||
const GLsizei atlasHeight = static_cast<GLsizei>(lutSize);
|
||||
glGenTextures(1, &textureId);
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, atlasWidth, atlasHeight, 0, GL_RGBA, GL_FLOAT, values.data());
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadTextureAsset(const ShaderTextureAsset& textureAsset, GLuint& textureId, std::string& error)
|
||||
{
|
||||
textureId = 0;
|
||||
if (LowercaseExtension(textureAsset.path) == ".cube")
|
||||
return LoadCubeTextureAsset(textureAsset, textureId, error);
|
||||
|
||||
HRESULT comInitResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
const bool shouldUninitializeCom = (comInitResult == S_OK || comInitResult == S_FALSE);
|
||||
|
||||
Reference in New Issue
Block a user