Migrating the rendering code to the Material Maps and adding the simplae variables to the the TextutreMap

This commit is contained in:
samcake 2015-09-18 18:47:18 -07:00
parent a804767d8f
commit 8941741508
11 changed files with 157 additions and 208 deletions

View file

@ -645,7 +645,7 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
// Using a unique URL ensures we don't get another avatar's texture from TextureCache // Using a unique URL ensures we don't get another avatar's texture from TextureCache
QUrl uniqueUrl = QUrl(QUuid::createUuid().toString()); QUrl uniqueUrl = QUrl(QUuid::createUuid().toString());
_billboardTexture = DependencyManager::get<TextureCache>()->getTexture( _billboardTexture = DependencyManager::get<TextureCache>()->getTexture(
uniqueUrl, DEFAULT_TEXTURE, false, _billboard); uniqueUrl, DEFAULT_TEXTURE, _billboard);
} }
if (!_billboardTexture || !_billboardTexture->isLoaded()) { if (!_billboardTexture || !_billboardTexture->isLoaded()) {
return; return;

View file

@ -143,21 +143,9 @@ public:
const QByteArray& content; const QByteArray& content;
}; };
NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type, bool dilatable, const QByteArray& content) { NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type, const QByteArray& content) {
if (!dilatable) {
TextureExtra extra = { type, content }; TextureExtra extra = { type, content };
return ResourceCache::getResource(url, QUrl(), false, &extra).staticCast<NetworkTexture>(); return ResourceCache::getResource(url, QUrl(), false, &extra).staticCast<NetworkTexture>();
}
NetworkTexturePointer texture = _dilatableNetworkTextures.value(url);
if (texture.isNull()) {
texture = NetworkTexturePointer(new DilatableNetworkTexture(url, content), &Resource::allReferencesCleared);
texture->setSelf(texture);
texture->setCache(this);
_dilatableNetworkTextures.insert(url, texture);
} else {
removeUnusedResource(texture);
}
return texture;
} }
/// Returns a texture version of an image file /// Returns a texture version of an image file
@ -567,12 +555,13 @@ void NetworkTexture::setImage(const QImage& image, void* voidTexture, bool trans
gpu::Texture* texture = static_cast<gpu::Texture*>(voidTexture); gpu::Texture* texture = static_cast<gpu::Texture*>(voidTexture);
// Passing ownership // Passing ownership
_gpuTexture.reset(texture); // _gpuTexture.reset(texture);
_textureStorage->resetTexture(texture); _textureStorage->resetTexture(texture);
auto gpuTexture = _textureStorage->getGPUTexture();
if (_gpuTexture) { if (gpuTexture) {
_width = _gpuTexture->getWidth(); _width = gpuTexture->getWidth();
_height = _gpuTexture->getHeight(); _height = gpuTexture->getHeight();
} else { } else {
_width = _height = 0; _width = _height = 0;
} }
@ -586,69 +575,3 @@ void NetworkTexture::imageLoaded(const QImage& image) {
// nothing by default // nothing by default
} }
DilatableNetworkTexture::DilatableNetworkTexture(const QUrl& url, const QByteArray& content) :
NetworkTexture(url, DEFAULT_TEXTURE, content),
_innerRadius(0),
_outerRadius(0)
{
}
QSharedPointer<Texture> DilatableNetworkTexture::getDilatedTexture(float dilation) {
QSharedPointer<Texture> texture = _dilatedTextures.value(dilation);
if (texture.isNull()) {
texture = QSharedPointer<Texture>::create();
if (!_image.isNull()) {
QImage dilatedImage = _image;
QPainter painter;
painter.begin(&dilatedImage);
QPainterPath path;
qreal radius = glm::mix((float) _innerRadius, (float) _outerRadius, dilation);
path.addEllipse(QPointF(_image.width() / 2.0, _image.height() / 2.0), radius, radius);
painter.fillPath(path, Qt::black);
painter.end();
bool isLinearRGB = true;// (_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
if (dilatedImage.hasAlphaChannel()) {
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
// FIXME either remove the ?: operator or provide different arguments depending on linear
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::BGRA));
}
texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, dilatedImage.width(), dilatedImage.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
texture->_gpuTexture->assignStoredMip(0, formatMip, dilatedImage.byteCount(), dilatedImage.constBits());
texture->_gpuTexture->autoGenerateMips(-1);
}
_dilatedTextures.insert(dilation, texture);
}
return texture;
}
void DilatableNetworkTexture::imageLoaded(const QImage& image) {
_image = image;
// scan out from the center to find inner and outer radii
int halfWidth = image.width() / 2;
int halfHeight = image.height() / 2;
const int BLACK_THRESHOLD = 32;
while (_innerRadius < halfWidth && qGray(image.pixel(halfWidth + _innerRadius, halfHeight)) < BLACK_THRESHOLD) {
_innerRadius++;
}
_outerRadius = _innerRadius;
const int TRANSPARENT_THRESHOLD = 32;
while (_outerRadius < halfWidth && qAlpha(image.pixel(halfWidth + _outerRadius, halfHeight)) > TRANSPARENT_THRESHOLD) {
_outerRadius++;
}
// clear out any textures we generated before loading
_dilatedTextures.clear();
}
void DilatableNetworkTexture::reinsert() {
static_cast<TextureCache*>(_cache.data())->_dilatableNetworkTextures.insert(_url,
qWeakPointerCast<NetworkTexture, Resource>(_self));
}

