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
QUrl uniqueUrl = QUrl(QUuid::createUuid().toString());
_billboardTexture = DependencyManager::get<TextureCache>()->getTexture(
uniqueUrl, DEFAULT_TEXTURE, false, _billboard);
uniqueUrl, DEFAULT_TEXTURE, _billboard);
}
if (!_billboardTexture || !_billboardTexture->isLoaded()) {
return;

View file

@ -143,21 +143,9 @@ public:
const QByteArray& content;
};
NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type, bool dilatable, const QByteArray& content) {
if (!dilatable) {
TextureExtra extra = { type, content };
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;
NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type, const QByteArray& content) {
TextureExtra extra = { type, content };
return ResourceCache::getResource(url, QUrl(), false, &extra).staticCast<NetworkTexture>();
}
/// 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);
// Passing ownership
_gpuTexture.reset(texture);
// _gpuTexture.reset(texture);
_textureStorage->resetTexture(texture);
auto gpuTexture = _textureStorage->getGPUTexture();
if (_gpuTexture) {
_width = _gpuTexture->getWidth();
_height = _gpuTexture->getHeight();
if (gpuTexture) {
_width = gpuTexture->getWidth();
_height = gpuTexture->getHeight();
} else {
_width = _height = 0;
}
@ -586,69 +575,3 @@ void NetworkTexture::imageLoaded(const QImage& image) {
// 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);
/// 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());
protected:
@ -88,7 +88,6 @@ private:
class Texture {
public:
friend class TextureCache;
friend class DilatableNetworkTexture;
Texture();
~Texture();
@ -97,8 +96,6 @@ public:
model::TextureStoragePointer _textureStorage;
protected:
gpu::TexturePointer _gpuTexture;
private:
};
@ -146,29 +143,4 @@ private:
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

View file

@ -356,7 +356,7 @@ public:
protected:
std::unique_ptr< Storage > _storage;
Stamp _stamp = 0;
Sampler _sampler;
@ -380,7 +380,6 @@ protected:
bool _autoGenerateMips = false;
bool _isIrradianceValid = 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);

View file

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

View file

@ -41,6 +41,7 @@ public:
GLOSS_MAP_BIT,
TRANSPARENT_MAP_BIT,
NORMAL_MAP_BIT,
LIGHTMAP_MAP_BIT,
NUM_FLAGS,
};
@ -53,6 +54,7 @@ public:
GLOSS_MAP,
TRANSPARENT_MAP,
NORMAL_MAP,
LIGHTMAP_MAP,
NUM_MAP_CHANNELS,
};
@ -83,6 +85,7 @@ public:
Builder& withTransparentMap() { _flags.set(TRANSPARENT_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
static MaterialKey opaqueDiffuse() { return Builder().withDiffuse().build(); }
@ -122,6 +125,9 @@ public:
void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); }
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); }
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& 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
static MaterialFilter opaqueDiffuse() { return Builder().withDiffuse().withoutTransparent().build(); }
};

View file

