Clean up shader initialization and preserve optional rendering fallbacks

The fixed-function renderer was removed, but shader capability guards,
bitmap text paths, and legacy attribute state still implied a working
shaderless fallback. Remove that obsolete state and check shader support
once when initializing rendering resources.

Return detailed context and shader errors through lcResult and show fatal
startup errors in GUI mode. Keep lighting, conditional lines, SDF text,
view sphere, and outlines optional, with program validity checks selecting
Flat shading, skipping unavailable overlays, or retaining selection tint.
Non-rendering exports initialize only the context needed for asset loading.

Apply icon availability to every parts list without overwriting requested
sizes. Disable unavailable lighting and view-sphere preference controls,
make attribute aliases explicit, and prevent signed-byte glyph indexing.

Validation: macOS debug build, GUI and image export under forced optional
shader compile/link failures, Flat fallback image comparisons, export
initialization checks, preference preservation, and glyph byte-range checks.
This commit is contained in:
Leonardo Zide committed 2026-10-11 21:00:12 -07:00
1 parent 75dc3883da
commit a84c3d7b7e
16 files changed
+457 -524

No files matched your search

+2 -3
View File
@@ -36,14 +36,13 @@ lcAboutDialog::lcAboutDialog(QWidget* Parent)
const QString BuffersFormat = tr("Color Buffer: %1 bits\nDepth Buffer: %2 bits\nStencil Buffer: %3 bits\n\n");
const QString Buffers = BuffersFormat.arg(QString::number(ColorDepth), QString::number(Format.depthBufferSize()), QString::number(Format.stencilBufferSize()));
const QString ExtensionsFormat = tr("Buffers: %1\nShaders: %2\nFramebuffers: %3\nBlendFuncSeparate: %4\nAnisotropic: %5\n");
const QString ExtensionsFormat = tr("Buffers: %1\nFramebuffers: %2\nBlendFuncSeparate: %3\nAnisotropic: %4\n");
const QString VertexBuffers = gSupportsVertexBufferObject ? tr("Supported") : tr("Not supported");
const QString Shaders = gSupportsShaderObjects ? tr("Supported") : tr("Not supported");
const QString Framebuffers = gSupportsFramebufferObject ? tr("Supported") : tr("Not supported");
const QString BlendFuncSeparate = gSupportsBlendFuncSeparate ? tr("Supported") : tr("Not supported");
const QString Anisotropic = gSupportsAnisotropic ? tr("Supported (max %1)").arg(gMaxAnisotropy) : tr("Not supported");
const QString Extensions = ExtensionsFormat.arg(VertexBuffers, Shaders, Framebuffers, BlendFuncSeparate, Anisotropic);
const QString Extensions = ExtensionsFormat.arg(VertexBuffers, Framebuffers, BlendFuncSeparate, Anisotropic);
ui->info->setText(QtVersion + Version + Buffers + Extensions);
}
+20 -5
View File
@@ -946,6 +946,8 @@ lcStartupMode lcApplication::Initialize(const QList<QPair<QString, bool>>& Libra
if (Options.Exit)
return lcStartupMode::Success;
const bool SaveAndExit = (Options.SaveImage || Options.SaveWavefront || Options.Save3DS || Options.SaveCOLLADA || Options.SaveCSV || Options.SaveHTML);
#ifdef Q_OS_IOS
if (Options.SaveImage)
{
@@ -955,14 +957,22 @@ lcStartupMode lcApplication::Initialize(const QList<QPair<QString, bool>>& Libra
#endif
#ifndef Q_OS_IOS
if (!lcContext::InitializeRenderer())
const bool CreateRenderResources = !SaveAndExit || Options.SaveImage || Options.SaveHTML;
const lcResult<void> RendererResult = lcContext::InitializeRenderer(CreateRenderResources);
if (!RendererResult)
{
StdErr << tr("Error creating OpenGL context.\n");
StdErr << RendererResult.error() << '\n';
if (!SaveAndExit)
QMessageBox::critical(nullptr, tr("LeoCAD"), RendererResult.error());
return lcStartupMode::Error;
}
emit RendererInitialized();
#endif
const bool SaveAndExit = (Options.SaveImage || Options.SaveWavefront || Options.Save3DS || Options.SaveCOLLADA || Options.SaveCSV || Options.SaveHTML);
bool OutputFailed = false;
if (!SaveAndExit)
@@ -1332,11 +1342,16 @@ lcStartupMode lcApplication::Initialize(const QList<QPair<QString, bool>>& Libra
gMainWindow->GetPartSelectionWidget()->SetDefaultPart();
#ifdef Q_OS_IOS
if (!lcContext::InitializeRenderer())
const lcResult<void> RendererResult = lcContext::InitializeRenderer(true);
if (!RendererResult)
{
StdErr << tr("Error creating OpenGL context.\n");
StdErr << RendererResult.error() << '\n';
QMessageBox::critical(gMainWindow, tr("LeoCAD"), RendererResult.error());
return lcStartupMode::Error;
}
emit RendererInitialized();
#endif
gMainWindow->show();
+3
View File
@@ -205,6 +205,9 @@ public:
lcPreferences mPreferences;
QByteArray mClipboard;
signals:
void RendererInitialized();
protected:
void UpdateStyle();
QString GetTabLayoutKey() const;
+294 -263
View File
@@ -11,15 +11,9 @@
#include "lc_viewsphere.h"
#include "lc_viewmanipulator.h"
#include "lc_stringcache.h"
#include "lc_partselectionwidget.h"
#include "lc_scene.h"
#ifdef LC_OPENGLES
#define glEnableClientState(...)
#define glDisableClientState(...)
#define glVertexPointer(...)
#define glTexCoordPointer(...)
#define glColorPointer(...)
#define GL_ARRAY_BUFFER_ARB GL_ARRAY_BUFFER
#define GL_ELEMENT_ARRAY_BUFFER_ARB GL_ELEMENT_ARRAY_BUFFER
#define GL_STATIC_DRAW_ARB GL_STATIC_DRAW
@@ -28,6 +22,7 @@
std::unique_ptr<QOpenGLContext> lcContext::mOffscreenContext;
std::unique_ptr<QOffscreenSurface> lcContext::mOffscreenSurface;
std::unique_ptr<lcContext> lcContext::mGlobalOffscreenContext;
bool lcContext::mRenderResourcesCreated = false;
lcProgram lcContext::mPrograms[static_cast<int>(lcMaterialType::Count)];
lcScopedGLContextState::lcScopedGLContextState()
@@ -81,11 +76,6 @@ lcContext::lcContext()
mIndexBufferObject = 0;
mVertexBufferPointer = nullptr;
mIndexBufferPointer = nullptr;
mVertexBufferOffset = (char*)~0;
mNormalEnabled = false;
mTexCoordEnabled = false;
mColorEnabled = false;
mTexture2D = 0;
mTextureCubeMap = 0;
@@ -127,39 +117,60 @@ lcContext::~lcContext()
{
}
bool lcContext::InitializeRenderer()
lcResult<void> lcContext::InitializeRenderer(bool CreateRenderResources)
{
if (!CreateOffscreenContext())
return false;
const lcResult<void> OffscreenResult = CreateOffscreenContext();
if (!OffscreenResult)
return lcUnexpected(OffscreenResult.error());
mGlobalOffscreenContext = std::unique_ptr<lcContext>(new(lcContext));
lcContext* Context = mGlobalOffscreenContext.get();
Context->SetOffscreenContext();
lcInitializeGLExtensions(mOffscreenContext.get());
if (!CreateRenderResources)
return lcResult<void>();
if (!Context->hasOpenGLFeature(QOpenGLFunctions::Shaders))
{
mGlobalOffscreenContext.reset();
DestroyOffscreenContext();
return lcUnexpected(QCoreApplication::translate("lcContext", "OpenGL shader support is required."));
}
const lcResult<void> ResourcesResult = Context->CreateResources();
if (!ResourcesResult)
{
Context->DestroyResources();
mGlobalOffscreenContext.reset();
DestroyOffscreenContext();
return lcUnexpected(ResourcesResult.error());
}
gStringCache.Initialize(Context);
gTexFont.Initialize(Context);
if (SupportsMaterial(lcMaterialType::TextSDF))
gTexFont.Initialize(Context);
Context->CreateResources();
lcView::CreateResources(Context);
lcViewManipulator::CreateResources(Context);
lcViewSphere::CreateResources(Context);
if (!gSupportsShaderObjects && lcGetPreferences().mShadingMode == lcShadingMode::DefaultLights)
lcGetPreferences().mShadingMode = lcShadingMode::Flat;
if (SupportsMaterial(lcMaterialType::UnlitViewSphere))
lcViewSphere::CreateResources(Context);
if (!gSupportsShaderObjects && lcGetPreferences().mDrawConditionalLines)
lcGetPreferences().mDrawConditionalLines = false;
mRenderResourcesCreated = true;
if (!SupportsSelectionOutline())
lcGetPreferences().mSelectionRenderMode = lcSelectionRenderMode::Tint;
if (!gSupportsFramebufferObject)
gMainWindow->GetPartSelectionWidget()->DisableIconMode();
return true;
return lcResult<void>();
}
void lcContext::ShutdownRenderer()
@@ -170,13 +181,18 @@ void lcContext::ShutdownRenderer()
mGlobalOffscreenContext->MakeCurrent();
lcContext* Context = mGlobalOffscreenContext.get();
gStringCache.Reset();
gTexFont.Reset();
if (mRenderResourcesCreated)
{
gStringCache.Reset();
gTexFont.Reset();
lcView::DestroyResources(Context);
Context->DestroyResources();
lcViewManipulator::DestroyResources(Context);
lcViewSphere::DestroyResources(Context);
lcView::DestroyResources(Context);
Context->DestroyResources();
lcViewManipulator::DestroyResources(Context);
lcViewSphere::DestroyResources(Context);
mRenderResourcesCreated = false;
}
mGlobalOffscreenContext.reset();
@@ -188,35 +204,29 @@ lcContext* lcContext::GetGlobalOffscreenContext()
return mGlobalOffscreenContext.get();
}
bool lcContext::CreateOffscreenContext()
lcResult<void> lcContext::CreateOffscreenContext()
{
std::unique_ptr<QOpenGLContext> OffscreenContext(new QOpenGLContext());
if (!OffscreenContext)
return false;
OffscreenContext->setShareContext(QOpenGLContext::globalShareContext());
if (!OffscreenContext->create() || !OffscreenContext->isValid())
return false;
return lcUnexpected(QCoreApplication::translate("lcContext", "Could not create the OpenGL context."));
std::unique_ptr<QOffscreenSurface> OffscreenSurface(new QOffscreenSurface());
if (!OffscreenSurface)
return false;
OffscreenSurface->create();
if (!OffscreenSurface->isValid())
return false;
return lcUnexpected(QCoreApplication::translate("lcContext", "Could not create the offscreen OpenGL surface."));
if (!OffscreenContext->makeCurrent(OffscreenSurface.get()))
return false;
return lcUnexpected(QCoreApplication::translate("lcContext", "Could not make the offscreen OpenGL context current."));
mOffscreenContext = std::move(OffscreenContext);
mOffscreenSurface = std::move(OffscreenSurface);
return true;
return lcResult<void>();
}
void lcContext::DestroyOffscreenContext()
@@ -225,7 +235,7 @@ void lcContext::DestroyOffscreenContext()
mOffscreenContext.reset();
}
void lcContext::CreateShaderPrograms()
lcResult<void> lcContext::CreateShaderPrograms()
{
const char* ShaderPrefix =
{
@@ -291,17 +301,21 @@ void lcContext::CreateShaderPrograms()
LC_ARRAY_SIZE_CHECK(FragmentShaders, lcMaterialType::Count);
const auto LoadShader = [this, ShaderPrefix](const char* FileName, GLuint ShaderType) -> GLuint
const auto LoadShader = [this, ShaderPrefix](const char* FileName, GLuint ShaderType) -> lcResult<GLuint>
{
QFile ShaderFile(FileName);
if (!ShaderFile.open(QIODevice::ReadOnly))
return 0;
return lcUnexpected(QCoreApplication::translate("lcContext", "Could not read shader %1: %2").arg(QString::fromUtf8(FileName), ShaderFile.errorString()));
QByteArray Data = ShaderPrefix + ShaderFile.readAll();
const char* Source = Data.constData();
const GLuint Shader = glCreateShader(ShaderType);
if (!Shader)
return lcUnexpected(QCoreApplication::translate("lcContext", "Could not create shader %1.").arg(QString::fromUtf8(FileName)));
glShaderSource(Shader, 1, &Source, nullptr);
glCompileShader(Shader);
@@ -310,22 +324,17 @@ void lcContext::CreateShaderPrograms()
if (ShaderCompiled == GL_FALSE)
{
#ifndef QT_NO_DEBUG
GLint Length = 0;
QByteArray InfoLog;
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &Length);
InfoLog.resize(Length);
QByteArray InfoLog(Length, '\0');
glGetShaderInfoLog(Shader, Length, &Length, InfoLog.data());
qDebug() << InfoLog;
#endif
if (Length > 0)
glGetShaderInfoLog(Shader, Length, nullptr, InfoLog.data());
glDeleteShader(Shader);
return 0;
return lcUnexpected(QCoreApplication::translate("lcContext", "Could not compile shader %1:\n%2").arg(QString::fromUtf8(FileName), QString::fromUtf8(InfoLog.constData())));
}
return Shader;
@@ -333,21 +342,75 @@ void lcContext::CreateShaderPrograms()
for (int MaterialType = 0; MaterialType < static_cast<int>(lcMaterialType::Count); MaterialType++)
{
const GLuint VertexShader = LoadShader(VertexShaders[MaterialType], GL_VERTEX_SHADER);
const GLuint FragmentShader = LoadShader(FragmentShaders[MaterialType], GL_FRAGMENT_SHADER);
bool Optional = false;
if (!VertexShader || !FragmentShader)
switch (static_cast<lcMaterialType>(MaterialType))
{
case lcMaterialType::UnlitColorConditional:
case lcMaterialType::TextSDF:
case lcMaterialType::UnlitViewSphere:
case lcMaterialType::FakeLitColor:
case lcMaterialType::FakeLitTextureDecal:
case lcMaterialType::OutlineComposite:
Optional = true;
break;
case lcMaterialType::UnlitColor:
case lcMaterialType::UnlitTextureModulate:
case lcMaterialType::UnlitTextureDecal:
case lcMaterialType::UnlitVertexColor:
case lcMaterialType::Count:
break;
}
const lcResult<GLuint> VertexResult = LoadShader(VertexShaders[MaterialType], GL_VERTEX_SHADER);
if (!VertexResult)
{
if (Optional)
{
qWarning().noquote() << VertexResult.error();
continue;
}
return lcUnexpected(VertexResult.error());
}
const GLuint VertexShader = VertexResult.value();
const lcResult<GLuint> FragmentResult = LoadShader(FragmentShaders[MaterialType], GL_FRAGMENT_SHADER);
if (!FragmentResult)
{
glDeleteShader(VertexShader);
if (Optional)
{
qWarning().noquote() << FragmentResult.error();
continue;
}
return lcUnexpected(FragmentResult.error());
}
const GLuint FragmentShader = FragmentResult.value();
const GLuint Program = glCreateProgram();
if (!Program)
{
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
mPrograms[MaterialType].Object = 0;
const QString Error = QCoreApplication::translate("lcContext", "Could not create the shader program for %1 and %2.").arg(QString::fromUtf8(VertexShaders[MaterialType]), QString::fromUtf8(FragmentShaders[MaterialType]));
continue;
if (Optional)
{
qWarning().noquote() << Error;
continue;
}
return lcUnexpected(Error);
}
GLuint Program = glCreateProgram();
glAttachShader(Program, VertexShader);
glAttachShader(Program, FragmentShader);
@@ -373,26 +436,29 @@ void lcContext::CreateShaderPrograms()
if (IsLinked == GL_FALSE)
{
#ifndef QT_NO_DEBUG
GLint Length = 0;
QByteArray InfoLog;
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &Length);
InfoLog.resize(Length);
QByteArray InfoLog(Length, '\0');
glGetProgramInfoLog(Program, Length, &Length, InfoLog.data());
#endif
if (Length > 0)
glGetProgramInfoLog(Program, Length, nullptr, InfoLog.data());
glDeleteProgram(Program);
Program = 0;
const QString Error = QCoreApplication::translate("lcContext", "Could not link the shader program for %1 and %2:\n%3").arg(QString::fromUtf8(VertexShaders[MaterialType]), QString::fromUtf8(FragmentShaders[MaterialType]), QString::fromUtf8(InfoLog.constData()));
if (Optional)
{
qWarning().noquote() << Error;
continue;
}
return lcUnexpected(Error);
}
mPrograms[MaterialType].Object = Program;
if (!Program)
continue;
mPrograms[MaterialType].WorldViewProjectionMatrixLocation = glGetUniformLocation(Program, "WorldViewProjectionMatrix");
mPrograms[MaterialType].WorldMatrixLocation = glGetUniformLocation(Program, "WorldMatrix");
mPrograms[MaterialType].MaterialColorLocation = glGetUniformLocation(Program, "MaterialColor");
@@ -412,7 +478,7 @@ void lcContext::CreateShaderPrograms()
}
const GLint VisibleTextureLocation = glGetUniformLocation(Program, "VisibleTexture");
if (VisibleTextureLocation != -1)
{
glUseProgram(Program);
@@ -420,21 +486,17 @@ void lcContext::CreateShaderPrograms()
glUseProgram(0);
}
}
return lcResult<void>();
}
void lcContext::CreateResources()
lcResult<void> lcContext::CreateResources()
{
if (!gSupportsShaderObjects)
return;
CreateShaderPrograms();
return CreateShaderPrograms();
}
void lcContext::DestroyResources()
{
if (!gSupportsShaderObjects)
return;
for (int MaterialType = 0; MaterialType < static_cast<int>(lcMaterialType::Count); MaterialType++)
{
glDeleteProgram(mPrograms[MaterialType].Object);
@@ -494,24 +556,20 @@ void lcContext::SetDefaultState()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
if (gSupportsShaderObjects)
{
SetVertexAttribPointer(lcProgramAttrib::Position, 3, GL_FLOAT, false, 0, nullptr);
EnableVertexAttrib(lcProgramAttrib::Position);
SetVertexAttribPointer(lcProgramAttrib::Position, 3, GL_FLOAT, false, 0, nullptr);
EnableVertexAttrib(lcProgramAttrib::Position);
DisableVertexAttrib(lcProgramAttrib::Normal);
SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::TexCoord);
SetVertexAttribPointer(lcProgramAttrib::TexCoord, 2, GL_FLOAT, false, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::Color);
SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
}
DisableVertexAttrib(lcProgramAttrib::Normal);
SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::TexCoord);
SetVertexAttribPointer(lcProgramAttrib::TexCoord, 2, GL_FLOAT, false, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::Color);
SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
mVertexBufferObject = 0;
mIndexBufferObject = 0;
mVertexBufferPointer = nullptr;
mIndexBufferPointer = nullptr;
mVertexBufferOffset = (char*)~0;
for (int AttribIndex = 0; AttribIndex < static_cast<int>(lcProgramAttrib::Count); AttribIndex++)
mVertexAttribState[AttribIndex] = lcVertexAttribState();
@@ -533,11 +591,8 @@ void lcContext::SetDefaultState()
glLineWidth(1.0f);
mLineWidth = 1.0f;
if (gSupportsShaderObjects)
{
glUseProgram(0);
mMaterialType = lcMaterialType::Count;
}
glUseProgram(0);
mMaterialType = lcMaterialType::Count;
}
void lcContext::ClearColorAndDepth(const lcVector4& ClearColor)
@@ -553,7 +608,7 @@ void lcContext::ClearDepth()
bool lcContext::SupportsSelectionOutline()
{
return gSupportsShaderObjects && gSupportsFramebufferObject &&
return gSupportsFramebufferObject &&
mPrograms[static_cast<int>(lcMaterialType::UnlitColor)].Object &&
mPrograms[static_cast<int>(lcMaterialType::OutlineComposite)].Object;
}
@@ -572,23 +627,23 @@ std::unique_ptr<QOpenGLFramebufferObject> lcContext::CreateFramebuffer(int Width
const int MaxTextureSize = GetMaxTextureSize();
GLint MaxRenderbufferSize = 0;
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &MaxRenderbufferSize);
if (Width > MaxTextureSize || Height > MaxTextureSize || Width > MaxRenderbufferSize || Height > MaxRenderbufferSize)
return nullptr;
lcScopedGLContextState GLState;
QOpenGLFramebufferObjectFormat Format;
Format.setAttachment(QOpenGLFramebufferObject::Depth);
std::unique_ptr<QOpenGLFramebufferObject> Framebuffer = std::make_unique<QOpenGLFramebufferObject>(QSize(Width, Height), Format);
if (!Framebuffer->isValid())
{
glBindTexture(GL_TEXTURE_2D, mTexture2D);
return nullptr;
}
@@ -598,7 +653,7 @@ std::unique_ptr<QOpenGLFramebufferObject> lcContext::CreateFramebuffer(int Width
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
return Framebuffer;
}
@@ -609,40 +664,40 @@ bool lcContext::TryShareDepthAttachment(GLuint SourceFramebuffer, QOpenGLFramebu
return false;
glBindFramebuffer(GL_FRAMEBUFFER, SourceFramebuffer);
GLint Samples = 0;
glGetIntegerv(GL_SAMPLES, &Samples);
if (Samples != 0)
return false;
GLint ObjectType = 0;
GLint DepthBuffer = 0;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &ObjectType);
if (ObjectType != GL_RENDERBUFFER)
return false;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &DepthBuffer);
GLint PreviousRenderbuffer = 0;
GLint Width = 0;
GLint Height = 0;
glGetIntegerv(GL_RENDERBUFFER_BINDING, &PreviousRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, DepthBuffer);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &Width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &Height);
glBindRenderbuffer(GL_RENDERBUFFER, PreviousRenderbuffer);
if (QSize(Width, Height) != TargetFramebuffer.size())
return false;
TargetFramebuffer.bind();
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, DepthBuffer);
return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
}
@@ -651,10 +706,10 @@ bool lcContext::GenerateOutlineMasks(const lcScene& Scene, QOpenGLFramebufferObj
lcScopedGLContextState GLState;
GLint SceneFramebuffer = 0;
GLint Viewport[4];
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &SceneFramebuffer);
glGetIntegerv(GL_VIEWPORT, Viewport);
const lcMatrix44 WorldMatrix = mWorldMatrix;
const lcMatrix44 ViewMatrix = mViewMatrix;
const lcMatrix44 ProjectionMatrix = mProjectionMatrix;
@@ -669,28 +724,28 @@ bool lcContext::GenerateOutlineMasks(const lcScene& Scene, QOpenGLFramebufferObj
Scene.DrawOutlineMask(this);
const bool Success = VisibleFramebuffer.bind() && glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
if (Success)
{
GLint OwnDepthBuffer = 0;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &OwnDepthBuffer);
const bool SharedDepth = Scene.CanReuseSceneDepth() && TryShareDepthAttachment(SceneFramebuffer, VisibleFramebuffer);
VisibleFramebuffer.bind();
if (!SharedDepth)
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, OwnDepthBuffer);
ClearColorAndDepth(lcVector4(0.0f, 0.0f, 0.0f, 0.0f));
EnableColorWrite(false);
SetPolygonOffset(lcPolygonOffset::Opaque);
Scene.DrawOutlineOccluders(this);
SetPolygonOffset(lcPolygonOffset::None);
EnableColorWrite(true);
}
@@ -701,9 +756,9 @@ bool lcContext::GenerateOutlineMasks(const lcScene& Scene, QOpenGLFramebufferObj
}
SetDepthWrite(false);
Scene.DrawOutlineMask(this);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, OwnDepthBuffer);
}
@@ -715,7 +770,7 @@ bool lcContext::GenerateOutlineMasks(const lcScene& Scene, QOpenGLFramebufferObj
SetProjectionMatrix(ProjectionMatrix);
SetViewport(Viewport[0], Viewport[1], Viewport[2], Viewport[3]);
SetLineWidth(LineWidth);
return Success;
}
@@ -735,7 +790,7 @@ void lcContext::DrawOutline(QOpenGLFramebufferObject& FullFramebuffer, QOpenGLFr
SetMaterial(lcMaterialType::OutlineComposite);
const lcPreferences& Preferences = lcGetPreferences();
SetOutlineParams(lcVector4(1.0f / FullFramebuffer.width(), 1.0f / FullFramebuffer.height(), 2.0f * DeviceScale, 0.3f),
lcVector4FromColor(Preferences.mObjectSelectedColor), lcVector4FromColor(Preferences.mObjectFocusedColor));
@@ -752,12 +807,12 @@ void lcContext::DrawOutline(QOpenGLFramebufferObject& FullFramebuffer, QOpenGLFr
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
SetVertexBufferPointer(Vertices);
SetVertexFormat(0, 3, 0, 2, 0, false);
DrawPrimitives(GL_TRIANGLE_STRIP, 0, 4);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
@@ -783,16 +838,13 @@ void lcContext::SetMaterial(lcMaterialType MaterialType)
mMaterialType = MaterialType;
if (gSupportsShaderObjects)
{
glUseProgram(mPrograms[static_cast<int>(MaterialType)].Object);
mColorDirty = true;
mWorldMatrixDirty = true; // todo: change dirty to a bitfield and set the lighting constants dirty here
mViewMatrixDirty = true;
mHighlightParamsDirty = true;
mOutlineParamsDirty = true;
mTextHaloColorDirty = true;
}
glUseProgram(mPrograms[static_cast<int>(MaterialType)].Object);
mColorDirty = true;
mWorldMatrixDirty = true; // todo: change dirty to a bitfield and set the lighting constants dirty here
mViewMatrixDirty = true;
mHighlightParamsDirty = true;
mOutlineParamsDirty = true;
mTextHaloColorDirty = true;
}
void lcContext::SetViewport(int x, int y, int Width, int Height)
@@ -1245,7 +1297,6 @@ void lcContext::DestroyIndexBuffer(lcIndexBuffer& IndexBuffer)
void lcContext::ClearVertexBuffer()
{
mVertexBufferPointer = nullptr;
mVertexBufferOffset = (char*)~0;
if (mVertexBufferObject)
{
@@ -1253,17 +1304,14 @@ void lcContext::ClearVertexBuffer()
mVertexBufferObject = 0;
}
if (gSupportsShaderObjects)
{
SetVertexAttribPointer(lcProgramAttrib::Position, 3, GL_FLOAT, false, 0, nullptr);
SetVertexAttribPointer(lcProgramAttrib::Position, 3, GL_FLOAT, false, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::Normal);
SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::TexCoord);
SetVertexAttribPointer(lcProgramAttrib::TexCoord, 2, GL_FLOAT, false, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::Color);
SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
}
DisableVertexAttrib(lcProgramAttrib::Normal);
SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::TexCoord);
SetVertexAttribPointer(lcProgramAttrib::TexCoord, 2, GL_FLOAT, false, 0, nullptr);
DisableVertexAttrib(lcProgramAttrib::Color);
SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
}
void lcContext::SetVertexBuffer(lcVertexBuffer VertexBuffer)
@@ -1277,13 +1325,11 @@ void lcContext::SetVertexBuffer(lcVertexBuffer VertexBuffer)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
mVertexBufferObject = VertexBufferObject;
mVertexBufferOffset = (char*)~0;
}
}
else
{
mVertexBufferPointer = (char*)VertexBuffer.Pointer;
mVertexBufferOffset = (char*)~0;
}
}
@@ -1296,7 +1342,6 @@ void lcContext::SetVertexBufferPointer(const void* VertexBuffer)
}
mVertexBufferPointer = (char*)VertexBuffer;
mVertexBufferOffset = (char*)~0;
}
void lcContext::SetVertexAttribPointer(lcProgramAttrib Attrib, GLint Size, GLenum Type, GLboolean Normalized, GLsizei Stride, const void* Pointer)
@@ -1346,13 +1391,10 @@ void lcContext::SetVertexFormatPosition(int PositionSize)
const int VertexSize = PositionSize * sizeof(float);
const char* VertexBufferPointer = mVertexBufferPointer;
if (gSupportsShaderObjects)
{
SetVertexAttribPointer(lcProgramAttrib::Position, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
DisableVertexAttrib(lcProgramAttrib::Normal);
DisableVertexAttrib(lcProgramAttrib::TexCoord);
DisableVertexAttrib(lcProgramAttrib::Color);
}
SetVertexAttribPointer(lcProgramAttrib::Position, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
DisableVertexAttrib(lcProgramAttrib::Normal);
DisableVertexAttrib(lcProgramAttrib::TexCoord);
DisableVertexAttrib(lcProgramAttrib::Color);
}
void lcContext::SetVertexFormatConditional(int BufferOffset)
@@ -1360,17 +1402,14 @@ void lcContext::SetVertexFormatConditional(int BufferOffset)
constexpr int VertexSize = 12 * sizeof(float);
const char* VertexBufferPointer = mVertexBufferPointer + BufferOffset;
if (gSupportsShaderObjects)
{
SetVertexAttribPointer(lcProgramAttrib::ControlPoint1, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer);
EnableVertexAttrib(lcProgramAttrib::ControlPoint1);
SetVertexAttribPointer(lcProgramAttrib::ControlPoint2, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 3 * sizeof(float));
EnableVertexAttrib(lcProgramAttrib::ControlPoint2);
SetVertexAttribPointer(lcProgramAttrib::ControlPoint3, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 6 * sizeof(float));
EnableVertexAttrib(lcProgramAttrib::ControlPoint3);
SetVertexAttribPointer(lcProgramAttrib::ControlPoint4, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 9 * sizeof(float));
EnableVertexAttrib(lcProgramAttrib::ControlPoint4);
}
SetVertexAttribPointer(lcProgramAttrib::ControlPoint1, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer);
EnableVertexAttrib(lcProgramAttrib::ControlPoint1);
SetVertexAttribPointer(lcProgramAttrib::ControlPoint2, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 3 * sizeof(float));
EnableVertexAttrib(lcProgramAttrib::ControlPoint2);
SetVertexAttribPointer(lcProgramAttrib::ControlPoint3, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 6 * sizeof(float));
EnableVertexAttrib(lcProgramAttrib::ControlPoint3);
SetVertexAttribPointer(lcProgramAttrib::ControlPoint4, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 9 * sizeof(float));
EnableVertexAttrib(lcProgramAttrib::ControlPoint4);
}
void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSize, int TexCoordSize, int ColorSize, bool EnableNormals)
@@ -1378,43 +1417,40 @@ void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSi
const int VertexSize = (PositionSize + TexCoordSize) * sizeof(float) + NormalSize * sizeof(quint32) + ColorSize;
const char* VertexBufferPointer = mVertexBufferPointer + BufferOffset;
if (gSupportsShaderObjects)
int Offset = 0;
SetVertexAttribPointer(lcProgramAttrib::Position, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
EnableVertexAttrib(lcProgramAttrib::Position);
Offset += PositionSize * sizeof(float);
if (NormalSize && EnableNormals)
{
int Offset = 0;
SetVertexAttribPointer(lcProgramAttrib::Position, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
EnableVertexAttrib(lcProgramAttrib::Position);
Offset += PositionSize * sizeof(float);
if (NormalSize && EnableNormals)
{
SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, VertexSize, VertexBufferPointer + Offset);
EnableVertexAttrib(lcProgramAttrib::Normal);
}
else
DisableVertexAttrib(lcProgramAttrib::Normal);
Offset += NormalSize * sizeof(quint32);
if (TexCoordSize)
{
SetVertexAttribPointer(lcProgramAttrib::TexCoord, TexCoordSize, GL_FLOAT, false, VertexSize, VertexBufferPointer + Offset);
EnableVertexAttrib(lcProgramAttrib::TexCoord);
}
else
DisableVertexAttrib(lcProgramAttrib::TexCoord);
Offset += TexCoordSize * sizeof(float);
if (ColorSize)
{
SetVertexAttribPointer(lcProgramAttrib::Color, ColorSize, GL_UNSIGNED_BYTE, true, VertexSize, VertexBufferPointer + Offset);
EnableVertexAttrib(lcProgramAttrib::Color);
}
else
DisableVertexAttrib(lcProgramAttrib::Color);
SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, VertexSize, VertexBufferPointer + Offset);
EnableVertexAttrib(lcProgramAttrib::Normal);
}
else
DisableVertexAttrib(lcProgramAttrib::Normal);
Offset += NormalSize * sizeof(quint32);
if (TexCoordSize)
{
SetVertexAttribPointer(lcProgramAttrib::TexCoord, TexCoordSize, GL_FLOAT, false, VertexSize, VertexBufferPointer + Offset);
EnableVertexAttrib(lcProgramAttrib::TexCoord);
}
else
DisableVertexAttrib(lcProgramAttrib::TexCoord);
Offset += TexCoordSize * sizeof(float);
if (ColorSize)
{
SetVertexAttribPointer(lcProgramAttrib::Color, ColorSize, GL_UNSIGNED_BYTE, true, VertexSize, VertexBufferPointer + Offset);
EnableVertexAttrib(lcProgramAttrib::Color);
}
else
DisableVertexAttrib(lcProgramAttrib::Color);
}
void lcContext::ClearIndexBuffer()
@@ -1470,7 +1506,6 @@ void lcContext::BindMesh(const lcMesh* Mesh)
glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
mVertexBufferObject = VertexBufferObject;
mVertexBufferPointer = nullptr;
mVertexBufferOffset = (char*)~0;
}
if (IndexBufferObject != mIndexBufferObject)
@@ -1496,74 +1531,70 @@ void lcContext::BindMesh(const lcMesh* Mesh)
mVertexBufferPointer = (char*)Mesh->mVertexData;
mIndexBufferPointer = (char*)Mesh->mIndexData;
mVertexBufferOffset = (char*)~0;
}
}
void lcContext::FlushState()
{
if (gSupportsShaderObjects)
const lcProgram& Program = mPrograms[static_cast<int>(mMaterialType)];
if (mWorldMatrixDirty || mViewMatrixDirty || mProjectionMatrixDirty)
{
const lcProgram& Program = mPrograms[static_cast<int>(mMaterialType)];
if (mWorldMatrixDirty || mViewMatrixDirty || mProjectionMatrixDirty)
if (mViewProjectionMatrixDirty)
{
if (mViewProjectionMatrixDirty)
mViewProjectionMatrix = lcMul(mViewMatrix, mProjectionMatrix);
mViewProjectionMatrixDirty = false;
}
if (mWorldMatrixDirty)
{
if (Program.WorldMatrixLocation != -1)
glUniformMatrix4fv(Program.WorldMatrixLocation, 1, false, mWorldMatrix.GetFloats());
}
if (mViewMatrixDirty)
{
const lcMatrix44 InverseViewMatrix = lcMatrix44AffineInverse(mViewMatrix);
lcVector3 ViewPosition = lcMul30(-mViewMatrix.GetTranslation(), InverseViewMatrix);
if (Program.LightPositionLocation != -1)
{
mViewProjectionMatrix = lcMul(mViewMatrix, mProjectionMatrix);
mViewProjectionMatrixDirty = false;
lcVector3 LightPosition = ViewPosition + lcMul30(lcVector3(300.0f, 300.0f, 0.0f), InverseViewMatrix);
glUniform3fv(Program.LightPositionLocation, 1, LightPosition.GetFloats());
}
if (mWorldMatrixDirty)
{
if (Program.WorldMatrixLocation != -1)
glUniformMatrix4fv(Program.WorldMatrixLocation, 1, false, mWorldMatrix.GetFloats());
}
if (mViewMatrixDirty)
{
const lcMatrix44 InverseViewMatrix = lcMatrix44AffineInverse(mViewMatrix);
lcVector3 ViewPosition = lcMul30(-mViewMatrix.GetTranslation(), InverseViewMatrix);
if (Program.LightPositionLocation != -1)
{
lcVector3 LightPosition = ViewPosition + lcMul30(lcVector3(300.0f, 300.0f, 0.0f), InverseViewMatrix);
glUniform3fv(Program.LightPositionLocation, 1, LightPosition.GetFloats());
}
if (Program.EyePositionLocation != -1)
glUniform3fv(Program.EyePositionLocation, 1, ViewPosition.GetFloats());
}
glUniformMatrix4fv(Program.WorldViewProjectionMatrixLocation, 1, false, lcMul(mWorldMatrix, mViewProjectionMatrix).GetFloats());
mWorldMatrixDirty = false;
mViewMatrixDirty = false;
mProjectionMatrixDirty = false;
if (Program.EyePositionLocation != -1)
glUniform3fv(Program.EyePositionLocation, 1, ViewPosition.GetFloats());
}
if (mColorDirty && Program.MaterialColorLocation != -1)
{
glUniform4fv(Program.MaterialColorLocation, 1, mColor.GetFloats());
mColorDirty = false;
}
glUniformMatrix4fv(Program.WorldViewProjectionMatrixLocation, 1, false, lcMul(mWorldMatrix, mViewProjectionMatrix).GetFloats());
mWorldMatrixDirty = false;
mViewMatrixDirty = false;
mProjectionMatrixDirty = false;
}
if (mTextHaloColorDirty && Program.TextHaloColorLocation != -1)
{
glUniform4fv(Program.TextHaloColorLocation, 1, mTextHaloColor.GetFloats());
mTextHaloColorDirty = false;
}
if (mColorDirty && Program.MaterialColorLocation != -1)
{
glUniform4fv(Program.MaterialColorLocation, 1, mColor.GetFloats());
mColorDirty = false;
}
if (mHighlightParamsDirty && Program.HighlightParamsLocation != -1)
{
glUniform4fv(Program.HighlightParamsLocation, 4, mHighlightParams[0].GetFloats());
mHighlightParamsDirty = false;
}
if (mTextHaloColorDirty && Program.TextHaloColorLocation != -1)
{
glUniform4fv(Program.TextHaloColorLocation, 1, mTextHaloColor.GetFloats());
mTextHaloColorDirty = false;
}
if (mOutlineParamsDirty && Program.OutlineParamsLocation != -1)
{
glUniform4fv(Program.OutlineParamsLocation, 3, mOutlineParams[0].GetFloats());
mOutlineParamsDirty = false;
}
if (mHighlightParamsDirty && Program.HighlightParamsLocation != -1)
{
glUniform4fv(Program.HighlightParamsLocation, 4, mHighlightParams[0].GetFloats());
mHighlightParamsDirty = false;
}
if (mOutlineParamsDirty && Program.OutlineParamsLocation != -1)
{
glUniform4fv(Program.OutlineParamsLocation, 3, mOutlineParams[0].GetFloats());
mOutlineParamsDirty = false;
}
}
+22 -13
View File
@@ -2,6 +2,7 @@
#include "lc_math.h"
#include "lc_mesh.h"
#include "lc_result.h"
class lcVertexBuffer
{
@@ -64,11 +65,11 @@ enum class lcProgramAttrib
Normal,
TexCoord,
Color,
ControlPoint1 = 0,
ControlPoint2,
ControlPoint3,
ControlPoint4,
Count
Count,
ControlPoint1 = Position,
ControlPoint2 = Normal,
ControlPoint3 = TexCoord,
ControlPoint4 = Color
};
struct lcProgram
@@ -137,11 +138,11 @@ public:
lcContext& operator=(const lcContext&) = delete;
lcContext& operator=(lcContext&&) = delete;
static bool InitializeRenderer();
static lcResult<void> InitializeRenderer(bool CreateRenderResources);
static void ShutdownRenderer();
static lcContext* GetGlobalOffscreenContext();
void CreateResources();
lcResult<void> CreateResources();
void DestroyResources();
void SetDefaultState();
@@ -160,6 +161,17 @@ public:
void ClearColorAndDepth(const lcVector4& ClearColor);
void ClearDepth();
static bool SupportsMaterial(lcMaterialType MaterialType)
{
return mPrograms[static_cast<int>(MaterialType)].Object != 0;
}
static bool SupportsDefaultLights()
{
return SupportsMaterial(lcMaterialType::FakeLitColor) && SupportsMaterial(lcMaterialType::FakeLitTextureDecal);
}
static bool SupportsSelectionOutline();
int GetMaxTextureSize();
std::unique_ptr<QOpenGLFramebufferObject> CreateFramebuffer(int Width, int Height);
@@ -266,10 +278,10 @@ public:
void BindMesh(const lcMesh* Mesh);
protected:
static bool CreateOffscreenContext();
static lcResult<void> CreateOffscreenContext();
static void DestroyOffscreenContext();
void CreateShaderPrograms();
lcResult<void> CreateShaderPrograms();
void FlushState();
bool TryShareDepthAttachment(GLuint SourceFramebuffer, QOpenGLFramebufferObject& TargetFramebuffer);
@@ -284,12 +296,8 @@ protected:
GLuint mIndexBufferObject;
const char* mVertexBufferPointer;
const char* mIndexBufferPointer;
const char* mVertexBufferOffset;
lcMaterialType mMaterialType;
bool mNormalEnabled;
bool mTexCoordEnabled;
bool mColorEnabled;
lcVertexAttribState mVertexAttribState[static_cast<int>(lcProgramAttrib::Count)];
@@ -325,6 +333,7 @@ protected:
static std::unique_ptr<QOffscreenSurface> mOffscreenSurface;
static std::unique_ptr<lcContext> mGlobalOffscreenContext;
static bool mRenderResourcesCreated;
static lcProgram mPrograms[static_cast<int>(lcMaterialType::Count)];
Q_DECLARE_TR_FUNCTIONS(lcContext);
-2
View File
@@ -1,7 +1,6 @@
#include "lc_global.h"
#include "lc_glextensions.h"
bool gSupportsShaderObjects;
bool gSupportsVertexBufferObject;
bool gSupportsFramebufferObject;
bool gSupportsBlendFuncSeparate;
@@ -60,5 +59,4 @@ void lcInitializeGLExtensions(const QOpenGLContext* Context)
gSupportsVertexBufferObject = Functions->hasOpenGLFeature(QOpenGLFunctions::Buffers);
gSupportsFramebufferObject = Functions->hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
gSupportsBlendFuncSeparate = Functions->hasOpenGLFeature(QOpenGLFunctions::BlendFuncSeparate);
gSupportsShaderObjects = Functions->hasOpenGLFeature(QOpenGLFunctions::Shaders);
}
-1
View File
@@ -2,7 +2,6 @@
void lcInitializeGLExtensions(const QOpenGLContext* Context);
extern bool gSupportsShaderObjects;
extern bool gSupportsVertexBufferObject;
extern bool gSupportsFramebufferObject;
extern bool gSupportsBlendFuncSeparate;
+12 -7
View File
@@ -574,7 +574,10 @@ lcPartSelectionListView::lcPartSelectionListView(QWidget* Parent, lcPartSelectio
connect(this, &QListView::doubleClicked, this, &lcPartSelectionListView::DoubleClicked);
connect(this, &QListView::customContextMenuRequested, this, &lcPartSelectionListView::CustomContextMenuRequested);
SetIconSize(lcGetProfileInt(LC_PROFILE_PARTS_LIST_ICONS));
connect(gApplication, &lcApplication::RendererInitialized, this, &lcPartSelectionListView::UpdateIconSize);
mRequestedIconSize = lcGetProfileInt(LC_PROFILE_PARTS_LIST_ICONS);
UpdateIconSize();
}
void lcPartSelectionListView::keyPressEvent(QKeyEvent* KeyEvent)
@@ -816,8 +819,15 @@ void lcPartSelectionListView::UpdateViewMode()
void lcPartSelectionListView::SetIconSize(int Size)
{
setIconSize(QSize(Size, Size));
mRequestedIconSize = Size;
lcSetProfileInt(LC_PROFILE_PARTS_LIST_ICONS, Size);
UpdateIconSize();
}
void lcPartSelectionListView::UpdateIconSize()
{
const int Size = gSupportsFramebufferObject ? mRequestedIconSize : NoIconSize;
setIconSize(QSize(Size, Size));
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
float DeviceScale = devicePixelRatioF();
@@ -1083,11 +1093,6 @@ void lcPartSelectionWidget::SaveState(QSettings& Settings)
Settings.setValue("PartSelectionSplitter", QVariant::fromValue(Sizes));
}
void lcPartSelectionWidget::DisableIconMode()
{
mPartsWidget->SetNoIcons();
}
void lcPartSelectionWidget::SetCurrentPart(PieceInfo* Info)
{
mPartsWidget->SetCurrentPart(Info);
+2 -1
View File
@@ -258,6 +258,7 @@ protected slots:
protected:
void SetIconSize(int Size);
void UpdateIconSize();
void UpdateItemGeometry();
void SetPartFilterType(lcPartFilterType Option);
void keyPressEvent(QKeyEvent* KeyEvent) override;
@@ -265,6 +266,7 @@ protected:
lcPartSelectionListModel* mListModel = nullptr;
lcPartSelectionWidget* mPartSelectionWidget = nullptr;
PieceInfo* mContextInfo = nullptr;
int mRequestedIconSize = NoIconSize;
lcPartCategoryType mCategoryType = lcPartCategoryType::AllParts;
int mCategoryIndex = 0;
std::map<std::pair<lcPartCategoryType, int>, int> mLastCategoryRow;
@@ -284,7 +286,6 @@ public:
void UpdateCategories();
void LoadState(QSettings& Settings);
void SaveState(QSettings& Settings);
void DisableIconMode();
void SetOrientation(Qt::Orientation Orientation);
void SetCurrentPart(PieceInfo* Info);
void SetCategory(lcPartCategoryType Type, int Index);
+7 -6
View File
@@ -440,13 +440,14 @@ void lcScene::Draw(lcContext* Context, const std::function<void()>& PreTransluce
const lcPreferences& Preferences = lcGetPreferences();
const bool DrawLines = Preferences.mDrawEdgeLines && Preferences.mLineWidth > 0.0f;
const bool DrawConditional = Preferences.mDrawConditionalLines && Preferences.mLineWidth > 0.0f;
const bool DrawConditional = Preferences.mDrawConditionalLines && Preferences.mLineWidth > 0.0f && lcContext::SupportsMaterial(lcMaterialType::UnlitColorConditional);
// lcShadingMode ShadingMode = Preferences.mShadingMode;
// if (ShadingMode == lcShadingMode::Wireframe && !mAllowWireframe)
// ShadingMode = lcShadingMode::Flat;
lcShadingMode ShadingMode = mShadingMode;
if (mShadingMode == lcShadingMode::Wireframe)
if (ShadingMode != lcShadingMode::Wireframe && ShadingMode != lcShadingMode::Flat && !lcContext::SupportsDefaultLights())
ShadingMode = lcShadingMode::Flat;
if (ShadingMode == lcShadingMode::Wireframe)
{
DrawOpaqueMeshes(Context, false, LC_MESH_LINES, true, true);
@@ -456,7 +457,7 @@ void lcScene::Draw(lcContext* Context, const std::function<void()>& PreTransluce
if (PreTranslucentCallback)
PreTranslucentCallback();
}
else if (mShadingMode == lcShadingMode::Flat)
else if (ShadingMode == lcShadingMode::Flat)
{
const int SolidPrimitiveTypes = LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES | (DrawLines ? LC_MESH_LINES : 0);
+23 -16
View File
@@ -1167,24 +1167,27 @@ void lcView::OnDraw()
TimerAverage += Result;
TimerAverage /= TimerResults.size();
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f));
if (gTexFont.IsLoaded())
{
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f));
QString Line = QString("GPU: %1 CPU: %2").arg(QString::number(QueryAverage / 1000000.0, 'f', 2), QString::number(TimerAverage / 1000000.0, 'f', 2));
QString Line = QString("GPU: %1 CPU: %2").arg(QString::number(QueryAverage / 1000000.0, 'f', 2), QString::number(TimerAverage / 1000000.0, 'f', 2));
mContext->SetMaterial(gTexFont.IsSDF() ? lcMaterialType::TextSDF : lcMaterialType::UnlitTextureModulate);
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mTextColor));
mContext->SetTextHaloColor(lcVector4FromColor(lcGetPreferences().mTextHaloColor));
mContext->BindTexture2D(gTexFont.GetTexture());
mContext->SetMaterial(lcMaterialType::TextSDF);
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mTextColor));
mContext->SetTextHaloColor(lcVector4FromColor(lcGetPreferences().mTextHaloColor));
mContext->BindTexture2D(gTexFont.GetTexture());
mContext->EnableDepthTest(false);
mContext->EnableColorBlend(true);
mContext->EnableDepthTest(false);
mContext->EnableColorBlend(true);
gTexFont.PrintText(mContext, 3.0f, (float)mHeight - 1.0f - 6.0f, 0.0f, Line.toLatin1().constData());
gTexFont.PrintText(mContext, 3.0f, (float)mHeight - 1.0f - 6.0f, 0.0f, Line.toLatin1().constData());
mContext->EnableColorBlend(false);
mContext->EnableDepthTest(true);
mContext->EnableColorBlend(false);
mContext->EnableDepthTest(true);
}
Redraw();
#endif
@@ -1308,15 +1311,16 @@ void lcView::DrawViewport() const
QString CameraName = mCamera->GetName();
if (!CameraName.isEmpty())
if (!CameraName.isEmpty() && gTexFont.IsLoaded())
{
mContext->SetMaterial(gTexFont.IsSDF() ? lcMaterialType::TextSDF : lcMaterialType::UnlitTextureModulate);
mContext->SetMaterial(lcMaterialType::TextSDF);
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mTextColor));
mContext->SetTextHaloColor(lcVector4FromColor(lcGetPreferences().mTextHaloColor));
mContext->BindTexture2D(gTexFont.GetTexture());
mContext->EnableColorBlend(true);
// TODO: Make TexFont support Unicode camera names instead of converting them to Latin-1.
gTexFont.PrintText(mContext, 3.0f, (float)Height - 1.0f - 6.0f, 0.0f, CameraName.toLatin1().constData());
mContext->EnableColorBlend(false);
@@ -1417,7 +1421,10 @@ void lcView::DrawAxes() const
mContext->DrawIndexedPrimitives(GL_LINES, 6, GL_UNSIGNED_SHORT, 0);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 72, GL_UNSIGNED_SHORT, 6 * 2);
mContext->SetMaterial(gTexFont.IsSDF() ? lcMaterialType::TextSDF : lcMaterialType::UnlitTextureModulate);
if (!gTexFont.IsLoaded())
return;
mContext->SetMaterial(lcMaterialType::TextSDF);
mContext->SetViewMatrix(TranslationMatrix);
mContext->BindTexture2D(gTexFont.GetTexture());
mContext->EnableColorBlend(true);
+6 -3
View File
@@ -959,7 +959,7 @@ void lcViewManipulator::DrawAxisRotationRings(lcTrackButton TrackButton, lcTrack
void lcViewManipulator::DrawRotationText(lcTrackButton TrackButton, const lcVector3& MouseToolDistance, const std::optional<lcRotationDiscInfo>& RotationDisc, const lcMatrix44& WorldMatrix, float OverlayScale) const
{
if (TrackButton == lcTrackButton::None || !RotationDisc)
if (TrackButton == lcTrackButton::None || !RotationDisc || !gTexFont.IsLoaded())
return;
lcContext* Context = mView->mContext;
@@ -978,7 +978,7 @@ void lcViewManipulator::DrawRotationText(lcTrackButton TrackButton, const lcVect
const lcVector3 ScreenPos = mView->ProjectPoint(lcMul31(TextPosition, RotatedWorldMatrix));
const float UIScale = mView->GetUIScale();
Context->SetMaterial(gTexFont.IsSDF() ? lcMaterialType::TextSDF : lcMaterialType::UnlitTextureModulate);
Context->SetMaterial(lcMaterialType::TextSDF);
Context->SetWorldMatrix(lcMatrix44Identity());
Context->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
Context->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mView->GetWidth() / UIScale, 0.0f, mView->GetHeight() / UIScale, -1.0f, 1.0f));
@@ -1045,10 +1045,13 @@ void lcViewManipulator::DrawMoveDistance(lcTrackButton TrackButton, lcTrackTool
Context->SetVertexFormatPosition(3);
Context->DrawPrimitives(GL_TRIANGLES, 0, 18);
if (!gTexFont.IsLoaded())
return;
const lcVector3 ScreenPos = mView->ProjectPoint(TextPosition);
const float UIScale = mView->GetUIScale();
Context->SetMaterial(gTexFont.IsSDF() ? lcMaterialType::TextSDF : lcMaterialType::UnlitTextureModulate);
Context->SetMaterial(lcMaterialType::TextSDF);
Context->SetWorldMatrix(lcMatrix44Identity());
Context->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
Context->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mView->GetWidth() / UIScale, 0.0f, mView->GetHeight() / UIScale, -1.0f, 1.0f));
+25 -58
View File
@@ -5,7 +5,6 @@
#include "lc_context.h"
#include "lc_stringcache.h"
#include "lc_application.h"
#include "lc_glextensions.h"
#include "image.h"
#include "lc_texture.h"
@@ -46,6 +45,8 @@ void lcViewSphere::UpdateSettings()
case lcViewType::Count:
break;
}
mEnabled = mEnabled && lcContext::SupportsMaterial(lcMaterialType::UnlitViewSphere);
}
lcMatrix44 lcViewSphere::GetViewMatrix() const
@@ -74,23 +75,11 @@ void lcViewSphere::CreateResources(lcContext* Context)
QImage PainterImage(SourceCellSize, SourceCellSize, QImage::Format_ARGB32);
QPainter Painter;
QFont Font("Helvetica", gSupportsShaderObjects ? 36 : 20);
const bool UseSDF = gSupportsShaderObjects;
QFont Font("Helvetica", 36);
Image AtlasImage;
std::vector<Image> BitmapFaces;
if (UseSDF)
{
AtlasImage.Allocate(AtlasWidth, AtlasHeight, lcPixelFormat::A8);
memset(AtlasImage.mData, 0, AtlasWidth * AtlasHeight);
}
else
BitmapFaces.reserve(6);
const QTransform BitmapTransforms[6] =
{
QTransform(0, 1, 1, 0, 0, 0), QTransform(0, -1, -1, 0, SourceCellSize, SourceCellSize),
QTransform(-1, 0, 0, 1, SourceCellSize, 0), QTransform(1, 0, 0, -1, 0, SourceCellSize),
QTransform(1, 0, 0, -1, 0, SourceCellSize), QTransform(-1, 0, 0, 1, SourceCellSize, 0)
};
AtlasImage.Allocate(AtlasWidth, AtlasHeight, lcPixelFormat::A8);
memset(AtlasImage.mData, 0, AtlasWidth * AtlasHeight);
auto ConvertToSDF = [](Image& TextureImage)
{
constexpr int Size = 128, Count = Size * Size;
@@ -116,23 +105,18 @@ void lcViewSphere::CreateResources(lcContext* Context)
Image TextureImage;
TextureImage.Allocate(SourceCellSize, SourceCellSize, lcPixelFormat::A8);
QFont LabelFont = Font;
if (UseSDF)
{
// The shader displays the middle 80% of each cell. Leave six pixels
// on either side for the SDF halo, including for translated labels.
constexpr int MaxLabelWidth = 90;
while (LabelFont.pointSize() > 1 && QFontMetrics(LabelFont).horizontalAdvance(ViewNames[ViewIdx]) > MaxLabelWidth)
LabelFont.setPointSize(LabelFont.pointSize() - 1);
}
// The shader displays the middle 80% of each cell. Leave six pixels
// on either side for the SDF halo, including for translated labels.
constexpr int MaxLabelWidth = 90;
while (LabelFont.pointSize() > 1 && QFontMetrics(LabelFont).horizontalAdvance(ViewNames[ViewIdx]) > MaxLabelWidth)
LabelFont.setPointSize(LabelFont.pointSize() - 1);
Painter.begin(&PainterImage);
Painter.setRenderHint(QPainter::TextAntialiasing, UseSDF);
Painter.setRenderHint(QPainter::TextAntialiasing);
Painter.fillRect(0, 0, PainterImage.width(), PainterImage.height(), QColor(0, 0, 0));
Painter.setBrush(QColor(255, 255, 255));
Painter.setPen(QColor(255, 255, 255));
Painter.setFont(LabelFont);
if (!UseSDF)
Painter.setTransform(BitmapTransforms[ViewIdx]);
Painter.drawText(0, 0, PainterImage.width(), PainterImage.height(), Qt::AlignCenter, ViewNames[ViewIdx]);
Painter.end();
@@ -143,27 +127,19 @@ void lcViewSphere::CreateResources(lcContext* Context)
for (int x = 0; x < SourceCellSize; x++)
*Dest++ = qRed(PainterImage.pixel(x, y));
}
if (UseSDF)
{
ConvertToSDF(TextureImage);
// Keep the middle band and its SDF margin in a vertical atlas.
const int AtlasY = ViewIdx * CellHeight;
for (int y = 0; y < CellHeight; y++)
memcpy(AtlasImage.mData + (AtlasY + y) * AtlasWidth,
TextureImage.mData + (CellBottom + y) * SourceCellSize, SourceCellSize);
}
else
BitmapFaces.emplace_back(std::move(TextureImage));
ConvertToSDF(TextureImage);
// Keep the middle band and its SDF margin in a vertical atlas.
const int AtlasY = ViewIdx * CellHeight;
for (int y = 0; y < CellHeight; y++)
memcpy(AtlasImage.mData + (AtlasY + y) * AtlasWidth,
TextureImage.mData + (CellBottom + y) * SourceCellSize, SourceCellSize);
}
if (UseSDF)
mTexture->SetImage(std::move(AtlasImage), LC_TEXTURE_LINEAR);
else
mTexture->SetImage(std::move(BitmapFaces), LC_TEXTURE_CUBEMAP | LC_TEXTURE_LINEAR);
mTexture->SetImage(std::move(AtlasImage), LC_TEXTURE_LINEAR);
const int SphereVertexCount = (mSubdivisions + 1) * (mSubdivisions + 1) * 6;
mSphereIndexCount = mSubdivisions * mSubdivisions * 6 * 6;
std::vector<float> Verts(SphereVertexCount * (UseSDF ? 6 : 3));
std::vector<float> Verts(SphereVertexCount * 6);
std::vector<GLushort> Indices(mSphereIndexCount);
lcMatrix44 Transforms[6] =
@@ -197,12 +173,9 @@ void lcViewSphere::CreateResources(lcContext* Context)
*CurVert++ = SphereVert.x;
*CurVert++ = SphereVert.y;
*CurVert++ = SphereVert.z;
if (UseSDF)
{
*CurVert++ = x / static_cast<float>(mSubdivisions);
*CurVert++ = y / static_cast<float>(mSubdivisions);
*CurVert++ = static_cast<float>(FaceIdx);
}
*CurVert++ = x / static_cast<float>(mSubdivisions);
*CurVert++ = y / static_cast<float>(mSubdivisions);
*CurVert++ = static_cast<float>(FaceIdx);
}
}
}
@@ -262,10 +235,7 @@ void lcViewSphere::Draw()
Context->EnableCullFace(true);
Context->SetVertexBuffer(mVertexBuffer);
if (gSupportsShaderObjects)
Context->SetVertexFormat(0, 3, 0, 3, 0, false);
else
Context->SetVertexFormatPosition(3);
Context->SetVertexFormat(0, 3, 0, 3, 0, false);
Context->SetIndexBuffer(mIndexBuffer);
Context->SetMaterial(lcMaterialType::UnlitColor);
@@ -279,10 +249,7 @@ void lcViewSphere::Draw()
Context->DrawIndexedPrimitives(GL_TRIANGLES, mSphereIndexCount, GL_UNSIGNED_SHORT, 0);
Context->SetMaterial(lcMaterialType::UnlitViewSphere);
if (gSupportsShaderObjects)
Context->BindTexture2D(mTexture);
else
Context->BindTextureCubeMap(mTexture);
Context->BindTexture2D(mTexture);
Context->SetWorldMatrix(lcMatrix44Identity());
Context->SetViewMatrix(GetViewMatrix());
+11 -130
View File
@@ -2,92 +2,17 @@
#include <string.h>
#include "texfont.h"
#include "lc_context.h"
#include "lc_glextensions.h"
#include "lc_texture.h"
#include "image.h"
static const unsigned char TextureData[2048] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0xe0, 0x00, 0x18, 0x60, 0x66, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x60, 0x66, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
0xf8, 0xb1, 0x03, 0x0f, 0x6e, 0x78, 0xfc, 0xb8, 0xd9, 0x61, 0x66, 0xcc, 0xec, 0x1c, 0x3b, 0x00, 0x0c, 0x73, 0x86, 0x19, 0x73, 0xcc, 0x30, 0xcc, 0x39, 0x63, 0x66, 0xc6, 0x9c, 0x33, 0x67, 0x00,
0x00, 0x33, 0xcc, 0x90, 0x61, 0x86, 0x31, 0x86, 0x19, 0x66, 0x66, 0xc3, 0x8c, 0x31, 0xc3, 0x00, 0xe0, 0x33, 0xcc, 0x80, 0x61, 0x86, 0x31, 0x86, 0x19, 0x66, 0xe6, 0xc1, 0x8c, 0x31, 0xc3, 0x00,
0x38, 0x33, 0xcc, 0x80, 0x61, 0xfe, 0x31, 0x86, 0x19, 0x66, 0xe6, 0xc1, 0x8c, 0x31, 0xc3, 0x00, 0x0c, 0x33, 0xcc, 0x80, 0x61, 0x06, 0x30, 0x86, 0x19, 0x66, 0x66, 0xc3, 0x8c, 0x31, 0xc3, 0x00,
0x0c, 0x33, 0xcc, 0x90, 0x61, 0x06, 0x30, 0x86, 0x19, 0x66, 0x66, 0xc6, 0x8c, 0x31, 0xc3, 0x00, 0x0c, 0x73, 0x86, 0x19, 0x73, 0x8c, 0x31, 0xcc, 0x19, 0x66, 0x66, 0xcc, 0x8c, 0x31, 0xc3, 0x00,
0xf8, 0xb6, 0x03, 0x0f, 0x6e, 0xf8, 0x30, 0xb8, 0x19, 0x66, 0x66, 0xd8, 0x8c, 0x31, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0xf0, 0xb0, 0x03, 0x37, 0x3b, 0x9f, 0xdf, 0xb0, 0xc1, 0x03, 0xf0, 0xf0, 0x60, 0x3f, 0x63, 0x00,
0x98, 0x71, 0x86, 0x39, 0x8f, 0x31, 0xc6, 0xb0, 0xc1, 0xc3, 0xf0, 0xf0, 0x60, 0x30, 0x63, 0x00, 0x0c, 0x33, 0xcc, 0x30, 0x87, 0x01, 0xc6, 0x30, 0x63, 0xc6, 0x98, 0x99, 0x31, 0x18, 0x63, 0x00,
0x0c, 0x33, 0xcc, 0x30, 0x83, 0x03, 0xc6, 0x30, 0x63, 0xe6, 0x19, 0x8f, 0x31, 0x18, 0x63, 0x00, 0x0c, 0x33, 0xcc, 0x30, 0x03, 0x1f, 0xc6, 0x30, 0x63, 0xe6, 0x19, 0x86, 0x31, 0x0c, 0x63, 0x00,
0x0c, 0x33, 0xcc, 0x30, 0x03, 0x38, 0xc6, 0x30, 0x36, 0x2c, 0x0d, 0x0f, 0x1b, 0x06, 0x63, 0x00, 0x0c, 0x33, 0xcc, 0x30, 0x03, 0x30, 0xc6, 0x30, 0x36, 0x3c, 0x8f, 0x19, 0x1b, 0x06, 0x63, 0x00,
0x98, 0x71, 0x86, 0x39, 0x83, 0x31, 0x86, 0x39, 0x1c, 0x18, 0xc6, 0x30, 0x0e, 0x03, 0x36, 0x00, 0xf0, 0xb0, 0x03, 0x37, 0x03, 0x1f, 0x1c, 0x37, 0x1c, 0x18, 0xc6, 0x30, 0x0e, 0x3f, 0x1c, 0x00,
0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0xe1, 0x03, 0xc6, 0x1f, 0x1e, 0x7f, 0x7c, 0xf8, 0x00, 0x01, 0x7f, 0x80, 0x0f, 0x00,
0x78, 0x18, 0x33, 0x06, 0xc6, 0x00, 0x03, 0x60, 0xc6, 0x8c, 0x81, 0x03, 0xc3, 0xc0, 0x18, 0x00, 0x60, 0x08, 0x13, 0x06, 0xc7, 0x80, 0x01, 0x60, 0xc6, 0x8c, 0x81, 0x03, 0x83, 0x61, 0x30, 0x00,
0x60, 0x00, 0x03, 0x06, 0xc7, 0x80, 0x01, 0x30, 0xc6, 0x8c, 0xc1, 0x06, 0x83, 0x61, 0x30, 0x00, 0x60, 0x00, 0x03, 0x86, 0xc7, 0x8f, 0x01, 0x30, 0xc6, 0x8c, 0xc1, 0x06, 0xc3, 0x30, 0x00, 0x00,
0x60, 0x80, 0xc1, 0xc3, 0xc6, 0x98, 0x1f, 0x18, 0x7c, 0x8c, 0x61, 0x0c, 0x7f, 0x30, 0x00, 0x00, 0x60, 0xc0, 0x00, 0xc6, 0x06, 0x98, 0x31, 0x18, 0xc6, 0xf8, 0x61, 0x0c, 0xc3, 0x30, 0x00, 0x00,
0x60, 0x60, 0x00, 0x66, 0x06, 0x98, 0x31, 0x18, 0xc6, 0x80, 0x31, 0x18, 0x83, 0x31, 0x00, 0x00, 0x60, 0x30, 0x00, 0xe6, 0x0f, 0x98, 0x31, 0x0c, 0xc6, 0x80, 0xf1, 0x1f, 0x83, 0x61, 0x30, 0x00,
0x60, 0x18, 0x10, 0x06, 0x46, 0x98, 0x31, 0x0c, 0xc6, 0x80, 0x19, 0x30, 0x83, 0x61, 0x30, 0x00, 0x60, 0x18, 0x30, 0x06, 0xc6, 0x98, 0x31, 0x0c, 0xc6, 0xc0, 0x18, 0x30, 0xc3, 0xc0, 0x18, 0x00,
0x60, 0xf8, 0xe3, 0x03, 0x86, 0x0f, 0x1f, 0x0c, 0x7c, 0x78, 0x18, 0x30, 0x7f, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xf8, 0x81, 0x7f, 0xfc, 0x83, 0x0f, 0x06, 0x63, 0xc0, 0x18, 0xc6, 0x00, 0x03, 0xc6, 0x60, 0x00, 0x18, 0x83, 0x01, 0x0c, 0xc0, 0x18, 0x06, 0x63, 0xc0, 0x18, 0xc3, 0x00, 0x03, 0xc6, 0x60, 0x00,
0x18, 0x86, 0x01, 0x0c, 0x60, 0x30, 0x06, 0x63, 0xc0, 0x98, 0xc1, 0x00, 0x07, 0xc7, 0x61, 0x00, 0x18, 0x86, 0x01, 0x0c, 0x60, 0x30, 0x06, 0x63, 0xc0, 0xd8, 0xc0, 0x00, 0x07, 0xc7, 0x63, 0x00,
0x18, 0x8c, 0x01, 0x0c, 0x30, 0x00, 0x06, 0x63, 0xc0, 0x78, 0xc0, 0x00, 0x8f, 0xc7, 0x67, 0x00, 0x18, 0x8c, 0x3f, 0xfc, 0x31, 0x00, 0xfe, 0x63, 0xc0, 0x38, 0xc0, 0x00, 0x8f, 0xc7, 0x66, 0x00,
0x18, 0x8c, 0x01, 0x0c, 0x30, 0x3e, 0x06, 0x63, 0xc0, 0x78, 0xc0, 0x00, 0xdb, 0xc6, 0x6c, 0x00, 0x18, 0x8c, 0x01, 0x0c, 0x30, 0x30, 0x06, 0x63, 0xc0, 0xd8, 0xc0, 0x00, 0xdb, 0xc6, 0x7c, 0x00,
0x18, 0x86, 0x01, 0x0c, 0x60, 0x30, 0x06, 0x63, 0xc6, 0x98, 0xc1, 0x00, 0x73, 0xc6, 0x78, 0x00, 0x18, 0x86, 0x01, 0x0c, 0x60, 0x38, 0x06, 0x63, 0xc6, 0x18, 0xc3, 0x00, 0x73, 0xc6, 0x70, 0x00,
0x18, 0x83, 0x01, 0x0c, 0xc0, 0x38, 0x06, 0x63, 0x6c, 0x18, 0xc6, 0x00, 0x23, 0xc6, 0x60, 0x00, 0xf8, 0x81, 0x7f, 0x0c, 0x80, 0x2f, 0x06, 0x63, 0x38, 0x18, 0xcc, 0x3f, 0x23, 0xc6, 0x60, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x7f, 0xc0, 0x03, 0x7f, 0xc0, 0xe3, 0x7f, 0x06, 0x33, 0xb0, 0x01, 0xd8, 0xc0, 0x00,
0x60, 0x06, 0xc3, 0x60, 0x06, 0xc3, 0x60, 0x06, 0x06, 0x06, 0x33, 0xb0, 0x61, 0xd8, 0xc0, 0x00, 0x30, 0x0c, 0x83, 0x31, 0x0c, 0x83, 0x31, 0x0c, 0x06, 0x06, 0x63, 0x98, 0x61, 0x98, 0x61, 0x00,
0x30, 0x0c, 0x83, 0x31, 0x0c, 0x83, 0x31, 0x00, 0x06, 0x06, 0x63, 0x18, 0x63, 0x0c, 0x33, 0x00, 0x18, 0x18, 0x83, 0x19, 0x18, 0x83, 0x61, 0x00, 0x06, 0x06, 0x63, 0x18, 0xf3, 0x0c, 0x1e, 0x00,
0x18, 0x18, 0xc3, 0x18, 0x18, 0xc3, 0xc0, 0x03, 0x06, 0x06, 0xc3, 0x0c, 0xf3, 0x0c, 0x0c, 0x00, 0x18, 0x18, 0x7f, 0x18, 0x18, 0x7f, 0x00, 0x06, 0x06, 0x06, 0xc3, 0x0c, 0x96, 0x06, 0x0c, 0x00,
0x18, 0x18, 0x03, 0x98, 0x19, 0xc3, 0x00, 0x0c, 0x06, 0x06, 0x83, 0x04, 0x9e, 0x07, 0x1e, 0x00, 0x30, 0x0c, 0x03, 0x30, 0x0f, 0x83, 0x01, 0x0c, 0x06, 0x06, 0x83, 0x07, 0x9e, 0x07, 0x33, 0x00,
0x30, 0x0c, 0x03, 0x30, 0x0e, 0x83, 0x31, 0x0c, 0x06, 0x06, 0x83, 0x07, 0x0c, 0x83, 0x61, 0x00, 0x60, 0x06, 0x03, 0x60, 0x0e, 0x83, 0x61, 0x06, 0x06, 0x8c, 0x01, 0x03, 0x0c, 0xc3, 0xc0, 0x00,
0xc0, 0x03, 0x03, 0xc0, 0x1b, 0x03, 0xc3, 0x03, 0x06, 0xf8, 0x00, 0x03, 0x0c, 0xc3, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0xec, 0x3f, 0x00, 0x03, 0x00, 0x00, 0x80, 0xf1, 0x80, 0x07, 0xf0, 0x03, 0x08, 0x1c, 0x18, 0x0c, 0x0c, 0x30, 0x00, 0x03, 0x00, 0x66, 0x80, 0x99, 0xc1, 0x0c, 0x1c, 0x0e, 0x3e, 0x36, 0x0c,
0x18, 0x06, 0x18, 0x00, 0x03, 0x00, 0xc3, 0x80, 0x0d, 0x63, 0x18, 0x06, 0x18, 0x6b, 0x36, 0x06, 0x30, 0x03, 0x0c, 0x00, 0x33, 0x83, 0x81, 0x81, 0x01, 0x63, 0x18, 0xc6, 0x19, 0x6b, 0x36, 0x03,
0x30, 0x03, 0x0c, 0x00, 0x33, 0xc3, 0x00, 0xc3, 0x00, 0x63, 0x18, 0x63, 0x33, 0x0b, 0x9c, 0x01, 0xe0, 0x01, 0x06, 0x00, 0x03, 0x60, 0x00, 0xc6, 0x80, 0x61, 0x18, 0x33, 0x33, 0x0b, 0xc0, 0x00,
0xe0, 0x01, 0x03, 0x00, 0x03, 0x30, 0x00, 0xcc, 0xc0, 0x60, 0x18, 0x33, 0x33, 0x3e, 0x60, 0x00, 0xc0, 0x80, 0x01, 0x00, 0x03, 0x60, 0x00, 0xc6, 0x60, 0x30, 0x30, 0x33, 0x33, 0x68, 0x30, 0x07,
0xc0, 0x80, 0x01, 0x00, 0x03, 0xc0, 0x00, 0x63, 0x60, 0x60, 0x18, 0x33, 0x1b, 0x68, 0x98, 0x0d, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x81, 0x61, 0x00, 0x60, 0x18, 0xe6, 0x0e, 0x6b, 0x8c, 0x0d,
0xc0, 0x60, 0x80, 0x19, 0x33, 0x03, 0xc3, 0x60, 0x60, 0x60, 0x18, 0x06, 0x00, 0x6b, 0x86, 0x0d, 0xc0, 0xe0, 0xbf, 0x19, 0x33, 0x03, 0x66, 0x60, 0x60, 0x60, 0x18, 0x1c, 0x00, 0x3e, 0x03, 0x07,
0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0xf0, 0x03, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x03, 0x00, 0x66, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x33, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x01, 0x33, 0xc3, 0x00, 0x0c, 0x7f, 0x00, 0x0c, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x1e, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe0, 0x81, 0x7f, 0xc3, 0x80, 0x7f, 0x00, 0x00, 0x0c, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1b, 0x1e, 0xc3, 0x3e, 0x0c, 0x7f, 0x00, 0x0c, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x0f, 0x33, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x83, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x33, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x03, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x0f, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x03, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0d, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0xff, 0x0d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char GlyphData[] =
{
0x20, 0x4b, 0x80, 0x04, 0x21, 0x1e, 0x70, 0x05, 0x23, 0x4f, 0x80, 0x09, 0x24, 0x67, 0x70, 0x09, 0x25, 0x70, 0x70, 0x0d, 0x26, 0x03, 0x80, 0x0b, 0x28, 0x17, 0x80, 0x05, 0x29, 0x1c, 0x80, 0x05,
0x2a, 0x0e, 0x80, 0x09, 0x2b, 0x26, 0x80, 0x09, 0x2c, 0x16, 0x70, 0x04, 0x2d, 0x21, 0x80, 0x05, 0x2e, 0x1a, 0x70, 0x04, 0x2f, 0x3d, 0x70, 0x04, 0x30, 0x6f, 0x24, 0x09, 0x31, 0x01, 0x37, 0x09,
0x32, 0x0a, 0x37, 0x09, 0x33, 0x13, 0x37, 0x09, 0x34, 0x1c, 0x37, 0x09, 0x35, 0x25, 0x37, 0x09, 0x36, 0x2e, 0x37, 0x09, 0x37, 0x37, 0x37, 0x09, 0x38, 0x40, 0x37, 0x09, 0x39, 0x49, 0x37, 0x09,
0x3a, 0x27, 0x70, 0x04, 0x3b, 0x23, 0x70, 0x04, 0x3c, 0x2b, 0x70, 0x09, 0x3d, 0x2f, 0x80, 0x09, 0x3e, 0x34, 0x70, 0x09, 0x3f, 0x41, 0x70, 0x0a, 0x40, 0x57, 0x70, 0x10, 0x41, 0x52, 0x37, 0x0c,
0x42, 0x5e, 0x37, 0x0c, 0x43, 0x6a, 0x37, 0x0c, 0x44, 0x01, 0x4a, 0x0c, 0x45, 0x0d, 0x4a, 0x0b, 0x46, 0x18, 0x4a, 0x0a, 0x47, 0x22, 0x4a, 0x0d, 0x48, 0x2f, 0x4a, 0x0c, 0x49, 0x3b, 0x4a, 0x05,
0x4a, 0x40, 0x4a, 0x09, 0x4b, 0x49, 0x4a, 0x0b, 0x4c, 0x54, 0x4a, 0x0a, 0x4d, 0x5e, 0x4a, 0x0e, 0x4e, 0x6c, 0x4a, 0x0c, 0x4f, 0x01, 0x5d, 0x0d, 0x50, 0x0e, 0x5d, 0x0b, 0x51, 0x19, 0x5d, 0x0d,
0x52, 0x26, 0x5d, 0x0c, 0x53, 0x32, 0x5d, 0x0b, 0x54, 0x3d, 0x5d, 0x0a, 0x55, 0x47, 0x5d, 0x0c, 0x56, 0x53, 0x5d, 0x0b, 0x57, 0x5e, 0x5d, 0x0f, 0x58, 0x6d, 0x5d, 0x0b, 0x59, 0x01, 0x70, 0x0b,
0x5a, 0x0c, 0x70, 0x0a, 0x5b, 0x41, 0x80, 0x05, 0x5d, 0x46, 0x80, 0x05, 0x5f, 0x38, 0x80, 0x09, 0x61, 0x01, 0x11, 0x0a, 0x62, 0x0b, 0x11, 0x0a, 0x63, 0x15, 0x11, 0x09, 0x64, 0x1e, 0x11, 0x0a,
0x65, 0x28, 0x11, 0x0a, 0x66, 0x32, 0x11, 0x06, 0x67, 0x38, 0x11, 0x0a, 0x68, 0x42, 0x11, 0x0a, 0x69, 0x4c, 0x11, 0x04, 0x6a, 0x50, 0x11, 0x04, 0x6b, 0x54, 0x11, 0x09, 0x6c, 0x5d, 0x11, 0x04,
0x6d, 0x61, 0x11, 0x0e, 0x6e, 0x6f, 0x11, 0x0a, 0x6f, 0x01, 0x24, 0x0a, 0x70, 0x0b, 0x24, 0x0a, 0x71, 0x15, 0x24, 0x0a, 0x72, 0x1f, 0x24, 0x07, 0x73, 0x26, 0x24, 0x09, 0x74, 0x2f, 0x24, 0x06,
0x75, 0x35, 0x24, 0x0a, 0x76, 0x3f, 0x24, 0x09, 0x77, 0x48, 0x24, 0x0e, 0x78, 0x56, 0x24, 0x08, 0x79, 0x5e, 0x24, 0x09, 0x7a, 0x67, 0x24, 0x08, 0x7b, 0x4b, 0x70, 0x06, 0x7d, 0x51, 0x70, 0x06,
0x00
0x20, 0x21, 0x23, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5d, 0x5f, 0x61, 0x62, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7d
};
// ============================================================================
@@ -105,45 +30,6 @@ bool TexFont::Initialize(lcContext* Context)
return true;
mFontHeight = 16;
mSDF = gSupportsShaderObjects;
// Keep the original binary atlas as a fixed-function fallback. SDF rendering
// requires only the shader support LeoCAD already uses for normal rendering.
if (!mSDF)
{
mTextureWidth = 128;
mTextureHeight = 128;
Image Image;
Image.Allocate(mTextureWidth, mTextureHeight, lcPixelFormat::L8A8);
for (unsigned int TexelIdx = 0; TexelIdx < sizeof(TextureData) * 8; TexelIdx++)
{
const unsigned char Texel = TextureData[TexelIdx / 8] & (1 << (TexelIdx % 8)) ? 255 : 0;
Image.mData[TexelIdx * 2] = Image.mData[TexelIdx * 2 + 1] = Texel;
}
const unsigned char* Ptr = GlyphData;
while (*Ptr)
{
const unsigned char Glyph = *Ptr++;
mGlyphs[Glyph].Left = *Ptr++;
mGlyphs[Glyph].Bottom = *Ptr++;
mGlyphs[Glyph].Width = *Ptr++;
mGlyphs[Glyph].Right = mGlyphs[Glyph].Left + mGlyphs[Glyph].Width;
mGlyphs[Glyph].Top = mGlyphs[Glyph].Bottom - mFontHeight;
mGlyphs[Glyph].RenderWidth = mGlyphs[Glyph].Width;
mGlyphs[Glyph].RenderHeight = mFontHeight;
mGlyphs[Glyph].Offset = 0.0f;
mGlyphs[Glyph].Left /= mTextureWidth;
mGlyphs[Glyph].Right /= mTextureWidth;
mGlyphs[Glyph].Top /= mTextureHeight;
mGlyphs[Glyph].Bottom /= mTextureHeight;
}
mTexture = new lcTexture();
mTexture->SetImage(std::move(Image), LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV | LC_TEXTURE_POINT);
mTexture->Upload(Context);
return true;
}
constexpr int Scale = 4, Padding = 8, TileWidth = 96, TileHeight = 80;
mTextureWidth = mTextureHeight = 1024;
@@ -156,13 +42,9 @@ bool TexFont::Initialize(lcContext* Context)
Font.setStyleStrategy(QFont::PreferAntialias);
const QFontMetrics Metrics(Font);
const unsigned char* Ptr = GlyphData;
int GlyphIndex = 0;
while (*Ptr)
for (const unsigned char Glyph : GlyphData)
{
const unsigned char Glyph = *Ptr++;
Ptr += 2; // Legacy atlas position; metrics now come from the vector font.
Ptr++;
const int Advance = Metrics.horizontalAdvance(QChar(Glyph));
const int TileX = (GlyphIndex % 10) * TileWidth;
const int TileY = (GlyphIndex / 10) * TileHeight;
@@ -237,7 +119,6 @@ bool TexFont::Initialize(lcContext* Context)
void TexFont::Reset()
{
mTexture = 0;
mSDF = false;
}
void TexFont::GetStringDimensions(int* cx, int* cy, const char* Text) const
@@ -247,7 +128,7 @@ void TexFont::GetStringDimensions(int* cx, int* cy, const char* Text) const
while (*Text != 0)
{
Width += mGlyphs[(int)(*Text)].Width;
Width += mGlyphs[static_cast<unsigned char>(*Text)].Width;
Text++;
}
@@ -266,7 +147,7 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, cons
while (*Text)
{
int ch = *Text;
const unsigned char ch = static_cast<unsigned char>(*Text);
const float GlyphLeft = Left + mGlyphs[ch].Offset;
const float GlyphRight = GlyphLeft + mGlyphs[ch].RenderWidth;
const float GlyphTop = Top - mGlyphs[ch].Offset;
@@ -326,7 +207,7 @@ void TexFont::GetTriangles(const lcMatrix44& Transform, const char* Text, float*
for (const char* ch = Text; *ch; ch++)
{
const int Glyph = *ch;
const unsigned char Glyph = static_cast<unsigned char>(*ch);
Width += mGlyphs[Glyph].Width;
}
@@ -336,7 +217,7 @@ void TexFont::GetTriangles(const lcMatrix44& Transform, const char* Text, float*
while (*Text)
{
int ch = *Text;
const unsigned char ch = static_cast<unsigned char>(*Text);
const float GlyphLeft = Left + mGlyphs[ch].Offset;
const float GlyphRight = GlyphLeft + mGlyphs[ch].RenderWidth;
-6
View File
@@ -10,11 +10,6 @@ public:
return mTexture != nullptr;
}
bool IsSDF() const
{
return mSDF;
}
lcTexture* GetTexture() const
{
return mTexture;
@@ -39,7 +34,6 @@ protected:
int mTextureWidth;
int mTextureHeight;
int mFontHeight;
bool mSDF = false;
};
extern TexFont gTexFont;
+30 -10
View File
@@ -145,12 +145,6 @@ lcPreferencesDialog::lcPreferencesDialog(QWidget* Parent, lcPreferencesDialogOpt
ui->edgeLines->setChecked(mOptions->Preferences.mDrawEdgeLines);
ui->ConditionalLinesCheckBox->setChecked(mOptions->Preferences.mDrawConditionalLines);
if (!gSupportsShaderObjects)
{
ui->ConditionalLinesCheckBox->setChecked(false);
ui->ConditionalLinesCheckBox->setEnabled(false);
}
lcViewWidget* Widget = gMainWindow->GetActiveView()->GetWidget();
QOpenGLContext* Context = Widget->context();
QOpenGLFunctions* Functions = Context->functions();
@@ -247,10 +241,36 @@ lcPreferencesDialog::lcPreferencesDialog(QWidget* Parent, lcPreferencesDialogOpt
ui->studStyleCombo->setCurrentIndex(static_cast<int>(mOptions->StudStyle));
if (!gSupportsShaderObjects)
ui->ShadingMode->removeItem(static_cast<int>(lcShadingMode::DefaultLights));
ui->ShadingMode->setCurrentIndex(static_cast<int>(mOptions->Preferences.mShadingMode));
if (!lcContext::SupportsDefaultLights())
{
QStandardItemModel* ShadingModel = qobject_cast<QStandardItemModel*>(ui->ShadingMode->model());
QStandardItem* DefaultLightsItem = ShadingModel->item(static_cast<int>(lcShadingMode::DefaultLights));
DefaultLightsItem->setEnabled(false);
const QString Message = tr("Default Lights is unavailable. Flat shading is used instead.");
DefaultLightsItem->setToolTip(Message);
ui->ShadingMode->setToolTip(Message);
}
if (!lcContext::SupportsMaterial(lcMaterialType::UnlitViewSphere))
{
const std::array<QWidget*, 7> Controls =
{
ui->ViewSphereSizeCombo, ui->ViewSphereLocationCombo,
ui->PreviewViewSphereSizeCombo, ui->PreviewViewSphereLocationCombo,
ui->ViewSphereColorButton, ui->ViewSphereTextColorButton, ui->ViewSphereHighlightColorButton
};
const QString Message = tr("View sphere rendering is unavailable.");
for (QWidget* Control : Controls)
{
Control->setEnabled(false);
Control->setToolTip(Message);
}
}
bool OutlineSupported = false;
{
@@ -710,12 +730,12 @@ void lcPreferencesDialog::GridLinesToggled()
void lcPreferencesDialog::PreviewViewSphereSizeComboCurrentIndexChanged(int Index)
{
ui->PreviewViewSphereLocationCombo->setEnabled(Index != 0);
ui->PreviewViewSphereLocationCombo->setEnabled(Index != 0 && lcContext::SupportsMaterial(lcMaterialType::UnlitViewSphere));
}
void lcPreferencesDialog::ViewSphereSizeComboCurrentIndexChanged(int Index)
{
ui->ViewSphereLocationCombo->setEnabled(Index != 0);
ui->ViewSphereLocationCombo->setEnabled(Index != 0 && lcContext::SupportsMaterial(lcMaterialType::UnlitViewSphere));
}
void lcPreferencesDialog::AutomateEdgeColorToggled()