View file

@ -61,7 +61,7 @@ public:
static gpu::TexturePointer getImageTexture(const QString& path); static gpu::TexturePointer getImageTexture(const QString& path);
/// Loads a texture from the specified URL. /// Loads a texture from the specified URL.
NetworkTexturePointer getTexture(const QUrl& url, TextureType type = DEFAULT_TEXTURE, bool dilatable = false, NetworkTexturePointer getTexture(const QUrl& url, TextureType type = DEFAULT_TEXTURE,
const QByteArray& content = QByteArray()); const QByteArray& content = QByteArray());
protected: protected:
@ -88,7 +88,6 @@ private:
class Texture { class Texture {
public: public:
friend class TextureCache; friend class TextureCache;
friend class DilatableNetworkTexture;
Texture(); Texture();
~Texture(); ~Texture();
@ -97,8 +96,6 @@ public:
model::TextureStoragePointer _textureStorage; model::TextureStoragePointer _textureStorage;
protected: protected:
gpu::TexturePointer _gpuTexture;
private: private:
}; };
@ -146,29 +143,4 @@ private:
int _height; int _height;
}; };
/// Caches derived, dilated textures.
class DilatableNetworkTexture : public NetworkTexture {
Q_OBJECT
public:
DilatableNetworkTexture(const QUrl& url, const QByteArray& content);
/// Returns a pointer to a texture with the requested amount of dilation.
QSharedPointer<Texture> getDilatedTexture(float dilation);
protected:
virtual void imageLoaded(const QImage& image);
virtual void reinsert();
private:
QImage _image;
int _innerRadius;
int _outerRadius;
QMap<float, QWeakPointer<Texture> > _dilatedTextures;
};
#endif // hifi_TextureCache_h #endif // hifi_TextureCache_h

View file

@ -381,7 +381,6 @@ protected:
bool _isIrradianceValid = false; bool _isIrradianceValid = false;
bool _defined = false; bool _defined = false;
static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler); static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler);
Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices); Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices);

View file

