#include "ShaderTextureBindings.h" #include "GlRenderConstants.h" #include "TextRasterizer.h" #include "TextureAssetLoader.h" #include #include 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& 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 empty(static_cast(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 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(previousUnpackBuffer)); glActiveTexture(static_cast(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()); }