mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
gizmos have materials, working on images
This commit is contained in:
parent
c869554d46
commit
25e4f59d55
8 changed files with 286 additions and 148 deletions
|
@ -29,6 +29,8 @@
|
|||
#include "RenderableZoneEntityItem.h"
|
||||
#include "RenderableMaterialEntityItem.h"
|
||||
|
||||
#include "RenderPipelines.h"
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
|
@ -149,10 +151,11 @@ Item::Bound EntityRenderer::getBound(RenderArgs* args) {
|
|||
}
|
||||
|
||||
ShapeKey EntityRenderer::getShapeKey() {
|
||||
ShapeKey::Builder builder = ShapeKey::Builder().withOwnPipeline();
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
return ShapeKey::Builder().withOwnPipeline().withWireframe();
|
||||
builder.withWireframe();
|
||||
}
|
||||
return ShapeKey::Builder().withOwnPipeline();
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
render::hifi::Tag EntityRenderer::getTagMask() const {
|
||||
|
@ -365,6 +368,7 @@ bool EntityRenderer::needsRenderUpdate() const {
|
|||
if (_prevIsTransparent != isTransparent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return needsRenderUpdateFromEntity(_entity);
|
||||
}
|
||||
|
||||
|
@ -486,6 +490,170 @@ void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const st
|
|||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
EntityRenderer::Pipeline EntityRenderer::getPipelineType(const graphics::MultiMaterial& materials) {
|
||||
if (materials.top().material && materials.top().material->isProcedural() && materials.top().material->isReady()) {
|
||||
return Pipeline::PROCEDURAL;
|
||||
}
|
||||
|
||||
graphics::MaterialKey drawMaterialKey = materials.getMaterialKey();
|
||||
if (drawMaterialKey.isEmissive() || drawMaterialKey.isUnlit() || drawMaterialKey.isMetallic() || drawMaterialKey.isScattering()) {
|
||||
return Pipeline::MATERIAL;
|
||||
}
|
||||
|
||||
// If the material is using any map, we need to use a material ShapeKey
|
||||
for (int i = 0; i < graphics::Material::MapChannel::NUM_MAP_CHANNELS; i++) {
|
||||
if (drawMaterialKey.isMapChannel(graphics::Material::MapChannel(i))) {
|
||||
return Pipeline::MATERIAL;
|
||||
}
|
||||
}
|
||||
return Pipeline::SIMPLE;
|
||||
}
|
||||
|
||||
bool EntityRenderer::needsRenderUpdateFromMaterials() const {
|
||||
MaterialMap::const_iterator materials;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
materials = _materials.find("0");
|
||||
|
||||
if (materials == _materials.cend()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (materials->second.shouldUpdate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials->second.top().material);
|
||||
if (procedural->isFading()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntityRenderer::updateMaterials(bool baseMaterialChanged) {
|
||||
MaterialMap::iterator materials;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
materials = _materials.find("0");
|
||||
|
||||
if (materials == _materials.end()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (baseMaterialChanged) {
|
||||
materials->second.setNeedsUpdate(true);
|
||||
}
|
||||
|
||||
bool requestUpdate = false;
|
||||
if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials->second.top().material);
|
||||
if (procedural->isFading()) {
|
||||
procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f);
|
||||
requestUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (materials->second.shouldUpdate()) {
|
||||
RenderPipelines::updateMultiMaterial(materials->second);
|
||||
requestUpdate = true;
|
||||
}
|
||||
|
||||
if (requestUpdate) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
bool EntityRenderer::materialsTransparent() const {
|
||||
MaterialMap::const_iterator materials;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
materials = _materials.find("0");
|
||||
|
||||
if (materials == _materials.cend()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (materials->second.top().material) {
|
||||
if (materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials->second.top().material);
|
||||
if (procedural->isFading()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (materials->second.getMaterialKey().isTranslucent()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Item::Bound EntityRenderer::getMaterialBound(RenderArgs* args) {
|
||||
MaterialMap::iterator materials;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
materials = _materials.find("0");
|
||||
|
||||
if (materials == _materials.end()) {
|
||||
return EntityRenderer::getBound(args);
|
||||
}
|
||||
}
|
||||
|
||||
if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials->second.top().material);
|
||||
if (procedural->hasVertexShader() && procedural->hasBoundOperator()) {
|
||||
return procedural->getBound(args);
|
||||
}
|
||||
}
|
||||
|
||||
return EntityRenderer::getBound(args);
|
||||
}
|
||||
|
||||
EntityRenderer::MaterialMap::iterator EntityRenderer::getAndUpdateMaterials() {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
auto materials = _materials.find("0");
|
||||
if (materials != _materials.end() && materials->second.shouldUpdate()) {
|
||||
RenderPipelines::updateMultiMaterial(materials->second);
|
||||
}
|
||||
|
||||
return materials;
|
||||
}
|
||||
|
||||
void EntityRenderer::updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& builder, MaterialMap::iterator materials) const {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
if (materials == _materials.end()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
builder.withCullFaceMode(materials->second.getCullFaceMode());
|
||||
auto pipelineType = getPipelineType(materials->second);
|
||||
if (pipelineType == Pipeline::MATERIAL) {
|
||||
builder.withMaterial();
|
||||
|
||||
graphics::MaterialKey drawMaterialKey = materials->second.getMaterialKey();
|
||||
if (drawMaterialKey.isNormalMap()) {
|
||||
builder.withTangents();
|
||||
}
|
||||
if (drawMaterialKey.isLightMap()) {
|
||||
builder.withLightMap();
|
||||
}
|
||||
if (drawMaterialKey.isUnlit()) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
} else if (pipelineType == Pipeline::PROCEDURAL) {
|
||||
builder.withOwnPipeline();
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec4 EntityRenderer::calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start) {
|
||||
if (pulseProperties.getPeriod() == 0.0f || (pulseProperties.getColorMode() == PulseMode::NONE && pulseProperties.getAlphaMode() == PulseMode::NONE)) {
|
||||
return color;
|
||||
|
|
|
@ -55,8 +55,14 @@ public:
|
|||
|
||||
const uint64_t& getUpdateTime() const { return _updateTime; }
|
||||
|
||||
enum class Pipeline {
|
||||
SIMPLE,
|
||||
MATERIAL,
|
||||
PROCEDURAL
|
||||
};
|
||||
virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName);
|
||||
virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName);
|
||||
static Pipeline getPipelineType(const graphics::MultiMaterial& materials);
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); }
|
||||
|
||||
|
@ -119,6 +125,15 @@ protected:
|
|||
static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters);
|
||||
const Transform& getModelTransform() const;
|
||||
|
||||
// Shared methods for entities that support materials
|
||||
using MaterialMap = std::unordered_map<std::string, graphics::MultiMaterial>;
|
||||
bool needsRenderUpdateFromMaterials() const;
|
||||
void updateMaterials(bool baseMaterialChanged = false);
|
||||
bool materialsTransparent() const;
|
||||
Item::Bound getMaterialBound(RenderArgs* args);
|
||||
MaterialMap::iterator getAndUpdateMaterials();
|
||||
void updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& builder, MaterialMap::iterator materials) const;
|
||||
|
||||
Item::Bound _bound;
|
||||
SharedSoundPointer _collisionSound;
|
||||
QUuid _changeHandlerId;
|
||||
|
@ -139,8 +154,8 @@ protected:
|
|||
bool _moving { false };
|
||||
Transform _renderTransform;
|
||||
|
||||
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
|
||||
std::mutex _materialsLock;
|
||||
MaterialMap _materials;
|
||||
mutable std::mutex _materialsLock;
|
||||
|
||||
quint64 _created;
|
||||
|
||||
|
|
|
@ -11,10 +11,15 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
|
||||
#include "RenderPipelines.h"
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
GizmoEntityRenderer::GizmoEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {}
|
||||
GizmoEntityRenderer::GizmoEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||
_material->setCullFaceMode(graphics::MaterialKey::CullFaceMode::CULL_NONE);
|
||||
addMaterial(graphics::MaterialLayer(_material, 0), "0");
|
||||
}
|
||||
|
||||
GizmoEntityRenderer::~GizmoEntityRenderer() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
@ -31,12 +36,8 @@ GizmoEntityRenderer::~GizmoEntityRenderer() {
|
|||
}
|
||||
}
|
||||
|
||||
bool GizmoEntityRenderer::isTransparent() const {
|
||||
bool ringTransparent = _gizmoType == GizmoType::RING && (_ringProperties.getInnerStartAlpha() < 1.0f ||
|
||||
_ringProperties.getInnerEndAlpha() < 1.0f || _ringProperties.getOuterStartAlpha() < 1.0f ||
|
||||
_ringProperties.getOuterEndAlpha() < 1.0f);
|
||||
|
||||
return Parent::isTransparent() || ringTransparent;
|
||||
bool GizmoEntityRenderer::needsRenderUpdate() const {
|
||||
return needsRenderUpdateFromMaterials() || Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
void GizmoEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
|
@ -193,10 +194,20 @@ void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateMaterials();
|
||||
}
|
||||
|
||||
bool GizmoEntityRenderer::isTransparent() const {
|
||||
bool ringTransparent = _gizmoType == GizmoType::RING && (_ringProperties.getInnerStartAlpha() < 1.0f ||
|
||||
_ringProperties.getInnerEndAlpha() < 1.0f || _ringProperties.getOuterStartAlpha() < 1.0f ||
|
||||
_ringProperties.getOuterEndAlpha() < 1.0f);
|
||||
|
||||
return ringTransparent || Parent::isTransparent() || materialsTransparent();
|
||||
}
|
||||
|
||||
Item::Bound GizmoEntityRenderer::getBound(RenderArgs* args) {
|
||||
auto bound = Parent::getBound(args);
|
||||
auto bound = Parent::getMaterialBound(args);
|
||||
if (_ringProperties.getHasTickMarks()) {
|
||||
glm::vec3 scale = bound.getScale();
|
||||
for (int i = 0; i < 3; i += 2) {
|
||||
|
@ -221,12 +232,19 @@ Item::Bound GizmoEntityRenderer::getBound(RenderArgs* args) {
|
|||
|
||||
ShapeKey GizmoEntityRenderer::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace();
|
||||
|
||||
auto mat = getAndUpdateMaterials();
|
||||
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
builder.withUnlit().withDepthBias().withWireframe();
|
||||
}
|
||||
|
||||
updateShapeKeyBuilderFromMaterials(builder, mat);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -249,15 +267,32 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
|
|||
transparent = isTransparent();
|
||||
});
|
||||
|
||||
graphics::MultiMaterial materials;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
materials = _materials["0"];
|
||||
}
|
||||
|
||||
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
|
||||
geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||
//geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, materials.getCullFaceMode());
|
||||
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true));
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
Pipeline pipelineType = getPipelineType(materials);
|
||||
if (pipelineType == Pipeline::PROCEDURAL) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials.top().material);
|
||||
transparent |= procedural->isFading();
|
||||
procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(transparent));
|
||||
} else {
|
||||
if (RenderPipelines::bindMaterials(materials, batch, args->_renderMode, args->_enableTexturing)) {
|
||||
args->_details._materialSwitches++;
|
||||
}
|
||||
}
|
||||
|
||||
// Background circle
|
||||
geometryCache->renderVertices(batch, wireframe ? gpu::LINE_STRIP : _solidPrimitive, _ringGeometryID);
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <GizmoEntityItem.h>
|
||||
|
||||
#include <procedural/Procedural.h>
|
||||
|
||||
namespace render { namespace entities {
|
||||
|
||||
class GizmoEntityRenderer : public TypedEntityRenderer<GizmoEntityItem> {
|
||||
|
@ -29,10 +31,12 @@ protected:
|
|||
bool isTransparent() const override;
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
std::shared_ptr<graphics::ProceduralMaterial> _material { std::make_shared<graphics::ProceduralMaterial>() };
|
||||
GizmoType _gizmoType { UNSET_GIZMO_TYPE };
|
||||
RingGizmoPropertyGroup _ringProperties;
|
||||
PrimitiveMode _prevPrimitiveMode;
|
||||
|
|
|
@ -25,8 +25,8 @@ ImageEntityRenderer::~ImageEntityRenderer() {
|
|||
}
|
||||
}
|
||||
|
||||
bool ImageEntityRenderer::isTransparent() const {
|
||||
return Parent::isTransparent() || (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()) || _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE;
|
||||
bool ImageEntityRenderer::needsRenderUpdate() const {
|
||||
return needsRenderUpdateFromMaterials() || Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
|
@ -63,6 +63,18 @@ void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
emit requestRenderUpdate();
|
||||
}
|
||||
_textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed());
|
||||
|
||||
updateMaterials();
|
||||
}
|
||||
|
||||
bool ImageEntityRenderer::isTransparent() const {
|
||||
bool imageTransparent = _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE ||
|
||||
(_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha());
|
||||
return imageTransparent || Parent::isTransparent() || materialsTransparent();
|
||||
}
|
||||
|
||||
Item::Bound ImageEntityRenderer::getBound(RenderArgs* args) {
|
||||
return Parent::getMaterialBound(args);
|
||||
}
|
||||
|
||||
ShapeKey ImageEntityRenderer::getShapeKey() {
|
||||
|
|
|
@ -23,11 +23,13 @@ public:
|
|||
~ImageEntityRenderer();
|
||||
|
||||
protected:
|
||||
Item::Bound getBound(RenderArgs* args) override;
|
||||
ShapeKey getShapeKey() override;
|
||||
|
||||
bool isTransparent() const override;
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
|
|
@ -29,26 +29,7 @@ ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Pare
|
|||
}
|
||||
|
||||
bool ShapeEntityRenderer::needsRenderUpdate() const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
auto mat = _materials.find("0");
|
||||
if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() &&
|
||||
mat->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(mat->second.top().material);
|
||||
if (procedural->isFading()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mat != _materials.end() && mat->second.shouldUpdate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parent::needsRenderUpdate();
|
||||
return needsRenderUpdateFromMaterials() || Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
|
@ -94,81 +75,21 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
materialChanged = true;
|
||||
}
|
||||
|
||||
withReadLock([&] {
|
||||
auto materials = _materials.find("0");
|
||||
if (materials != _materials.end()) {
|
||||
if (materialChanged) {
|
||||
materials->second.setNeedsUpdate(true);
|
||||
}
|
||||
|
||||
bool requestUpdate = false;
|
||||
if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials->second.top().material);
|
||||
if (procedural->isFading()) {
|
||||
procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f);
|
||||
requestUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (materials->second.shouldUpdate()) {
|
||||
RenderPipelines::updateMultiMaterial(materials->second);
|
||||
requestUpdate = true;
|
||||
}
|
||||
|
||||
if (requestUpdate) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
}
|
||||
});
|
||||
updateMaterials(materialChanged);
|
||||
}
|
||||
|
||||
bool ShapeEntityRenderer::isTransparent() const {
|
||||
if (_pulseProperties.getAlphaMode() != PulseMode::NONE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto mat = _materials.find("0");
|
||||
if (mat != _materials.end() && mat->second.top().material) {
|
||||
if (mat->second.top().material->isProcedural() && mat->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(mat->second.top().material);
|
||||
if (procedural->isFading()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mat->second.getMaterialKey().isTranslucent()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Parent::isTransparent();
|
||||
return _pulseProperties.getAlphaMode() != PulseMode::NONE || Parent::isTransparent() || materialsTransparent();
|
||||
}
|
||||
|
||||
ShapeEntityRenderer::Pipeline ShapeEntityRenderer::getPipelineType(const graphics::MultiMaterial& materials) const {
|
||||
if (materials.top().material && materials.top().material->isProcedural() && materials.top().material->isReady()) {
|
||||
return Pipeline::PROCEDURAL;
|
||||
}
|
||||
|
||||
graphics::MaterialKey drawMaterialKey = materials.getMaterialKey();
|
||||
if (drawMaterialKey.isEmissive() || drawMaterialKey.isUnlit() || drawMaterialKey.isMetallic() || drawMaterialKey.isScattering()) {
|
||||
return Pipeline::MATERIAL;
|
||||
}
|
||||
|
||||
// If the material is using any map, we need to use a material ShapeKey
|
||||
for (int i = 0; i < graphics::Material::MapChannel::NUM_MAP_CHANNELS; i++) {
|
||||
if (drawMaterialKey.isMapChannel(graphics::Material::MapChannel(i))) {
|
||||
return Pipeline::MATERIAL;
|
||||
}
|
||||
}
|
||||
return Pipeline::SIMPLE;
|
||||
Item::Bound ShapeEntityRenderer::getBound(RenderArgs* args) {
|
||||
return Parent::getMaterialBound(args);
|
||||
}
|
||||
|
||||
ShapeKey ShapeEntityRenderer::getShapeKey() {
|
||||
ShapeKey::Builder builder;
|
||||
auto mat = _materials.find("0");
|
||||
if (mat != _materials.end() && mat->second.shouldUpdate()) {
|
||||
RenderPipelines::updateMultiMaterial(mat->second);
|
||||
}
|
||||
|
||||
auto mat = getAndUpdateMaterials();
|
||||
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
|
@ -178,71 +99,46 @@ ShapeKey ShapeEntityRenderer::getShapeKey() {
|
|||
builder.withWireframe();
|
||||
}
|
||||
|
||||
auto pipelineType = getPipelineType(mat->second);
|
||||
if (pipelineType == Pipeline::MATERIAL) {
|
||||
builder.withMaterial();
|
||||
|
||||
graphics::MaterialKey drawMaterialKey = mat->second.getMaterialKey();
|
||||
if (drawMaterialKey.isNormalMap()) {
|
||||
builder.withTangents();
|
||||
}
|
||||
if (drawMaterialKey.isLightMap()) {
|
||||
builder.withLightMap();
|
||||
}
|
||||
if (drawMaterialKey.isUnlit()) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
builder.withCullFaceMode(mat->second.getCullFaceMode());
|
||||
} else if (pipelineType == Pipeline::PROCEDURAL) {
|
||||
builder.withOwnPipeline();
|
||||
}
|
||||
updateShapeKeyBuilderFromMaterials(builder, mat);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
Item::Bound ShapeEntityRenderer::getBound(RenderArgs* args) {
|
||||
auto mat = _materials.find("0");
|
||||
if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() &&
|
||||
mat->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(mat->second.top().material);
|
||||
if (procedural->hasVertexShader() && procedural->hasBoundOperator()) {
|
||||
return procedural->getBound(args);
|
||||
}
|
||||
}
|
||||
return Parent::getBound(args);
|
||||
}
|
||||
|
||||
void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
||||
Q_ASSERT(args->_batch);
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
graphics::MultiMaterial materials;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
GeometryCache::Shape geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||
glm::vec4 outColor;
|
||||
Pipeline pipelineType;
|
||||
Transform transform;
|
||||
withReadLock([&] {
|
||||
transform = _renderTransform;
|
||||
materials = _materials["0"];
|
||||
pipelineType = getPipelineType(materials);
|
||||
auto& schema = materials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
|
||||
outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity);
|
||||
});
|
||||
|
||||
graphics::MultiMaterial materials;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
materials = _materials["0"];
|
||||
}
|
||||
|
||||
auto& schema = materials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
|
||||
glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity);
|
||||
outColor = EntityRenderer::calculatePulseColor(outColor, _pulseProperties, _created);
|
||||
|
||||
if (outColor.a == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(),
|
||||
_shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron));
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
Pipeline pipelineType = getPipelineType(materials);
|
||||
if (pipelineType == Pipeline::PROCEDURAL) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials.top().material);
|
||||
outColor = procedural->getColor(outColor);
|
||||
|
@ -251,7 +147,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
});
|
||||
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) {
|
||||
if (wireframe) {
|
||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
||||
} else {
|
||||
geometryCache->renderShape(batch, geometryShape, outColor);
|
||||
|
@ -259,12 +155,21 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
} else if (pipelineType == Pipeline::SIMPLE) {
|
||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false,
|
||||
_renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode());
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) {
|
||||
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||
bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
if (outColor.a >= 1.0f) {
|
||||
render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(false, wireframe,
|
||||
forward, materials.top().material->getCullFaceMode());
|
||||
if (wireframe) {
|
||||
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||
} else {
|
||||
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||
}
|
||||
} else {
|
||||
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||
if (wireframe) {
|
||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
||||
} else {
|
||||
geometryCache->renderShape(batch, geometryShape, outColor);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (RenderPipelines::bindMaterials(materials, batch, args->_renderMode, args->_enableTexturing)) {
|
||||
|
|
|
@ -35,9 +35,6 @@ private:
|
|||
virtual void doRender(RenderArgs* args) override;
|
||||
virtual bool isTransparent() const override;
|
||||
|
||||
enum Pipeline { SIMPLE, MATERIAL, PROCEDURAL };
|
||||
Pipeline getPipelineType(const graphics::MultiMaterial& materials) const;
|
||||
|
||||
QString _proceduralData;
|
||||
entity::Shape _shape { entity::Sphere };
|
||||
|
||||
|
|
Loading…
Reference in a new issue