@ -82,7 +82,7 @@ void Material::setOpacity(float opacity) {
} }
void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) { void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) {
if (textureMap && !textureMap->isNull()) { if (textureMap) {
_key.setMapChannel(channel, (true)); _key.setMapChannel(channel, (true));
_textureMaps[channel] = textureMap; _textureMaps[channel] = textureMap;
} else { } else {

View file

@ -41,6 +41,7 @@ public:
GLOSS_MAP_BIT, GLOSS_MAP_BIT,
TRANSPARENT_MAP_BIT, TRANSPARENT_MAP_BIT,
NORMAL_MAP_BIT, NORMAL_MAP_BIT,
LIGHTMAP_MAP_BIT,
NUM_FLAGS, NUM_FLAGS,
}; };
@ -53,6 +54,7 @@ public:
GLOSS_MAP, GLOSS_MAP,
TRANSPARENT_MAP, TRANSPARENT_MAP,
NORMAL_MAP, NORMAL_MAP,
LIGHTMAP_MAP,
NUM_MAP_CHANNELS, NUM_MAP_CHANNELS,
}; };
@ -83,6 +85,7 @@ public:
Builder& withTransparentMap() { _flags.set(TRANSPARENT_MAP_BIT); return (*this); } Builder& withTransparentMap() { _flags.set(TRANSPARENT_MAP_BIT); return (*this); }
Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); } Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); }
Builder& withLightmapMap() { _flags.set(LIGHTMAP_MAP_BIT); return (*this); }
// Convenient standard keys that we will keep on using all over the place // Convenient standard keys that we will keep on using all over the place
static MaterialKey opaqueDiffuse() { return Builder().withDiffuse().build(); } static MaterialKey opaqueDiffuse() { return Builder().withDiffuse().build(); }
@ -122,6 +125,9 @@ public:
void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); } void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); }
bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; } bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; }
void setLightmapMap(bool value) { _flags.set(LIGHTMAP_MAP_BIT, value); }
bool isLightmapMap() const { return _flags[LIGHTMAP_MAP_BIT]; }
void setMapChannel(MapChannel channel, bool value) { _flags.set(EMISSIVE_MAP_BIT + channel, value); } void setMapChannel(MapChannel channel, bool value) { _flags.set(EMISSIVE_MAP_BIT + channel, value); }
bool isMapChannel(MapChannel channel) const { return _flags[EMISSIVE_MAP_BIT + channel]; } bool isMapChannel(MapChannel channel) const { return _flags[EMISSIVE_MAP_BIT + channel]; }
@ -177,6 +183,9 @@ public:
Builder& withoutNormalMap() { _value.reset(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); } Builder& withoutNormalMap() { _value.reset(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); }
Builder& withNormalMap() { _value.set(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); } Builder& withNormalMap() { _value.set(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); }
Builder& withoutLightmapMap() { _value.reset(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
Builder& withLightmapMap() { _value.set(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
// Convenient standard keys that we will keep on using all over the place // Convenient standard keys that we will keep on using all over the place
static MaterialFilter opaqueDiffuse() { return Builder().withDiffuse().withoutTransparent().build(); } static MaterialFilter opaqueDiffuse() { return Builder().withDiffuse().withoutTransparent().build(); }
}; };

View file

@ -14,9 +14,10 @@ using namespace model;
using namespace gpu; using namespace gpu;
// TextureStorage // TextureStorage
TextureStorage::TextureStorage() : Texture::Storage()//, TextureStorage::TextureStorage()
// _gpuTexture(Texture::createFromStorage(this)) {/* : Texture::Storage()//,
{} // _gpuTexture(Texture::createFromStorage(this))*/
}
TextureStorage::~TextureStorage() { TextureStorage::~TextureStorage() {
} }
@ -30,16 +31,22 @@ void TextureStorage::resetTexture(gpu::Texture* texture) {
_gpuTexture.reset(texture); _gpuTexture.reset(texture);
} }
bool TextureStorage::isDefined() const {
if (_gpuTexture) {
return _gpuTexture->isDefined();
} else {
return false;
}
}
void TextureMap::setTextureStorage(TextureStoragePointer& texStorage) { void TextureMap::setTextureStorage(TextureStoragePointer& texStorage) {
_textureStorage = texStorage; _textureStorage = texStorage;
} }
bool TextureMap::isNull() const { bool TextureMap::isDefined() const {
if (_textureStorage) { if (_textureStorage) {
return _textureStorage->isMipAvailable(0); return _textureStorage->isDefined();
} else { } else {
return false; return false;
} }
@ -52,3 +59,13 @@ gpu::TextureView TextureMap::getTextureView() const {
return gpu::TextureView(); return gpu::TextureView();
} }
} }
void TextureMap::setTextureTransform(const Transform& texcoordTransform) {
_texcoordTransform = texcoordTransform;
}
void TextureMap::setLightmapOffsetScale(float offset, float scale) {
_lightmapOffsetScale.x = offset;
_lightmapOffsetScale.y = scale;
}

View file

