105 lines
4.1 KiB
C++
105 lines
4.1 KiB
C++
#include "ShaderTextureBindings.h"
|
|
|
|
#include "GlRenderConstants.h"
|
|
#include "TextRasterizer.h"
|
|
#include "TextureAssetLoader.h"
|
|
|
|
#include <algorithm>
|
|
#include <filesystem>
|
|
|
|
namespace
|
|
{
|
|
std::string TextValueForBinding(const RuntimeRenderState& state, const std::string& parameterId)
|
|
{
|
|
auto valueIt = state.parameterValues.find(parameterId);
|
|
return valueIt == state.parameterValues.end() ? std::string() : valueIt->second.textValue;
|
|
}
|
|
|
|
const ShaderFontAsset* FindFontAssetForParameter(const RuntimeRenderState& state, const ShaderParameterDefinition& definition)
|
|
{
|
|
if (!definition.fontId.empty())
|
|
{
|
|
for (const ShaderFontAsset& fontAsset : state.fontAssets)
|
|
{
|
|
if (fontAsset.id == definition.fontId)
|
|
return &fontAsset;
|
|
}
|
|
}
|
|
return state.fontAssets.empty() ? nullptr : &state.fontAssets.front();
|
|
}
|
|
}
|
|
|
|
bool ShaderTextureBindings::LoadTextureAsset(const ShaderTextureAsset& textureAsset, GLuint& textureId, std::string& error)
|
|
{
|
|
return ::LoadTextureAsset(textureAsset, textureId, error);
|
|
}
|
|
|
|
void ShaderTextureBindings::CreateTextBindings(const RuntimeRenderState& state, std::vector<LayerProgram::TextBinding>& textBindings)
|
|
{
|
|
for (const ShaderParameterDefinition& definition : state.parameterDefinitions)
|
|
{
|
|
if (definition.type != ShaderParameterType::Text)
|
|
continue;
|
|
LayerProgram::TextBinding textBinding;
|
|
textBinding.parameterId = definition.id;
|
|
textBinding.samplerName = definition.id + "Texture";
|
|
textBinding.fontId = definition.fontId;
|
|
glGenTextures(1, &textBinding.texture);
|
|
glBindTexture(GL_TEXTURE_2D, textBinding.texture);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
std::vector<unsigned char> empty(static_cast<std::size_t>(kTextTextureWidth) * kTextTextureHeight * 4, 0);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTextTextureWidth, kTextTextureHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, empty.data());
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
textBindings.push_back(textBinding);
|
|
}
|
|
}
|
|
|
|
bool ShaderTextureBindings::UpdateTextBindingTexture(const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error)
|
|
{
|
|
const std::string text = TextValueForBinding(state, textBinding.parameterId);
|
|
if (text == textBinding.renderedText && textBinding.renderedWidth == kTextTextureWidth && textBinding.renderedHeight == kTextTextureHeight)
|
|
return true;
|
|
|
|
auto definitionIt = std::find_if(state.parameterDefinitions.begin(), state.parameterDefinitions.end(),
|
|
[&textBinding](const ShaderParameterDefinition& definition) { return definition.id == textBinding.parameterId; });
|
|
if (definitionIt == state.parameterDefinitions.end())
|
|
return true;
|
|
|
|
const ShaderFontAsset* fontAsset = FindFontAssetForParameter(state, *definitionIt);
|
|
std::filesystem::path fontPath;
|
|
if (fontAsset)
|
|
fontPath = fontAsset->path;
|
|
|
|
std::vector<unsigned char> sdf;
|
|
if (!RasterizeTextSdf(text, fontPath, sdf, error))
|
|
return false;
|
|
|
|
GLint previousActiveTexture = 0;
|
|
GLint previousUnpackBuffer = 0;
|
|
glGetIntegerv(GL_ACTIVE_TEXTURE, &previousActiveTexture);
|
|
glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &previousUnpackBuffer);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
|
glBindTexture(GL_TEXTURE_2D, textBinding.texture);
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextTextureWidth, kTextTextureHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, sdf.data());
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, static_cast<GLuint>(previousUnpackBuffer));
|
|
glActiveTexture(static_cast<GLenum>(previousActiveTexture));
|
|
|
|
textBinding.renderedText = text;
|
|
textBinding.renderedWidth = kTextTextureWidth;
|
|
textBinding.renderedHeight = kTextTextureHeight;
|
|
return true;
|
|
}
|
|
|
|
GLint ShaderTextureBindings::FindSamplerUniformLocation(GLuint program, const std::string& samplerName) const
|
|
{
|
|
GLint location = glGetUniformLocation(program, samplerName.c_str());
|
|
if (location >= 0)
|
|
return location;
|
|
return glGetUniformLocation(program, (samplerName + "_0").c_str());
|
|
}
|