@ -14,9 +14,10 @@ using namespace model;
using namespace gpu;
// TextureStorage
TextureStorage::TextureStorage() : Texture::Storage()//,
// _gpuTexture(Texture::createFromStorage(this))
{}
TextureStorage::TextureStorage()
{/* : Texture::Storage()//,
// _gpuTexture(Texture::createFromStorage(this))*/
}
TextureStorage::~TextureStorage() {
}
@ -30,16 +31,22 @@ void TextureStorage::resetTexture(gpu::Texture* texture) {
_gpuTexture.reset(texture);
}
bool TextureStorage::isDefined() const {
if (_gpuTexture) {
return _gpuTexture->isDefined();
} else {
return false;
}
}
void TextureMap::setTextureStorage(TextureStoragePointer& texStorage) {
_textureStorage = texStorage;
}
bool TextureMap::isNull() const {
bool TextureMap::isDefined() const {
if (_textureStorage) {
return _textureStorage->isMipAvailable(0);
return _textureStorage->isDefined();
} else {
return false;
}
@ -51,4 +58,14 @@ gpu::TextureView TextureMap::getTextureView() const {
} else {
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
//
// Created by Sam Gateau on 5/6/2015.
@ -14,6 +14,7 @@
#include "gpu/Texture.h"
#include "Material.h"
#include "Transform.h"
#include <qurl.h>
@ -32,7 +33,7 @@ public:
// 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
// that guides the internal format used
class TextureStorage : public gpu::Texture::Storage {
class TextureStorage {
public:
TextureStorage();
~TextureStorage();
@ -40,12 +41,13 @@ public:
const QUrl& getUrl() const { return _imageUrl; }
gpu::Texture::Type getType() const { return _usage._type; }
const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; }
virtual void reset() { Storage::reset(); }
void reset(const QUrl& url, const TextureUsage& usage);
void resetTexture(gpu::Texture* texture);
bool isDefined() const;
protected:
gpu::TexturePointer _gpuTexture;
TextureUsage _usage;
@ -59,12 +61,20 @@ public:
void setTextureStorage(TextureStoragePointer& texStorage);
bool isNull() const;
bool isDefined() 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:
TextureStoragePointer _textureStorage;
Transform _texcoordTransform;
glm::vec2 _lightmapOffsetScale{ 0.0f, 1.0f };
};
typedef std::shared_ptr< TextureMap > TextureMapPointer;

View file

@ -2035,33 +2035,45 @@ static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const
networkMaterial->_material = material._material;
if (!material.diffuseTexture.filename.isEmpty()) {
// TODO: SOlve the eye case
networkMaterial->diffuseTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.diffuseTexture.filename)), DEFAULT_TEXTURE,
/* mesh.isEye*/ false, material.diffuseTexture.content);
networkMaterial->diffuseTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.diffuseTexture.filename)), DEFAULT_TEXTURE, material.diffuseTexture.content);
networkMaterial->diffuseTextureName = material.diffuseTexture.name;
networkMaterial->_diffuseTexTransform = material.diffuseTexture.transform;
auto diffuseMap = model::TextureMapPointer(new model::TextureMap());
diffuseMap->setTextureStorage(networkMaterial->diffuseTexture->_textureStorage);
diffuseMap->setTextureTransform(material.diffuseTexture.transform);
material._material->setTextureMap(model::MaterialKey::DIFFUSE_MAP, diffuseMap);
}
if (!material.normalTexture.filename.isEmpty()) {
networkMaterial->normalTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.normalTexture.filename)), NORMAL_TEXTURE,
false, material.normalTexture.content);
networkMaterial->normalTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.normalTexture.filename)), NORMAL_TEXTURE, material.normalTexture.content);
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()) {
networkMaterial->specularTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.specularTexture.filename)), SPECULAR_TEXTURE,
false, material.specularTexture.content);
networkMaterial->specularTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.specularTexture.filename)), SPECULAR_TEXTURE, material.specularTexture.content);
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()) {
networkMaterial->emissiveTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.emissiveTexture.filename)), EMISSIVE_TEXTURE,
false, material.emissiveTexture.content);
networkMaterial->emissiveTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.emissiveTexture.filename)), EMISSIVE_TEXTURE, material.emissiveTexture.content);
networkMaterial->emissiveTextureName = material.emissiveTexture.name;
networkMaterial->_emissiveTexTransform = material.emissiveTexture.transform;
networkMaterial->_emissiveParams = material.emissiveParams;
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;

View file

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

View file

@ -97,6 +97,11 @@ Model::~Model() {
Model::RenderPipelineLib Model::_renderPipelineLib;
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,
gpu::ShaderPointer& vertexShader,
@ -104,11 +109,11 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
gpu::Shader::BindingSet slotBindings;
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("normalMap"), 1));
slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2));
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), 4));
slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), DIFFUSE_MAP_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), NORMAL_MAP_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), SPECULAR_MAP_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), LIGHTMAP_MAP_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_BUFFER_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT));
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());
}
auto textureMaps = drawMaterial->_material->getTextureMaps();
auto materialKey = material->getKey();
auto textureMaps = material->getTextureMaps();
glm::mat4 texcoordTransform[2];
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();
// 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());
}
}
// 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());
}
}
// TODO: For now gloss map is used as the "specular map in the shading, we ll need to fix that
if ((locations->specularTextureUnit >= 0) && materialKey.isGlossMap()) {
auto specularMap = textureMaps[model::MaterialKey::GLOSS_MAP];
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());
}
}
// TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too
if ((locations->emissiveTextureUnit >= 0) && materialKey.isLightmapMap()) {
auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP];
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]);
}
}
}
//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());
else {
batch.setResourceTexture(LIGHTMAP_MAP_SLOT, textureCache->getGrayTexture());
}
}
// Texcoord transforms ?
if (locations->texcoordMatrices >= 0) {
glm::mat4 texcoordTransform[2];
if (!drawMaterial->_diffuseTexTransform.isIdentity()) {
drawMaterial->_diffuseTexTransform.getMatrix(texcoordTransform[0]);
}
if (!drawMaterial->_emissiveTexTransform.isIdentity()) {
drawMaterial->_emissiveTexTransform.getMatrix(texcoordTransform[1]);
}
batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);
batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*)&texcoordTransform);
}
if (!mesh.tangents.isEmpty()) {
NetworkTexture* normalMap = drawMaterial->normalTexture.data();
batch.setResourceTexture(1, (!normalMap || !normalMap->isLoaded()) ?
textureCache->getBlueTexture() : normalMap->getGPUTexture());
// 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 (locations->specularTextureUnit >= 0) {
NetworkTexture* specularMap = drawMaterial->specularTexture.data();
batch.setResourceTexture(locations->specularTextureUnit, (!specularMap || !specularMap->isLoaded()) ?
textureCache->getBlackTexture() : specularMap->getGPUTexture());
}
if (args) {
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);
}
}
}