Merge pull request #6811 from Atlante45/master

Fix skybox not always rendering correctly
This commit is contained in:
Brad Hefta-Gaub 2016-01-13 21:00:48 -08:00
commit 8f8afabbfe
6 changed files with 159 additions and 173 deletions

View file

@ -3635,10 +3635,15 @@ public:
render::ItemID BackgroundRenderData::_item = 0;
namespace render {
template <> const ItemKey payloadGetKey(const BackgroundRenderData::Pointer& stuff) { return ItemKey::Builder::background(); }
template <> const Item::Bound payloadGetBound(const BackgroundRenderData::Pointer& stuff) { return Item::Bound(); }
template <> void payloadRender(const BackgroundRenderData::Pointer& background, RenderArgs* args) {
template <> const ItemKey payloadGetKey(const BackgroundRenderData::Pointer& stuff) {
return ItemKey::Builder::background();
}
template <> const Item::Bound payloadGetBound(const BackgroundRenderData::Pointer& stuff) {
return Item::Bound();
}
template <> void payloadRender(const BackgroundRenderData::Pointer& background, RenderArgs* args) {
Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch;
@ -3646,20 +3651,18 @@ namespace render {
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
auto backgroundMode = skyStage->getBackgroundMode();
if (backgroundMode == model::SunSkyStage::NO_BACKGROUND) {
// this line intentionally left blank
} else {
if (backgroundMode == model::SunSkyStage::SKY_BOX) {
switch (backgroundMode) {
case model::SunSkyStage::SKY_BOX: {
auto skybox = skyStage->getSkybox();
if (skybox && skybox->getCubemap() && skybox->getCubemap()->isDefined()) {
PerformanceTimer perfTimer("skybox");
skybox->render(batch, *(args->_viewFrustum));
} else {
// If no skybox texture is available, render the SKY_DOME while it loads
backgroundMode = model::SunSkyStage::SKY_DOME;
break;
}
// If no skybox texture is available, render the SKY_DOME while it loads
}
if (backgroundMode == model::SunSkyStage::SKY_DOME) {
// fall through to next case
case model::SunSkyStage::SKY_DOME: {
if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
PerformanceTimer perfTimer("stars");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
@ -3725,6 +3728,11 @@ namespace render {
}
}
break;
case model::SunSkyStage::NO_BACKGROUND:
default:
// this line intentionally left blank
break;
}
}
}

View file

@ -23,7 +23,6 @@
#include <SceneScriptingInterface.h>
#include <ScriptEngine.h>
#include <procedural/ProceduralSkybox.h>
#include <TextureCache.h>
#include "EntityTreeRenderer.h"
@ -141,7 +140,7 @@ void EntityTreeRenderer::update() {
// even if we haven't changed positions, if we previously attempted to set the skybox, but
// have a pending download of the skybox texture, then we should attempt to reapply to
// get the correct texture.
if (_pendingSkyboxTextureDownload) {
if (_pendingSkyboxTexture && _skyboxTexture && _skyboxTexture->isLoaded()) {
applyZonePropertiesToScene(_bestZone);
}
@ -254,94 +253,17 @@ void EntityTreeRenderer::forceRecheckEntities() {
void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone) {
QSharedPointer<SceneScriptingInterface> scene = DependencyManager::get<SceneScriptingInterface>();
auto scene = DependencyManager::get<SceneScriptingInterface>();
auto sceneStage = scene->getStage();
auto skyStage = scene->getSkyStage();
auto sceneKeyLight = sceneStage->getKeyLight();
auto sceneLocation = sceneStage->getLocation();
auto sceneTime = sceneStage->getTime();
if (!zone) {
_pendingSkyboxTexture = false;
_skyboxTexture.clear();
if (zone) {
if (!_hasPreviousZone) {
_previousKeyLightColor = sceneKeyLight->getColor();
_previousKeyLightIntensity = sceneKeyLight->getIntensity();
_previousKeyLightAmbientIntensity = sceneKeyLight->getAmbientIntensity();
_previousKeyLightDirection = sceneKeyLight->getDirection();
_previousStageSunModelEnabled = sceneStage->isSunModelEnabled();
_previousStageLongitude = sceneLocation->getLongitude();
_previousStageLatitude = sceneLocation->getLatitude();
_previousStageAltitude = sceneLocation->getAltitude();
_previousStageHour = sceneTime->getHour();
_previousStageDay = sceneTime->getDay();
_hasPreviousZone = true;
}
sceneKeyLight->setColor(ColorUtils::toVec3(zone->getKeyLightProperties().getColor()));
sceneKeyLight->setIntensity(zone->getKeyLightProperties().getIntensity());
sceneKeyLight->setAmbientIntensity(zone->getKeyLightProperties().getAmbientIntensity());
sceneKeyLight->setDirection(zone->getKeyLightProperties().getDirection());
sceneStage->setSunModelEnable(zone->getStageProperties().getSunModelEnabled());
sceneStage->setLocation(zone->getStageProperties().getLongitude(), zone->getStageProperties().getLatitude(),
zone->getStageProperties().getAltitude());
sceneTime->setHour(zone->getStageProperties().calculateHour());
sceneTime->setDay(zone->getStageProperties().calculateDay());
if (zone->getBackgroundMode() == BACKGROUND_MODE_ATMOSPHERE) {
EnvironmentData data = zone->getEnvironmentData();
glm::vec3 keyLightDirection = sceneKeyLight->getDirection();
glm::vec3 inverseKeyLightDirection = keyLightDirection * -1.0f;
// NOTE: is this right? It seems like the "sun" should be based on the center of the
// atmosphere, not where the camera is.
glm::vec3 keyLightLocation = _viewState->getAvatarPosition()
+ (inverseKeyLightDirection * data.getAtmosphereOuterRadius());
data.setSunLocation(keyLightLocation);
const float KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO = 20.0f;
float sunBrightness = sceneKeyLight->getIntensity() * KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO;
data.setSunBrightness(sunBrightness);
_viewState->overrideEnvironmentData(data);
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME);
_pendingSkyboxTextureDownload = false;
} else {
_viewState->endOverrideEnvironmentData();
auto stage = scene->getSkyStage();
if (zone->getBackgroundMode() == BACKGROUND_MODE_SKYBOX) {
auto skybox = std::dynamic_pointer_cast<ProceduralSkybox>(stage->getSkybox());
skybox->setColor(zone->getSkyboxProperties().getColorVec3());
static QString userData;
if (userData != zone->getUserData()) {
userData = zone->getUserData();
ProceduralPointer procedural(new Procedural(userData));
if (procedural->_enabled) {
skybox->setProcedural(procedural);
} else {
skybox->setProcedural(ProceduralPointer());
}
}
if (zone->getSkyboxProperties().getURL().isEmpty()) {
skybox->setCubemap(gpu::TexturePointer());
_pendingSkyboxTextureDownload = false;
} else {
// Update the Texture of the Skybox with the one pointed by this zone
auto cubeMap = DependencyManager::get<TextureCache>()->getTexture(zone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
if (cubeMap->getGPUTexture()) {
skybox->setCubemap(cubeMap->getGPUTexture());
_pendingSkyboxTextureDownload = false;
} else {
_pendingSkyboxTextureDownload = true;
}
}
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
} else {
stage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
_pendingSkyboxTextureDownload = false;
}
}
} else {
_pendingSkyboxTextureDownload = false;
if (_hasPreviousZone) {
sceneKeyLight->setColor(_previousKeyLightColor);
sceneKeyLight->setIntensity(_previousKeyLightIntensity);
@ -354,14 +276,106 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
sceneTime->setDay(_previousStageDay);
_hasPreviousZone = false;
}
_viewState->endOverrideEnvironmentData();
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
return; // Early exit
}
if (!_hasPreviousZone) {
_previousKeyLightColor = sceneKeyLight->getColor();
_previousKeyLightIntensity = sceneKeyLight->getIntensity();
_previousKeyLightAmbientIntensity = sceneKeyLight->getAmbientIntensity();
_previousKeyLightDirection = sceneKeyLight->getDirection();
_previousStageSunModelEnabled = sceneStage->isSunModelEnabled();
_previousStageLongitude = sceneLocation->getLongitude();
_previousStageLatitude = sceneLocation->getLatitude();
_previousStageAltitude = sceneLocation->getAltitude();
_previousStageHour = sceneTime->getHour();
_previousStageDay = sceneTime->getDay();
_hasPreviousZone = true;
}
sceneKeyLight->setColor(ColorUtils::toVec3(zone->getKeyLightProperties().getColor()));
sceneKeyLight->setIntensity(zone->getKeyLightProperties().getIntensity());
sceneKeyLight->setAmbientIntensity(zone->getKeyLightProperties().getAmbientIntensity());
sceneKeyLight->setDirection(zone->getKeyLightProperties().getDirection());
sceneStage->setSunModelEnable(zone->getStageProperties().getSunModelEnabled());
sceneStage->setLocation(zone->getStageProperties().getLongitude(), zone->getStageProperties().getLatitude(),
zone->getStageProperties().getAltitude());
sceneTime->setHour(zone->getStageProperties().calculateHour());
sceneTime->setDay(zone->getStageProperties().calculateDay());
switch (zone->getBackgroundMode()) {
case BACKGROUND_MODE_ATMOSPHERE: {
EnvironmentData data = zone->getEnvironmentData();
glm::vec3 keyLightDirection = sceneKeyLight->getDirection();
glm::vec3 inverseKeyLightDirection = keyLightDirection * -1.0f;
// NOTE: is this right? It seems like the "sun" should be based on the center of the
// atmosphere, not where the camera is.
glm::vec3 keyLightLocation = _viewState->getAvatarPosition() +
(inverseKeyLightDirection * data.getAtmosphereOuterRadius());
data.setSunLocation(keyLightLocation);
const float KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO = 20.0f;
float sunBrightness = sceneKeyLight->getIntensity() * KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO;
data.setSunBrightness(sunBrightness);
_viewState->overrideEnvironmentData(data);
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME);
_pendingSkyboxTexture = false;
_skyboxTexture.clear();
break;
}
case BACKGROUND_MODE_SKYBOX: {
auto skybox = std::dynamic_pointer_cast<ProceduralSkybox>(skyStage->getSkybox());
skybox->setColor(zone->getSkyboxProperties().getColorVec3());
static QString userData;
if (userData != zone->getUserData()) {
userData = zone->getUserData();
auto procedural = std::make_shared<Procedural>(userData);
if (procedural->_enabled) {
skybox->setProcedural(procedural);
} else {
skybox->setProcedural(ProceduralPointer());
}
}
if (zone->getSkyboxProperties().getURL().isEmpty()) {
skybox->setCubemap(gpu::TexturePointer());
_pendingSkyboxTexture = false;
_skyboxTexture.clear();
} else {
// Update the Texture of the Skybox with the one pointed by this zone
auto textureCache = DependencyManager::get<TextureCache>();
_skyboxTexture = textureCache->getTexture(zone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
if (_skyboxTexture->getGPUTexture()) {
skybox->setCubemap(_skyboxTexture->getGPUTexture());
_pendingSkyboxTexture = false;
} else {
_pendingSkyboxTexture = true;
}
}
_viewState->endOverrideEnvironmentData();
skyStage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
break;
}
case BACKGROUND_MODE_INHERIT:
_viewState->endOverrideEnvironmentData();
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
_pendingSkyboxTexture = false;
_skyboxTexture.clear();
break;
}
}
const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer entityItem) {
const FBXGeometry* result = NULL;
if (entityItem->getType() == EntityTypes::Model) {
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);

View file

@ -15,12 +15,13 @@
#include <QSet>
#include <QStack>
#include <EntityTree.h>
#include <AbstractAudioInterface.h>
#include <EntityScriptingInterface.h> // for RayToEntityIntersectionResult
#include <EntityTree.h>
#include <MouseEvent.h>
#include <OctreeRenderer.h>
#include <ScriptCache.h>
#include <AbstractAudioInterface.h>
#include <TextureCache.h>
class AbstractScriptingServicesInterface;
class AbstractViewStateInterface;
@ -142,9 +143,11 @@ private:
void forceRecheckEntities();
glm::vec3 _lastAvatarPosition;
bool _pendingSkyboxTextureDownload = false;
QVector<EntityItemID> _currentEntitiesInside;
bool _pendingSkyboxTexture { false };
NetworkTexturePointer _skyboxTexture;
bool _wantScripts;
ScriptEngine* _entitiesScriptEngine;
@ -161,11 +164,11 @@ private:
bool _displayModelBounds;
bool _dontDoPrecisionPicking;
bool _shuttingDown = false;
bool _shuttingDown { false };
QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
bool _hasPreviousZone = false;
bool _hasPreviousZone { false };
std::shared_ptr<ZoneEntityItem> _bestZone;
float _bestZoneVolume;

View file

@ -147,7 +147,6 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u
if (_meshes.size() > 0) {
auto textureCache = DependencyManager::get<TextureCache>();
for (auto&& material : _materials) {
QSharedPointer<NetworkTexture> matchingTexture = QSharedPointer<NetworkTexture>();
if (material->diffuseTextureName == name) {
material->diffuseTexture = textureCache->getTexture(url, DEFAULT_TEXTURE);
} else if (material->normalTextureName == name) {

View file

@ -72,11 +72,12 @@ const gpu::TexturePointer& TextureCache::getPermutationNormalTexture() {
data[3*i+0] = permutation[i];
data[3*i+1] = permutation[i];
data[3*i+2] = permutation[i];
}
#else
for (int i = 0; i < 256 * 3; i++) {
data[i] = rand() % 256;
#endif
}
#endif
for (int i = 256 * 3; i < 256 * 3 * 2; i += 3) {
glm::vec3 randvec = glm::sphericalRand(1.0f);
@ -173,19 +174,11 @@ QSharedPointer<Resource> TextureCache::createResource(const QUrl& url,
&Resource::allReferencesCleared);
}
Texture::Texture() {
}
Texture::~Texture() {
}
NetworkTexture::NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content) :
Resource(url, !content.isEmpty()),
_type(type),
_width(0),
_height(0) {
_textureSource.reset(new gpu::TextureSource());
_type(type)
{
_textureSource = std::make_shared<gpu::TextureSource>();
if (!url.isValid()) {
_loaded = true;
@ -200,24 +193,9 @@ NetworkTexture::NetworkTexture(const QUrl& url, TextureType type, const QByteArr
}
NetworkTexture::NetworkTexture(const QUrl& url, const TextureLoaderFunc& textureLoader, const QByteArray& content) :
Resource(url, !content.isEmpty()),
_type(CUSTOM_TEXTURE),
_textureLoader(textureLoader),
_width(0),
_height(0) {
_textureSource.reset(new gpu::TextureSource());
if (!url.isValid()) {
_loaded = true;
}
std::string theName = url.toString().toStdString();
// if we have content, load it after we have our self pointer
if (!content.isEmpty()) {
_startedLoading = true;
QMetaObject::invokeMethod(this, "loadContent", Qt::QueuedConnection, Q_ARG(const QByteArray&, content));
}
NetworkTexture(url, CUSTOM_TEXTURE, content)
{
_textureLoader = textureLoader;
}
NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
@ -247,57 +225,52 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
}
}
}
class ImageReader : public QRunnable {
public:
ImageReader(const QWeakPointer<Resource>& texture, const NetworkTexture::TextureLoaderFunc& textureLoader, const QByteArray& data, const QUrl& url = QUrl());
ImageReader(const QWeakPointer<Resource>& texture, const QByteArray& data, const QUrl& url = QUrl());
virtual void run();
private:
static void listSupportedImageFormats();
QWeakPointer<Resource> _texture;
NetworkTexture::TextureLoaderFunc _textureLoader;
QUrl _url;
QByteArray _content;
};
void NetworkTexture::downloadFinished(const QByteArray& data) {
// send the reader off to the thread pool
QThreadPool::globalInstance()->start(new ImageReader(_self, getTextureLoader(), data, _url));
QThreadPool::globalInstance()->start(new ImageReader(_self, data, _url));
}
void NetworkTexture::loadContent(const QByteArray& content) {
QThreadPool::globalInstance()->start(new ImageReader(_self, getTextureLoader(), content, _url));
QThreadPool::globalInstance()->start(new ImageReader(_self, content, _url));
}
ImageReader::ImageReader(const QWeakPointer<Resource>& texture, const NetworkTexture::TextureLoaderFunc& textureLoader, const QByteArray& data,
ImageReader::ImageReader(const QWeakPointer<Resource>& texture, const QByteArray& data,
const QUrl& url) :
_texture(texture),
_textureLoader(textureLoader),
_url(url),
_content(data)
{
}
std::once_flag onceListSupportedFormatsflag;
void listSupportedImageFormats() {
std::call_once(onceListSupportedFormatsflag, [](){
void ImageReader::listSupportedImageFormats() {
static std::once_flag once;
std::call_once(once, []{
auto supportedFormats = QImageReader::supportedImageFormats();
QString formats;
foreach(const QByteArray& f, supportedFormats) {
formats += QString(f) + ",";
}
qCDebug(modelnetworking) << "List of supported Image formats:" << formats;
qCDebug(modelnetworking) << "List of supported Image formats:" << supportedFormats.join(", ");
});
}
void ImageReader::run() {
QSharedPointer<Resource> texture = _texture.toStrongRef();
if (texture.isNull()) {
auto texture = _texture.toStrongRef();
if (!texture) {
qCWarning(modelnetworking) << "Could not get strong ref";
return;
}
@ -324,7 +297,7 @@ void ImageReader::run() {
}
gpu::Texture* theTexture = nullptr;
auto ntex = dynamic_cast<NetworkTexture*>(&*texture);
auto ntex = texture.dynamicCast<NetworkTexture>();
if (ntex) {
theTexture = ntex->getTextureLoader()(image, _url.toString().toStdString());
}
@ -333,8 +306,6 @@ void ImageReader::run() {
Q_ARG(const QImage&, image),
Q_ARG(void*, theTexture),
Q_ARG(int, originalWidth), Q_ARG(int, originalHeight));
}
void NetworkTexture::setImage(const QImage& image, void* voidTexture, int originalWidth,

View file

@ -67,9 +67,6 @@ public:
typedef gpu::Texture* TextureLoader(const QImage& image, const std::string& srcImageName);
typedef std::function<TextureLoader> TextureLoaderFunc;
NetworkTexturePointer getTexture(const QUrl& url, const TextureLoaderFunc& textureLoader,
const QByteArray& content = QByteArray());
protected:
virtual QSharedPointer<Resource> createResource(const QUrl& url,
@ -94,15 +91,9 @@ private:
class Texture {
public:
friend class TextureCache;
Texture();
~Texture();
const gpu::TexturePointer getGPUTexture() const { return _textureSource->getGPUTexture(); }
gpu::TexturePointer getGPUTexture() const { return _textureSource->getGPUTexture(); }
gpu::TextureSourcePointer _textureSource;
protected:
private:
};
/// A texture loaded from the network.
@ -134,14 +125,14 @@ protected:
virtual void imageLoaded(const QImage& image);
TextureType _type;
private:
TextureType _type;
TextureLoaderFunc _textureLoader;
int _originalWidth;
int _originalHeight;
int _width;
int _height;
int _originalWidth { 0 };
int _originalHeight { 0 };
int _width { 0 };
int _height { 0 };
};
#endif // hifi_TextureCache_h