mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 13:18:38 +02:00
Remove uniform from SDF text rendering
This commit is contained in:
parent
a4cd56532e
commit
f704ddc11c
6 changed files with 92 additions and 53 deletions
|
@ -70,9 +70,8 @@ void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& st
|
||||||
const glm::vec2& bounds, bool layered) {
|
const glm::vec2& bounds, bool layered) {
|
||||||
// The font does all the OpenGL work
|
// The font does all the OpenGL work
|
||||||
if (_font) {
|
if (_font) {
|
||||||
// Cache color so that the pointer stays valid.
|
|
||||||
_color = color;
|
_color = color;
|
||||||
_font->drawString(batch, x, y, str, &_color, _effectType, bounds, layered);
|
_font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, layered);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,14 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
#include <gpu/Forward.h>
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
class Batch;
|
class Batch;
|
||||||
}
|
}
|
||||||
class Font;
|
class Font;
|
||||||
|
|
||||||
|
#include "text/Font.h"
|
||||||
#include "text/EffectType.h"
|
#include "text/EffectType.h"
|
||||||
#include "text/FontFamilies.h"
|
#include "text/FontFamilies.h"
|
||||||
|
|
||||||
|
@ -51,7 +53,7 @@ private:
|
||||||
|
|
||||||
// text color
|
// text color
|
||||||
glm::vec4 _color;
|
glm::vec4 _color;
|
||||||
|
Font::DrawInfo _drawInfo;
|
||||||
std::shared_ptr<Font> _font;
|
std::shared_ptr<Font> _font;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,15 @@
|
||||||
<@include render-utils/ShaderConstants.h@>
|
<@include render-utils/ShaderConstants.h@>
|
||||||
|
|
||||||
layout(binding=0) uniform sampler2D Font;
|
layout(binding=0) uniform sampler2D Font;
|
||||||
layout(location=RENDER_UTILS_UNIFORM_TEXT_OUTLINE) uniform bool Outline;
|
|
||||||
layout(location=RENDER_UTILS_UNIFORM_TEXT_COLOR) uniform vec4 Color;
|
struct TextParams {
|
||||||
|
vec4 color;
|
||||||
|
float outline;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding=0) uniform textParamsBuffer {
|
||||||
|
TextParams params;
|
||||||
|
};
|
||||||
|
|
||||||
// the interpolated normal
|
// the interpolated normal
|
||||||
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
|
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
|
||||||
|
@ -32,7 +39,7 @@ const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS);
|
||||||
float evalSDF(vec2 texCoord) {
|
float evalSDF(vec2 texCoord) {
|
||||||
// retrieve signed distance
|
// retrieve signed distance
|
||||||
float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g;
|
float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g;
|
||||||
if (Outline) {
|
if (params.outline > 0.0) {
|
||||||
if (sdf > interiorCutoff) {
|
if (sdf > interiorCutoff) {
|
||||||
sdf = 1.0 - sdf;
|
sdf = 1.0 - sdf;
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,8 +69,8 @@ void main() {
|
||||||
|
|
||||||
packDeferredFragment(
|
packDeferredFragment(
|
||||||
normalize(_normalWS),
|
normalize(_normalWS),
|
||||||
a * Color.a,
|
a * params.color.a,
|
||||||
Color.rgb,
|
params.color.rgb,
|
||||||
DEFAULT_ROUGHNESS,
|
DEFAULT_ROUGHNESS,
|
||||||
DEFAULT_METALLIC,
|
DEFAULT_METALLIC,
|
||||||
DEFAULT_EMISSIVE,
|
DEFAULT_EMISSIVE,
|
||||||
|
|
|
@ -14,8 +14,15 @@
|
||||||
<@include render-utils/ShaderConstants.h@>
|
<@include render-utils/ShaderConstants.h@>
|
||||||
|
|
||||||
layout(binding=0) uniform sampler2D Font;
|
layout(binding=0) uniform sampler2D Font;
|
||||||
layout(location=RENDER_UTILS_UNIFORM_TEXT_OUTLINE) uniform bool Outline;
|
|
||||||
layout(location=RENDER_UTILS_UNIFORM_TEXT_COLOR) uniform vec4 Color;
|
struct TextParams {
|
||||||
|
vec4 color;
|
||||||
|
float outline;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding=0) uniform textParamsBuffer {
|
||||||
|
TextParams params;
|
||||||
|
};
|
||||||
|
|
||||||
// the interpolated normal
|
// the interpolated normal
|
||||||
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
|
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
|
||||||
|
@ -31,7 +38,7 @@ const float outlineExpansion = 0.2;
|
||||||
void main() {
|
void main() {
|
||||||
// retrieve signed distance
|
// retrieve signed distance
|
||||||
float sdf = texture(Font, _texCoord0).g;
|
float sdf = texture(Font, _texCoord0).g;
|
||||||
if (Outline) {
|
if (params.outline > 0.0) {
|
||||||
if (sdf > interiorCutoff) {
|
if (sdf > interiorCutoff) {
|
||||||
sdf = 1.0 - sdf;
|
sdf = 1.0 - sdf;
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,8 +58,8 @@ void main() {
|
||||||
|
|
||||||
packDeferredFragmentTranslucent(
|
packDeferredFragmentTranslucent(
|
||||||
normalize(_normalWS),
|
normalize(_normalWS),
|
||||||
a * Color.a,
|
a * params.color.a,
|
||||||
Color.rgb,
|
params.color.rgb,
|
||||||
DEFAULT_FRESNEL,
|
DEFAULT_FRESNEL,
|
||||||
DEFAULT_ROUGHNESS);
|
DEFAULT_ROUGHNESS);
|
||||||
}
|
}
|
|
@ -256,29 +256,30 @@ void Font::setupGPU() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2& bounds) {
|
void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds) {
|
||||||
_verticesBuffer = std::make_shared<gpu::Buffer>();
|
drawInfo.verticesBuffer = std::make_shared<gpu::Buffer>();
|
||||||
_numVertices = 0;
|
drawInfo.indicesBuffer = std::make_shared<gpu::Buffer>();
|
||||||
_indicesBuffer = std::make_shared<gpu::Buffer>();
|
drawInfo.indexCount = 0;
|
||||||
_numIndices = 0;
|
int numVertices = 0;
|
||||||
|
|
||||||
_lastStringRendered = str;
|
drawInfo.string = str;
|
||||||
_lastBounds = bounds;
|
drawInfo.bounds = bounds;
|
||||||
|
drawInfo.origin = origin;
|
||||||
|
|
||||||
// Top left of text
|
// Top left of text
|
||||||
glm::vec2 advance = glm::vec2(x, y);
|
glm::vec2 advance = origin;
|
||||||
foreach(const QString& token, tokenizeForWrapping(str)) {
|
foreach(const QString& token, tokenizeForWrapping(str)) {
|
||||||
bool isNewLine = (token == QString('\n'));
|
bool isNewLine = (token == QString('\n'));
|
||||||
bool forceNewLine = false;
|
bool forceNewLine = false;
|
||||||
|
|
||||||
// Handle wrapping
|
// Handle wrapping
|
||||||
if (!isNewLine && (bounds.x != -1) && (advance.x + computeExtent(token).x > x + bounds.x)) {
|
if (!isNewLine && (bounds.x != -1) && (advance.x + computeExtent(token).x > origin.x + bounds.x)) {
|
||||||
// We are out of the x bound, force new line
|
// We are out of the x bound, force new line
|
||||||
forceNewLine = true;
|
forceNewLine = true;
|
||||||
}
|
}
|
||||||
if (isNewLine || forceNewLine) {
|
if (isNewLine || forceNewLine) {
|
||||||
// Character return, move the advance to a new line
|
// Character return, move the advance to a new line
|
||||||
advance = glm::vec2(x, advance.y - _leading);
|
advance = glm::vec2(origin.x, advance.y - _leading);
|
||||||
|
|
||||||
if (isNewLine) {
|
if (isNewLine) {
|
||||||
// No need to draw anything, go directly to next token
|
// No need to draw anything, go directly to next token
|
||||||
|
@ -288,7 +289,7 @@ void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((bounds.y != -1) && (advance.y - _fontSize < -y - bounds.y)) {
|
if ((bounds.y != -1) && (advance.y - _fontSize < -origin.y - bounds.y)) {
|
||||||
// We are out of the y bound, stop drawing
|
// We are out of the y bound, stop drawing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -297,11 +298,11 @@ void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2
|
||||||
if (!isNewLine) {
|
if (!isNewLine) {
|
||||||
for (auto c : token) {
|
for (auto c : token) {
|
||||||
auto glyph = _glyphs[c];
|
auto glyph = _glyphs[c];
|
||||||
quint16 verticesOffset = _numVertices;
|
quint16 verticesOffset = numVertices;
|
||||||
|
|
||||||
QuadBuilder qd(glyph, advance - glm::vec2(0.0f, _ascent));
|
QuadBuilder qd(glyph, advance - glm::vec2(0.0f, _ascent));
|
||||||
_verticesBuffer->append(sizeof(QuadBuilder), (const gpu::Byte*)&qd);
|
drawInfo.verticesBuffer->append(qd);
|
||||||
_numVertices += 4;
|
numVertices += 4;
|
||||||
|
|
||||||
// Sam's recommended triangle slices
|
// Sam's recommended triangle slices
|
||||||
// Triangle tri1 = { v0, v1, v3 };
|
// Triangle tri1 = { v0, v1, v3 };
|
||||||
|
@ -327,8 +328,8 @@ void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2
|
||||||
indices[3] = verticesOffset + 2;
|
indices[3] = verticesOffset + 2;
|
||||||
indices[4] = verticesOffset + 1;
|
indices[4] = verticesOffset + 1;
|
||||||
indices[5] = verticesOffset + 3;
|
indices[5] = verticesOffset + 3;
|
||||||
_indicesBuffer->append(sizeof(indices), (const gpu::Byte*)indices);
|
drawInfo.indicesBuffer->append(sizeof(indices), (const gpu::Byte*)indices);
|
||||||
_numIndices += NUMBER_OF_INDICES_PER_QUAD;
|
drawInfo.indexCount += NUMBER_OF_INDICES_PER_QUAD;
|
||||||
|
|
||||||
|
|
||||||
// Advance by glyph size
|
// Advance by glyph size
|
||||||
|
@ -341,26 +342,39 @@ void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4* color,
|
void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color,
|
||||||
EffectType effectType, const glm::vec2& bounds, bool layered) {
|
EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool layered) {
|
||||||
if (str == "") {
|
if (str == "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str != _lastStringRendered || bounds != _lastBounds) {
|
if (str != drawInfo.string || bounds != drawInfo.bounds || origin != drawInfo.origin) {
|
||||||
rebuildVertices(x, y, str, bounds);
|
buildVertices(drawInfo, str, origin, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
setupGPU();
|
setupGPU();
|
||||||
|
|
||||||
batch.setPipeline(((*color).a < 1.0f || layered) ? _transparentPipeline : _pipeline);
|
struct GpuDrawParams {
|
||||||
batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture);
|
glm::vec4 color;
|
||||||
batch._glUniform1i(render_utils::slot::uniform::TextOutline, (effectType == OUTLINE_EFFECT));
|
float outline;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!drawInfo.paramsBuffer || drawInfo.params.color != color || drawInfo.params.effect != effectType) {
|
||||||
|
drawInfo.params.color = color;
|
||||||
|
drawInfo.params.effect = effectType;
|
||||||
|
GpuDrawParams gpuDrawParams;
|
||||||
|
gpuDrawParams.color = ColorUtils::sRGBToLinearVec4(drawInfo.params.color);
|
||||||
|
gpuDrawParams.outline = (drawInfo.params.effect == OUTLINE_EFFECT) ? 1 : 0;
|
||||||
|
drawInfo.paramsBuffer = std::make_shared<gpu::Buffer>(sizeof(GpuDrawParams), nullptr);
|
||||||
|
drawInfo.paramsBuffer->setSubData(0, sizeof(GpuDrawParams), (const gpu::Byte*)&gpuDrawParams);
|
||||||
|
}
|
||||||
// need the gamma corrected color here
|
// need the gamma corrected color here
|
||||||
glm::vec4 lrgba = ColorUtils::sRGBToLinearVec4(*color);
|
|
||||||
batch._glUniform4fv(render_utils::slot::uniform::TextColor, 1, (const float*)&lrgba);
|
batch.setPipeline((color.a < 1.0f || layered) ? _transparentPipeline : _pipeline);
|
||||||
batch.setInputFormat(_format);
|
batch.setInputFormat(_format);
|
||||||
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||||
batch.setIndexBuffer(gpu::UINT16, _indicesBuffer, 0);
|
batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture);
|
||||||
batch.drawIndexed(gpu::TRIANGLES, _numIndices, 0);
|
batch.setUniformBuffer(0, drawInfo.paramsBuffer, 0, sizeof(GpuDrawParams));
|
||||||
|
batch.setIndexBuffer(gpu::UINT16, drawInfo.indicesBuffer, 0);
|
||||||
|
batch.drawIndexed(gpu::TRIANGLES, drawInfo.indexCount, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,34 @@ public:
|
||||||
|
|
||||||
void read(QIODevice& path);
|
void read(QIODevice& path);
|
||||||
|
|
||||||
|
struct DrawParams {
|
||||||
|
vec4 color{ -1 };
|
||||||
|
EffectType effect;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DrawInfo {
|
||||||
|
gpu::BufferPointer verticesBuffer;
|
||||||
|
gpu::BufferPointer indicesBuffer;
|
||||||
|
gpu::BufferPointer paramsBuffer;
|
||||||
|
uint32_t indexCount;
|
||||||
|
|
||||||
|
QString string;
|
||||||
|
glm::vec2 origin;
|
||||||
|
glm::vec2 bounds;
|
||||||
|
DrawParams params;
|
||||||
|
};
|
||||||
|
|
||||||
glm::vec2 computeExtent(const QString& str) const;
|
glm::vec2 computeExtent(const QString& str) const;
|
||||||
float getFontSize() const { return _fontSize; }
|
float getFontSize() const { return _fontSize; }
|
||||||
|
|
||||||
// Render string to batch
|
// Render string to batch
|
||||||
void drawString(gpu::Batch& batch, float x, float y, const QString& str,
|
void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str,
|
||||||
const glm::vec4* color, EffectType effectType,
|
const glm::vec4& color, EffectType effectType,
|
||||||
const glm::vec2& bound, bool layered = false);
|
const glm::vec2& origin, const glm::vec2& bound, bool layered = false);
|
||||||
|
|
||||||
static Pointer load(const QString& family);
|
static Pointer load(const QString& family);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Pointer load(QIODevice& fontFile);
|
static Pointer load(QIODevice& fontFile);
|
||||||
QStringList tokenizeForWrapping(const QString& str) const;
|
QStringList tokenizeForWrapping(const QString& str) const;
|
||||||
|
@ -40,7 +58,7 @@ private:
|
||||||
glm::vec2 computeTokenExtent(const QString& str) const;
|
glm::vec2 computeTokenExtent(const QString& str) const;
|
||||||
|
|
||||||
const Glyph& getGlyph(const QChar& c) const;
|
const Glyph& getGlyph(const QChar& c) const;
|
||||||
void rebuildVertices(float x, float y, const QString& str, const glm::vec2& bounds);
|
void buildVertices(DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds);
|
||||||
|
|
||||||
void setupGPU();
|
void setupGPU();
|
||||||
|
|
||||||
|
@ -66,15 +84,7 @@ private:
|
||||||
gpu::PipelinePointer _transparentPipeline;
|
gpu::PipelinePointer _transparentPipeline;
|
||||||
gpu::TexturePointer _texture;
|
gpu::TexturePointer _texture;
|
||||||
gpu::Stream::FormatPointer _format;
|
gpu::Stream::FormatPointer _format;
|
||||||
gpu::BufferPointer _verticesBuffer;
|
|
||||||
gpu::BufferPointer _indicesBuffer;
|
|
||||||
gpu::BufferStreamPointer _stream;
|
gpu::BufferStreamPointer _stream;
|
||||||
unsigned int _numVertices = 0;
|
|
||||||
unsigned int _numIndices = 0;
|
|
||||||
|
|
||||||
// last string render characteristics
|
|
||||||
QString _lastStringRendered;
|
|
||||||
glm::vec2 _lastBounds;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue