mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-16 12:57:27 +02:00
Merge pull request #5256 from Atlante45/fix_billboard
Fix display name z-fighting
This commit is contained in:
commit
3842e748b5
6 changed files with 117 additions and 63 deletions
|
@ -750,7 +750,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum) co
|
|||
const int text_y = -nameDynamicRect.height() / 2;
|
||||
|
||||
// Compute background position/size
|
||||
static const float SLIGHTLY_BEHIND = -0.05f;
|
||||
static const float SLIGHTLY_IN_FRONT = 0.1f;
|
||||
const int border = 0.1f * nameDynamicRect.height();
|
||||
const int left = text_x - border;
|
||||
const int bottom = text_y - border;
|
||||
|
@ -765,16 +765,16 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum) co
|
|||
|
||||
// Compute display name transform
|
||||
auto textTransform = calculateDisplayNameTransform(frustum, renderer->getFontSize());
|
||||
|
||||
// Render background slightly behind to avoid z-fighting
|
||||
auto backgroundTransform = textTransform;
|
||||
backgroundTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_BEHIND));
|
||||
batch.setModelTransform(backgroundTransform);
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch);
|
||||
batch.setModelTransform(textTransform);
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, true, true, true);
|
||||
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
||||
bevelDistance, backgroundColor);
|
||||
// Render actual name
|
||||
QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit();
|
||||
|
||||
// Render text slightly in front to avoid z-fighting
|
||||
textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * renderer->getFontSize()));
|
||||
batch.setModelTransform(textTransform);
|
||||
renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "Text3DOverlay.h"
|
||||
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <TextRenderer3D.h>
|
||||
|
||||
|
@ -114,6 +115,7 @@ void Text3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, true, false, true);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, quadColor);
|
||||
|
||||
// Same font properties as textSize()
|
||||
|
|
|
@ -36,10 +36,6 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
|||
glm::vec4 backgroundColor = glm::vec4(toGlm(getBackgroundColorX()), 1.0f);
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
|
||||
Transform transformToTopLeft = getTransformToCenter();
|
||||
transformToTopLeft.postTranslate(glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
|
||||
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
|
||||
|
||||
// Render background
|
||||
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
|
||||
|
@ -48,15 +44,22 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
|||
// Batch render calls
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
Transform transformToTopLeft = getTransformToCenter();
|
||||
if (getFaceCamera()) {
|
||||
//rotate about vertical to face the camera
|
||||
glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition();
|
||||
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
|
||||
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
|
||||
glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
|
||||
transformToTopLeft.setRotation(orientation);
|
||||
}
|
||||
transformToTopLeft.postTranslate(glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
|
||||
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
|
||||
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
|
||||
//rotate about vertical to face the camera
|
||||
if (getFaceCamera()) {
|
||||
transformToTopLeft.postRotate(args->_viewFrustum->getOrientation());
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
}
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, false);
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, false, false, true);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, minCorner, maxCorner, backgroundColor);
|
||||
|
||||
float scale = _lineHeight / _textRenderer->getFontSize();
|
||||
|
|
|
@ -589,7 +589,7 @@ void GLBackend::do_setStateAntialiasedLineEnable(bool enable) {
|
|||
|
||||
void GLBackend::do_setStateDepthBias(Vec2 bias) {
|
||||
if ( (bias.x != _pipeline._stateCache.depthBias) || (bias.y != _pipeline._stateCache.depthBiasSlopeScale)) {
|
||||
if ((bias.x != 0.f) || (bias.y != 0.f)) {
|
||||
if ((bias.x != 0.0f) || (bias.y != 0.0f)) {
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glEnable(GL_POLYGON_OFFSET_LINE);
|
||||
glEnable(GL_POLYGON_OFFSET_POINT);
|
||||
|
|
|
@ -50,37 +50,44 @@
|
|||
|
||||
static const std::string glowIntensityShaderHandle = "glowIntensity";
|
||||
|
||||
gpu::PipelinePointer DeferredLightingEffect::getPipeline(SimpleProgramKey config) {
|
||||
auto it = _simplePrograms.find(config);
|
||||
if (it != _simplePrograms.end()) {
|
||||
return it.value();
|
||||
}
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
if (config.isCulled()) {
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
} else {
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
}
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
if (config.hasDepthBias()) {
|
||||
state->setDepthBias(1.0f);
|
||||
state->setDepthBiasSlopeScale(1.0f);
|
||||
}
|
||||
state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
|
||||
gpu::PipelinePointer pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
|
||||
_simplePrograms.insert(config, pipeline);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
|
||||
auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(simple_vert)));
|
||||
auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(simple_textured_frag)));
|
||||
auto PSEmissive = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(simple_textured_emisive_frag)));
|
||||
|
||||
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));
|
||||
gpu::ShaderPointer programEmissive = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive));
|
||||
_simpleShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));
|
||||
_emissiveShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive));
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
gpu::Shader::makeProgram(*programEmissive, slotBindings);
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
|
||||
gpu::StatePointer stateCullNone = gpu::StatePointer(new gpu::State());
|
||||
stateCullNone->setCullMode(gpu::State::CULL_NONE);
|
||||
stateCullNone->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
stateCullNone->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
_simpleProgram = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
|
||||
_simpleProgramCullNone = gpu::PipelinePointer(gpu::Pipeline::create(program, stateCullNone));
|
||||
_simpleProgramEmissive = gpu::PipelinePointer(gpu::Pipeline::create(programEmissive, state));
|
||||
_simpleProgramEmissiveCullNone = gpu::PipelinePointer(gpu::Pipeline::create(programEmissive, stateCullNone));
|
||||
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
|
||||
gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
|
||||
|
||||
_viewState = viewState;
|
||||
loadLightProgram(directional_light_frag, false, _directionalLight, _directionalLightLocations);
|
||||
|
@ -117,21 +124,12 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
|
|||
lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset(_ambientLightMode % gpu::SphericalHarmonics::NUM_PRESET));
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool emmisive) {
|
||||
if (emmisive) {
|
||||
if (culled) {
|
||||
batch.setPipeline(_simpleProgramEmissive);
|
||||
} else {
|
||||
batch.setPipeline(_simpleProgramEmissiveCullNone);
|
||||
}
|
||||
} else {
|
||||
if (culled) {
|
||||
batch.setPipeline(_simpleProgram);
|
||||
} else {
|
||||
batch.setPipeline(_simpleProgramCullNone);
|
||||
}
|
||||
}
|
||||
if (!textured) {
|
||||
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
|
||||
bool emmisive, bool depthBias) {
|
||||
SimpleProgramKey config{textured, culled, emmisive, depthBias};
|
||||
batch.setPipeline(getPipeline(config));
|
||||
|
||||
if (!config.isTextured()) {
|
||||
// If it is not textured, bind white texture and keep using textured pipeline
|
||||
batch.setUniformTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
class AbstractViewStateInterface;
|
||||
class RenderArgs;
|
||||
class SimpleProgramKey;
|
||||
|
||||
/// Handles deferred lighting for the bits that require it (voxels...)
|
||||
class DeferredLightingEffect : public Dependency {
|
||||
|
@ -34,7 +35,8 @@ public:
|
|||
void init(AbstractViewStateInterface* viewState);
|
||||
|
||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, bool emmisive = false);
|
||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||
bool emmisive = false, bool depthBias = false);
|
||||
|
||||
//// Renders a solid sphere with the simple program.
|
||||
void renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color);
|
||||
|
@ -95,11 +97,11 @@ private:
|
|||
};
|
||||
|
||||
static void loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations);
|
||||
gpu::PipelinePointer getPipeline(SimpleProgramKey config);
|
||||
|
||||
gpu::PipelinePointer _simpleProgram;
|
||||
gpu::PipelinePointer _simpleProgramCullNone;
|
||||
gpu::PipelinePointer _simpleProgramEmissive;
|
||||
gpu::PipelinePointer _simpleProgramEmissiveCullNone;
|
||||
gpu::ShaderPointer _simpleShader;
|
||||
gpu::ShaderPointer _emissiveShader;
|
||||
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
||||
|
||||
ProgramObject _directionalSkyboxLight;
|
||||
LightLocations _directionalSkyboxLightLocations;
|
||||
|
@ -160,4 +162,53 @@ private:
|
|||
model::SkyboxPointer _skybox;
|
||||
};
|
||||
|
||||
class SimpleProgramKey {
|
||||
public:
|
||||
enum FlagBit {
|
||||
IS_TEXTURED_FLAG = 0,
|
||||
IS_CULLED_FLAG,
|
||||
IS_EMISSIVE_FLAG,
|
||||
HAS_DEPTH_BIAS_FLAG,
|
||||
|
||||
NUM_FLAGS,
|
||||
};
|
||||
|
||||
enum Flag {
|
||||
IS_TEXTURED = (1 << IS_TEXTURED_FLAG),
|
||||
IS_CULLED = (1 << IS_CULLED_FLAG),
|
||||
IS_EMISSIVE = (1 << IS_EMISSIVE_FLAG),
|
||||
HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG),
|
||||
};
|
||||
typedef unsigned short Flags;
|
||||
|
||||
bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }
|
||||
|
||||
bool isTextured() const { return isFlag(IS_TEXTURED); }
|
||||
bool isCulled() const { return isFlag(IS_CULLED); }
|
||||
bool isEmissive() const { return isFlag(IS_EMISSIVE); }
|
||||
bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); }
|
||||
|
||||
Flags _flags = 0;
|
||||
short _spare = 0;
|
||||
|
||||
int getRaw() const { return *reinterpret_cast<const int*>(this); }
|
||||
|
||||
|
||||
SimpleProgramKey(bool textured = false, bool culled = true,
|
||||
bool emissive = false, bool depthBias = false) {
|
||||
_flags = (textured ? IS_TEXTURED : 0) | (culled ? IS_CULLED : 0) |
|
||||
(emissive ? IS_EMISSIVE : 0) | (depthBias ? HAS_DEPTH_BIAS : 0);
|
||||
}
|
||||
|
||||
SimpleProgramKey(int bitmask) : _flags(bitmask) {}
|
||||
};
|
||||
|
||||
inline uint qHash(const SimpleProgramKey& key, uint seed) {
|
||||
return qHash(key.getRaw(), seed);
|
||||
}
|
||||
|
||||
inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) {
|
||||
return a.getRaw() == b.getRaw();
|
||||
}
|
||||
|
||||
#endif // hifi_DeferredLightingEffect_h
|
||||
|
|
Loading…
Reference in a new issue