@ -1,5 +1,5 @@
// //
// TextureStorage.h // TextureMap.h
// libraries/model/src/model // libraries/model/src/model
// //
// Created by Sam Gateau on 5/6/2015. // Created by Sam Gateau on 5/6/2015.
@ -14,6 +14,7 @@
#include "gpu/Texture.h" #include "gpu/Texture.h"
#include "Material.h" #include "Material.h"
#include "Transform.h"
#include <qurl.h> #include <qurl.h>
@ -32,7 +33,7 @@ public:
// TextureStorage is a specialized version of the gpu::Texture::Storage // TextureStorage is a specialized version of the gpu::Texture::Storage
// It provides the mechanism to create a texture from a Url and the intended usage // It provides the mechanism to create a texture from a Url and the intended usage
// that guides the internal format used // that guides the internal format used
class TextureStorage : public gpu::Texture::Storage { class TextureStorage {
public: public:
TextureStorage(); TextureStorage();
~TextureStorage(); ~TextureStorage();
@ -41,11 +42,12 @@ public:
gpu::Texture::Type getType() const { return _usage._type; } gpu::Texture::Type getType() const { return _usage._type; }
const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; } const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; }
virtual void reset() { Storage::reset(); }
void reset(const QUrl& url, const TextureUsage& usage); void reset(const QUrl& url, const TextureUsage& usage);
void resetTexture(gpu::Texture* texture); void resetTexture(gpu::Texture* texture);
bool isDefined() const;
protected: protected:
gpu::TexturePointer _gpuTexture; gpu::TexturePointer _gpuTexture;
TextureUsage _usage; TextureUsage _usage;
@ -59,12 +61,20 @@ public:
void setTextureStorage(TextureStoragePointer& texStorage); void setTextureStorage(TextureStoragePointer& texStorage);
bool isNull() const; bool isDefined() const;
gpu::TextureView getTextureView() const; gpu::TextureView getTextureView() const;
void setTextureTransform(const Transform& texcoordTransform);
const Transform& getTextureTransform() const { return _texcoordTransform; }
void setLightmapOffsetScale(float offset, float scale);
const glm::vec2& getLightmapOffsetScale() const { return _lightmapOffsetScale; }
protected: protected:
TextureStoragePointer _textureStorage; TextureStoragePointer _textureStorage;
Transform _texcoordTransform;
glm::vec2 _lightmapOffsetScale{ 0.0f, 1.0f };
}; };
typedef std::shared_ptr< TextureMap > TextureMapPointer; typedef std::shared_ptr< TextureMap > TextureMapPointer;

View file

@ -2035,33 +2035,45 @@ static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const
networkMaterial->_material = material._material; networkMaterial->_material = material._material;
if (!material.diffuseTexture.filename.isEmpty()) { if (!material.diffuseTexture.filename.isEmpty()) {
// TODO: SOlve the eye case networkMaterial->diffuseTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.diffuseTexture.filename)), DEFAULT_TEXTURE, material.diffuseTexture.content);
networkMaterial->diffuseTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.diffuseTexture.filename)), DEFAULT_TEXTURE,
/* mesh.isEye*/ false, material.diffuseTexture.content);
networkMaterial->diffuseTextureName = material.diffuseTexture.name; networkMaterial->diffuseTextureName = material.diffuseTexture.name;
networkMaterial->_diffuseTexTransform = material.diffuseTexture.transform;
auto diffuseMap = model::TextureMapPointer(new model::TextureMap()); auto diffuseMap = model::TextureMapPointer(new model::TextureMap());
diffuseMap->setTextureStorage(networkMaterial->diffuseTexture->_textureStorage); diffuseMap->setTextureStorage(networkMaterial->diffuseTexture->_textureStorage);
diffuseMap->setTextureTransform(material.diffuseTexture.transform);
material._material->setTextureMap(model::MaterialKey::DIFFUSE_MAP, diffuseMap); material._material->setTextureMap(model::MaterialKey::DIFFUSE_MAP, diffuseMap);
} }
if (!material.normalTexture.filename.isEmpty()) { if (!material.normalTexture.filename.isEmpty()) {
networkMaterial->normalTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.normalTexture.filename)), NORMAL_TEXTURE, networkMaterial->normalTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.normalTexture.filename)), NORMAL_TEXTURE, material.normalTexture.content);
false, material.normalTexture.content);
networkMaterial->normalTextureName = material.normalTexture.name; networkMaterial->normalTextureName = material.normalTexture.name;
auto normalMap = model::TextureMapPointer(new model::TextureMap());
normalMap->setTextureStorage(networkMaterial->normalTexture->_textureStorage);
material._material->setTextureMap(model::MaterialKey::NORMAL_MAP, normalMap);
} }
if (!material.specularTexture.filename.isEmpty()) { if (!material.specularTexture.filename.isEmpty()) {
networkMaterial->specularTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.specularTexture.filename)), SPECULAR_TEXTURE, networkMaterial->specularTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.specularTexture.filename)), SPECULAR_TEXTURE, material.specularTexture.content);
false, material.specularTexture.content);
networkMaterial->specularTextureName = material.specularTexture.name; networkMaterial->specularTextureName = material.specularTexture.name;
auto glossMap = model::TextureMapPointer(new model::TextureMap());
glossMap->setTextureStorage(networkMaterial->specularTexture->_textureStorage);
material._material->setTextureMap(model::MaterialKey::GLOSS_MAP, glossMap);
} }
if (!material.emissiveTexture.filename.isEmpty()) { if (!material.emissiveTexture.filename.isEmpty()) {
networkMaterial->emissiveTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.emissiveTexture.filename)), EMISSIVE_TEXTURE, networkMaterial->emissiveTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.emissiveTexture.filename)), EMISSIVE_TEXTURE, material.emissiveTexture.content);
false, material.emissiveTexture.content);
networkMaterial->emissiveTextureName = material.emissiveTexture.name; networkMaterial->emissiveTextureName = material.emissiveTexture.name;
networkMaterial->_emissiveTexTransform = material.emissiveTexture.transform;
networkMaterial->_emissiveParams = material.emissiveParams;
checkForTexcoordLightmap = true; checkForTexcoordLightmap = true;
auto lightmapMap = model::TextureMapPointer(new model::TextureMap());
lightmapMap->setTextureStorage(networkMaterial->emissiveTexture->_textureStorage);
lightmapMap->setTextureTransform(material.emissiveTexture.transform);
lightmapMap->setLightmapOffsetScale(material.emissiveParams.x, material.emissiveParams.y);
material._material->setTextureMap(model::MaterialKey::LIGHTMAP_MAP, lightmapMap);
} }
return networkMaterial; return networkMaterial;

