mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Merge pull request #16086 from AndrewMeadows/opaque-polylines
BUGZ-1170: improved render bounding box for PolyLines; use opaque pipeline when possible
This commit is contained in:
commit
b33e5a60c2
8 changed files with 94 additions and 24 deletions
|
@ -101,7 +101,7 @@ protected:
|
|||
virtual void doRender(RenderArgs* args) = 0;
|
||||
|
||||
virtual bool isFading() const { return _isFading; }
|
||||
void updateModelTransformAndBound();
|
||||
virtual void updateModelTransformAndBound();
|
||||
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
||||
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
|
||||
|
||||
|
@ -124,7 +124,6 @@ signals:
|
|||
protected:
|
||||
template<typename T>
|
||||
std::shared_ptr<T> asTypedEntity() { return std::static_pointer_cast<T>(_entity); }
|
||||
|
||||
|
||||
static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters);
|
||||
const Transform& getModelTransform() const;
|
||||
|
@ -153,7 +152,6 @@ protected:
|
|||
|
||||
quint64 _created;
|
||||
|
||||
private:
|
||||
// The base class relies on comparing the model transform to the entity transform in order
|
||||
// to trigger an update, so the member must not be visible to derived classes as a modifiable
|
||||
// transform
|
||||
|
|
|
@ -41,23 +41,55 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
|
|||
}
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::buildPipelines() {
|
||||
// FIXME: opaque pipelines
|
||||
void PolyLineEntityRenderer::updateModelTransformAndBound() {
|
||||
bool success = false;
|
||||
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||
if (success) {
|
||||
_modelTransform = newModelTransform;
|
||||
|
||||
auto lineEntity = std::static_pointer_cast<PolyLineEntityItem>(_entity);
|
||||
AABox bound;
|
||||
lineEntity->computeTightLocalBoundingBox(bound);
|
||||
bound.transform(newModelTransform);
|
||||
_bound = bound;
|
||||
}
|
||||
}
|
||||
|
||||
bool PolyLineEntityRenderer::isTransparent() const {
|
||||
return _glow || (_textureLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha());
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::buildPipelines() {
|
||||
static const std::vector<std::pair<render::Args::RenderMethod, bool>> keys = {
|
||||
{ render::Args::DEFERRED, false }, { render::Args::DEFERRED, true }, { render::Args::FORWARD, false }, { render::Args::FORWARD, true },
|
||||
};
|
||||
|
||||
for (auto& key : keys) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(key.first == render::Args::DEFERRED ? shader::entities_renderer::program::paintStroke : shader::entities_renderer::program::paintStroke_forward);
|
||||
gpu::ShaderPointer program;
|
||||
render::Args::RenderMethod renderMethod = key.first;
|
||||
bool transparent = key.second;
|
||||
|
||||
if (renderMethod == render::Args::DEFERRED) {
|
||||
if (transparent) {
|
||||
program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke_translucent);
|
||||
} else {
|
||||
program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke);
|
||||
}
|
||||
} else { // render::Args::FORWARD
|
||||
program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke_forward);
|
||||
}
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
state->setCullMode(gpu::State::CullMode::CULL_NONE);
|
||||
state->setDepthTest(true, !key.second, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setDepthTest(true, !transparent, gpu::LESS_EQUAL);
|
||||
if (transparent) {
|
||||
PrepareStencil::testMask(*state);
|
||||
} else {
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
}
|
||||
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
state->setBlendFunction(transparent, 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);
|
||||
|
||||
_pipelines[key] = gpu::Pipeline::create(program, state);
|
||||
|
@ -65,11 +97,16 @@ void PolyLineEntityRenderer::buildPipelines() {
|
|||
}
|
||||
|
||||
ItemKey PolyLineEntityRenderer::getKey() {
|
||||
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||
return isTransparent() ?
|
||||
ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()) :
|
||||
ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||
}
|
||||
|
||||
ShapeKey PolyLineEntityRenderer::getShapeKey() {
|
||||
auto builder = ShapeKey::Builder().withOwnPipeline().withTranslucent().withoutCullFace();
|
||||
auto builder = ShapeKey::Builder().withOwnPipeline().withoutCullFace();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
builder.withWireframe();
|
||||
}
|
||||
|
@ -294,7 +331,7 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
|||
buildPipelines();
|
||||
}
|
||||
|
||||
batch.setPipeline(_pipelines[{args->_renderMethod, _glow}]);
|
||||
batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]);
|
||||
batch.setModelTransform(transform);
|
||||
batch.setResourceTexture(0, texture);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * numVertices), 0);
|
||||
|
|
|
@ -25,8 +25,9 @@ class PolyLineEntityRenderer : public TypedEntityRenderer<PolyLineEntityItem> {
|
|||
public:
|
||||
PolyLineEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
// FIXME: shouldn't always be transparent: take into account texture and glow
|
||||
virtual bool isTransparent() const override { return true; }
|
||||
void updateModelTransformAndBound() override;
|
||||
|
||||
virtual bool isTransparent() const override;
|
||||
|
||||
protected:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
|
|
|
@ -1 +1 @@
|
|||
DEFINES forward
|
||||
DEFINES translucent:f forward
|
||||
|
|
|
@ -34,7 +34,11 @@ void main(void) {
|
|||
texel.a *= mix(1.0, pow(1.0 - min(1.0, abs(_distanceFromCenter)), 10.0), _polylineData.faceCameraGlow.y);
|
||||
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS);
|
||||
<@if HIFI_USE_TRANSLUCENT@>
|
||||
packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS);
|
||||
<@else@>
|
||||
packDeferredFragmentUnlit((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb);
|
||||
<@endif@>
|
||||
<@else@>
|
||||
_fragColor0 = texel;
|
||||
<@endif@>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <QDebug>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
#include <Extents.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItemProperties.h"
|
||||
|
@ -85,7 +86,7 @@ void PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
|||
_points = points;
|
||||
_pointsChanged = true;
|
||||
});
|
||||
computeAndUpdateDimensionsAndPosition();
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
|
||||
|
@ -93,7 +94,7 @@ void PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
|
|||
_widths = strokeWidths;
|
||||
_widthsChanged = true;
|
||||
});
|
||||
computeAndUpdateDimensionsAndPosition();
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
|
||||
|
@ -110,7 +111,7 @@ void PolyLineEntityItem::setStrokeColors(const QVector<glm::vec3>& strokeColors)
|
|||
});
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::computeAndUpdateDimensionsAndPosition() {
|
||||
void PolyLineEntityItem::computeAndUpdateDimensions() {
|
||||
QVector<glm::vec3> points;
|
||||
QVector<float> widths;
|
||||
|
||||
|
@ -129,6 +130,32 @@ void PolyLineEntityItem::computeAndUpdateDimensionsAndPosition() {
|
|||
setScaledDimensions(2.0f * (maxHalfDim + maxWidth));
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::computeTightLocalBoundingBox(AABox& localBox) const {
|
||||
QVector<glm::vec3> points;
|
||||
QVector<float> widths;
|
||||
withReadLock([&] {
|
||||
points = _points;
|
||||
widths = _widths;
|
||||
});
|
||||
|
||||
if (points.size() > 0) {
|
||||
Extents extents;
|
||||
float maxWidth = DEFAULT_LINE_WIDTH;
|
||||
for (int i = 0; i < points.length(); i++) {
|
||||
extents.addPoint(points[i]);
|
||||
if (i < widths.size()) {
|
||||
maxWidth = glm::max(maxWidth, widths[i]);
|
||||
}
|
||||
}
|
||||
extents.addPoint(extents.minimum - maxWidth * Vectors::ONE);
|
||||
extents.addPoint(extents.maximum + maxWidth * Vectors::ONE);
|
||||
|
||||
localBox.setBox(extents.minimum, extents.maximum - extents.minimum);
|
||||
} else {
|
||||
localBox.setBox(glm::vec3(-0.5f * DEFAULT_LINE_WIDTH), glm::vec3(DEFAULT_LINE_WIDTH));
|
||||
}
|
||||
}
|
||||
|
||||
int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
|
@ -267,4 +294,4 @@ void PolyLineEntityItem::setFaceCamera(bool faceCamera) {
|
|||
_needsRenderUpdate = _faceCamera != faceCamera;
|
||||
_faceCamera = faceCamera;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "EntityItem.h"
|
||||
|
||||
class PolyLineEntityItem : public EntityItem {
|
||||
public:
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
PolyLineEntityItem(const EntityItemID& entityItemID);
|
||||
|
@ -90,10 +90,12 @@ class PolyLineEntityItem : public EntityItem {
|
|||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const override { return false; }
|
||||
|
||||
void computeTightLocalBoundingBox(AABox& box) const;
|
||||
|
||||
virtual void debugDump() const override;
|
||||
private:
|
||||
void computeAndUpdateDimensionsAndPosition();
|
||||
|
||||
void computeAndUpdateDimensions();
|
||||
|
||||
protected:
|
||||
glm::u8vec3 _color;
|
||||
QVector<glm::vec3> _points;
|
||||
|
|
|
@ -52,7 +52,8 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r
|
|||
}
|
||||
|
||||
void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {
|
||||
if (alpha < 1.0) {
|
||||
// to reduce texel flickering for floating point error we discard when alpha is "almost one"
|
||||
if (alpha < 0.999999) {
|
||||
discard;
|
||||
}
|
||||
_fragColor0 = vec4(color, packUnlit());
|
||||
|
|
Loading…
Reference in a new issue