View file

@ -438,11 +438,6 @@ public:
QSharedPointer<NetworkTexture> specularTexture; QSharedPointer<NetworkTexture> specularTexture;
QString emissiveTextureName; QString emissiveTextureName;
QSharedPointer<NetworkTexture> emissiveTexture; QSharedPointer<NetworkTexture> emissiveTexture;
Transform _diffuseTexTransform;
Transform _emissiveTexTransform;
glm::vec2 _emissiveParams;
}; };

View file

@ -97,6 +97,11 @@ Model::~Model() {
Model::RenderPipelineLib Model::_renderPipelineLib; Model::RenderPipelineLib Model::_renderPipelineLib;
const int MATERIAL_GPU_SLOT = 3; const int MATERIAL_GPU_SLOT = 3;
const int DIFFUSE_MAP_SLOT = 0;
const int NORMAL_MAP_SLOT = 1;
const int SPECULAR_MAP_SLOT = 2;
const int LIGHTMAP_MAP_SLOT = 3;
const int LIGHT_BUFFER_SLOT = 4;
void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& vertexShader,
@ -104,11 +109,11 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
gpu::Shader::BindingSet slotBindings; gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), DIFFUSE_MAP_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), NORMAL_MAP_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), SPECULAR_MAP_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), LIGHTMAP_MAP_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), 4)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_BUFFER_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT));
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader));
@ -1642,75 +1647,82 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shape
batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer());
} }
auto textureMaps = drawMaterial->_material->getTextureMaps(); auto materialKey = material->getKey();
auto textureMaps = material->getTextureMaps();
auto diffuseMap2 = textureMaps[model::MaterialKey::DIFFUSE_MAP];
Texture* diffuseMap = drawMaterial->diffuseTexture.data();
if (mesh.isEye && diffuseMap) {
// FIXME - guard against out of bounds here
if (meshIndex < _dilatedTextures.size()) {
if (partIndex < _dilatedTextures[meshIndex].size()) {
diffuseMap = (_dilatedTextures[meshIndex][partIndex] =
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
}
}
}
//if (diffuseMap && static_cast<NetworkTexture*>(diffuseMap)->isLoaded()) {
if (diffuseMap2 && !diffuseMap2->isNull()) {
batch.setResourceTexture(0, diffuseMap2->getTextureView());
// batch.setResourceTexture(0, diffuseMap->getGPUTexture());
} else {
batch.setResourceTexture(0, textureCache->getGrayTexture());
}
if (locations->texcoordMatrices >= 0) {
glm::mat4 texcoordTransform[2]; glm::mat4 texcoordTransform[2];
if (!drawMaterial->_diffuseTexTransform.isIdentity()) {
drawMaterial->_diffuseTexTransform.getMatrix(texcoordTransform[0]); // Diffuse
if (materialKey.isDiffuseMap()) {
auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP];
if (diffuseMap && diffuseMap->isDefined()) {
batch.setResourceTexture(DIFFUSE_MAP_SLOT, diffuseMap->getTextureView());
if (!diffuseMap->getTextureTransform().isIdentity()) {
diffuseMap->getTextureTransform().getMatrix(texcoordTransform[0]);
}
} else {
batch.setResourceTexture(DIFFUSE_MAP_SLOT, textureCache->getGrayTexture());
} }
if (!drawMaterial->_emissiveTexTransform.isIdentity()) {
drawMaterial->_emissiveTexTransform.getMatrix(texcoordTransform[1]);
} }
batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); // Normal map
if (materialKey.isNormalMap()) {
auto normalMap = textureMaps[model::MaterialKey::NORMAL_MAP];
if (normalMap && normalMap->isDefined()) {
batch.setResourceTexture(NORMAL_MAP_SLOT, normalMap->getTextureView());
// texcoord are assumed to be the same has diffuse
} else {
batch.setResourceTexture(NORMAL_MAP_SLOT, textureCache->getBlueTexture());
}
} }
if (!mesh.tangents.isEmpty()) { // TODO: For now gloss map is used as the "specular map in the shading, we ll need to fix that
NetworkTexture* normalMap = drawMaterial->normalTexture.data(); if ((locations->specularTextureUnit >= 0) && materialKey.isGlossMap()) {
batch.setResourceTexture(1, (!normalMap || !normalMap->isLoaded()) ? auto specularMap = textureMaps[model::MaterialKey::GLOSS_MAP];
textureCache->getBlueTexture() : normalMap->getGPUTexture()); if (specularMap && specularMap->isDefined()) {
batch.setResourceTexture(SPECULAR_MAP_SLOT, specularMap->getTextureView());
// texcoord are assumed to be the same has diffuse
} else {
batch.setResourceTexture(SPECULAR_MAP_SLOT, textureCache->getBlackTexture());
}
} }
if (locations->specularTextureUnit >= 0) { // TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too
NetworkTexture* specularMap = drawMaterial->specularTexture.data(); if ((locations->emissiveTextureUnit >= 0) && materialKey.isLightmapMap()) {
batch.setResourceTexture(locations->specularTextureUnit, (!specularMap || !specularMap->isLoaded()) ? auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP];
textureCache->getBlackTexture() : specularMap->getGPUTexture());
if (lightmapMap && lightmapMap->isDefined()) {
batch.setResourceTexture(LIGHTMAP_MAP_SLOT, lightmapMap->getTextureView());
auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale();
batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y);
if (!lightmapMap->getTextureTransform().isIdentity()) {
lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]);
} }
}
else {
batch.setResourceTexture(LIGHTMAP_MAP_SLOT, textureCache->getGrayTexture());
}
}
// Texcoord transforms ?
if (locations->texcoordMatrices >= 0) {
batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*)&texcoordTransform);
}
// TODO: We should be able to do that just in the renderTransparentJob
if (translucentMesh && locations->lightBufferUnit >= 0) {
DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit);
}
if (args) { if (args) {
args->_details._materialSwitches++; args->_details._materialSwitches++;
} }
// HACK: For unknown reason (yet!) this code that should be assigned only if the material changes need to be called for every
// drawcall with an emissive, so let's do it for now.
if (locations->emissiveTextureUnit >= 0) {
// assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader
//float emissiveOffset = part.emissiveParams.x;
//float emissiveScale = part.emissiveParams.y;
float emissiveOffset = drawMaterial->_emissiveParams.x;
float emissiveScale = drawMaterial->_emissiveParams.y;
batch._glUniform2f(locations->emissiveParams, emissiveOffset, emissiveScale);
NetworkTexture* emissiveMap = drawMaterial->emissiveTexture.data();
batch.setResourceTexture(locations->emissiveTextureUnit, (!emissiveMap || !emissiveMap->isLoaded()) ?
textureCache->getGrayTexture() : emissiveMap->getGPUTexture());
}
if (translucentMesh && locations->lightBufferUnit >= 0) {
DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit);
}
} }
} }