Integrate the PR from ALessandro through a different Texture Type and a different TextureLoader to transform a bump map into a normal map

This commit is contained in:
samcake 2015-09-21 00:53:48 -07:00
parent 3614812681
commit 6a714f405c
8 changed files with 168 additions and 335 deletions

View file

@ -1080,9 +1080,10 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
} else if (type.contains("transparentcolor")) { // it should be TransparentColor...
// THis is how Maya assign a texture that affect diffuse color AND transparency ?
diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("bump") || type.contains("normal")) {
} else if (type.contains("bump")) {
bumpTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("normal")) {
normalTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("specular") || type.contains("reflection")) {
specularTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));

View file

@ -112,7 +112,9 @@ public:
Transform transform;
int texcoordSet;
QString texcoordSetName;
bool isBumpmap{ false };
bool isNull() const { return name.isEmpty() && filename.isEmpty() && content.isEmpty(); }
};
@ -394,6 +396,7 @@ public:
QHash<QString, QString> diffuseTextures;
QHash<QString, QString> bumpTextures;
QHash<QString, QString> normalTextures;
QHash<QString, QString> specularTextures;
QHash<QString, QString> emissiveTextures;
QHash<QString, QString> ambientTextures;

View file

@ -86,13 +86,21 @@ void FBXReader::consolidateFBXMaterials() {
FBXTexture normalTexture;
QString bumpTextureID = bumpTextures.value(material.materialID);
if (!bumpTextureID.isNull()) {
normalTexture = getTexture(bumpTextureID);
QString normalTextureID = normalTextures.value(material.materialID);
if (!normalTextureID.isNull()) {
normalTexture = getTexture(normalTextureID);
normalTexture.isBumpmap = false;
material.normalTexture = normalTexture;
detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity());
} else if (!bumpTextureID.isNull()) {
normalTexture = getTexture(bumpTextureID);
normalTexture.isBumpmap = true;
material.normalTexture = normalTexture;
detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity());
}
FBXTexture specularTexture;
QString specularTextureID = specularTextures.value(material.materialID);

View file

@ -182,11 +182,10 @@ Texture::~Texture() {
NetworkTexture::NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content) :
Resource(url, !content.isEmpty()),
_type(type),
_translucent(false),
_width(0),
_height(0) {
_textureStorage.reset(new model::TextureStorage());
_textureSource.reset(new model::TextureSource());
if (!url.isValid()) {
_loaded = true;
@ -202,13 +201,12 @@ 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(type),
_type(CUSTOM_TEXTURE),
_textureLoader(textureLoader),
_translucent(false),
_width(0),
_height(0) {
_textureStorage.reset(new model::TextureStorage());
_textureSource.reset(new model::TextureSource());
if (!url.isValid()) {
_loaded = true;
@ -223,11 +221,27 @@ NetworkTexture::NetworkTexture(const QUrl& url, const TextureLoaderFunc& texture
}
NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
if (_type != CUBE_TEXTURE) {
return TextureLoaderFunc(model::TextureStorage::create2DTextureFromImage);
} else {
return TextureLoaderFunc(model::TextureStorage::createCubeTextureFromImage);
switch (_type) {
case CUBE_TEXTURE: {
return TextureLoaderFunc(model::TextureSource::createCubeTextureFromImage);
break;
}
case BUMP_TEXTURE: {
return TextureLoaderFunc(model::TextureSource::createNormalTextureFromBumpImage);
break;
}
case CUSTOM_TEXTURE: {
return _textureLoader;
break;
}
case DEFAULT_TEXTURE:
case NORMAL_TEXTURE:
case SPECULAR_TEXTURE:
case EMISSIVE_TEXTURE:
default: {
return TextureLoaderFunc(model::TextureSource::create2DTextureFromImage);
break;
}
}
}
@ -278,42 +292,6 @@ void listSupportedImageFormats() {
});
}
/*
class CubeLayout {
public:
int _widthRatio = 1;
int _heightRatio = 1;
class Face {
public:
int _x = 0;
int _y = 0;
bool _horizontalMirror = false;
bool _verticalMirror = false;
Face() {}
Face(int x, int y, bool horizontalMirror, bool verticalMirror) : _x(x), _y(y), _horizontalMirror(horizontalMirror), _verticalMirror(verticalMirror) {}
};
Face _faceXPos;
Face _faceXNeg;
Face _faceYPos;
Face _faceYNeg;
Face _faceZPos;
Face _faceZNeg;
CubeLayout(int wr, int hr, Face fXP, Face fXN, Face fYP, Face fYN, Face fZP, Face fZN) :
_widthRatio(wr),
_heightRatio(hr),
_faceXPos(fXP),
_faceXNeg(fXN),
_faceYPos(fYP),
_faceYNeg(fYN),
_faceZPos(fZP),
_faceZNeg(fZN) {}
};
*/
void ImageReader::run() {
QSharedPointer<Resource> texture = _texture.toStrongRef();
if (texture.isNull()) {
@ -347,259 +325,25 @@ void ImageReader::run() {
if (ntex) {
theTexture = ntex->getTextureLoader()(image, _url.toString().toStdString());
}
/*
int imageArea = image.width() * image.height();
gpu::Texture* theTexture = nullptr;
if (ntex && (ntex->getType() == CUBE_TEXTURE)) {
qCDebug(gpunetwork) << "Cube map size:" << _url << image.width() << image.height();
}
int opaquePixels = 0;
int translucentPixels = 0;
bool isTransparent = false;
int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0;
const int EIGHT_BIT_MAXIMUM = 255;
QColor averageColor(EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM);
if (!image.hasAlphaChannel()) {
if (image.format() != QImage::Format_RGB888) {
image = image.convertToFormat(QImage::Format_RGB888);
}
// int redTotal = 0, greenTotal = 0, blueTotal = 0;
for (int y = 0; y < image.height(); y++) {
for (int x = 0; x < image.width(); x++) {
QRgb rgb = image.pixel(x, y);
redTotal += qRed(rgb);
greenTotal += qGreen(rgb);
blueTotal += qBlue(rgb);
}
}
if (imageArea > 0) {
averageColor.setRgb(redTotal / imageArea, greenTotal / imageArea, blueTotal / imageArea);
}
} else {
if (image.format() != QImage::Format_ARGB32) {
image = image.convertToFormat(QImage::Format_ARGB32);
}
// check for translucency/false transparency
// int opaquePixels = 0;
// int translucentPixels = 0;
// int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0;
for (int y = 0; y < image.height(); y++) {
for (int x = 0; x < image.width(); x++) {
QRgb rgb = image.pixel(x, y);
redTotal += qRed(rgb);
greenTotal += qGreen(rgb);
blueTotal += qBlue(rgb);
int alpha = qAlpha(rgb);
alphaTotal += alpha;
if (alpha == EIGHT_BIT_MAXIMUM) {
opaquePixels++;
} else if (alpha != 0) {
translucentPixels++;
}
}
}
if (opaquePixels == imageArea) {
qCDebug(gpunetwork) << "Image with alpha channel is completely opaque:" << _url;
image = image.convertToFormat(QImage::Format_RGB888);
}
averageColor = QColor(redTotal / imageArea,
greenTotal / imageArea, blueTotal / imageArea, alphaTotal / imageArea);
isTransparent = (translucentPixels >= imageArea / 2);
}
gpu::Texture* theTexture = nullptr;
if ((image.width() > 0) && (image.height() > 0)) {
// bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
bool isLinearRGB = !(_type == CUBE_TEXTURE); //(_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 (image.hasAlphaChannel()) {
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
}
if (_type == CUBE_TEXTURE) {
const CubeLayout CUBEMAP_LAYOUTS[] = {
// Here is the expected layout for the faces in an image with the 1/6 aspect ratio:
//
// WIDTH
// <------>
// ^ +------+
// | | |
// | | +X |
// | | |
// H +------+
// E | |
// I | -X |
// G | |
// H +------+
// T | |
// | | +Y |
// | | |
// | +------+
// | | |
// | | -Y |
// | | |
// H +------+
// E | |
// I | +Z |
// G | |
// H +------+
// T | |
// | | -Z |
// | | |
// V +------+
//
// FaceWidth = width = height / 6
{ 1, 6,
{0, 0, true, false},
{0, 1, true, false},
{0, 2, false, true},
{0, 3, false, true},
{0, 4, true, false},
{0, 5, true, false}
},
// Here is the expected layout for the faces in an image with the 3/4 aspect ratio:
//
// <-----------WIDTH----------->
// ^ +------+------+------+------+
// | | | | | |
// | | | +Y | | |
// | | | | | |
// H +------+------+------+------+
// E | | | | |
// I | -X | -Z | +X | +Z |
// G | | | | |
// H +------+------+------+------+
// T | | | | |
// | | | -Y | | |
// | | | | | |
// V +------+------+------+------+
//
// FaceWidth = width / 4 = height / 3
{ 4, 3,
{2, 1, true, false},
{0, 1, true, false},
{1, 0, false, true},
{1, 2, false, true},
{3, 1, true, false},
{1, 1, true, false}
},
// Here is the expected layout for the faces in an image with the 4/3 aspect ratio:
//
// <-------WIDTH-------->
// ^ +------+------+------+
// | | | | |
// | | | +Y | |
// | | | | |
// H +------+------+------+
// E | | | |
// I | -X | -Z | +X |
// G | | | |
// H +------+------+------+
// T | | | |
// | | | -Y | |
// | | | | |
// | +------+------+------+
// | | | | |
// | | | +Z! | | <+Z is upside down!
// | | | | |
// V +------+------+------+
//
// FaceWidth = width / 3 = height / 4
{ 3, 4,
{2, 1, true, false},
{0, 1, true, false},
{1, 0, false, true},
{1, 2, false, true},
{1, 3, false, true},
{1, 1, true, false}
}
};
const int NUM_CUBEMAP_LAYOUTS = sizeof(CUBEMAP_LAYOUTS) / sizeof(CubeLayout);
// Find the layout of the cubemap in the 2D image
int foundLayout = -1;
for (int i = 0; i < NUM_CUBEMAP_LAYOUTS; i++) {
if ((image.height() * CUBEMAP_LAYOUTS[i]._widthRatio) == (image.width() * CUBEMAP_LAYOUTS[i]._heightRatio)) {
foundLayout = i;
break;
}
}
std::vector<QImage> faces;
// If found, go extract the faces as separate images
if (foundLayout >= 0) {
auto& layout = CUBEMAP_LAYOUTS[foundLayout];
int faceWidth = image.width() / layout._widthRatio;
faces.push_back(image.copy(QRect(layout._faceXPos._x * faceWidth, layout._faceXPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXPos._horizontalMirror, layout._faceXPos._verticalMirror));
faces.push_back(image.copy(QRect(layout._faceXNeg._x * faceWidth, layout._faceXNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXNeg._horizontalMirror, layout._faceXNeg._verticalMirror));
faces.push_back(image.copy(QRect(layout._faceYPos._x * faceWidth, layout._faceYPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYPos._horizontalMirror, layout._faceYPos._verticalMirror));
faces.push_back(image.copy(QRect(layout._faceYNeg._x * faceWidth, layout._faceYNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYNeg._horizontalMirror, layout._faceYNeg._verticalMirror));
faces.push_back(image.copy(QRect(layout._faceZPos._x * faceWidth, layout._faceZPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZPos._horizontalMirror, layout._faceZPos._verticalMirror));
faces.push_back(image.copy(QRect(layout._faceZNeg._x * faceWidth, layout._faceZNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZNeg._horizontalMirror, layout._faceZNeg._verticalMirror));
} else {
qCDebug(gpunetwork) << "Failed to find a known cube map layout from this image:" << _url;
return;
}
// If the 6 faces have been created go on and define the true Texture
if (faces.size() == gpu::Texture::NUM_FACES_PER_TYPE[gpu::Texture::TEX_CUBE]) {
theTexture = gpu::Texture::createCube(formatGPU, faces[0].width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP));
theTexture->autoGenerateMips(-1);
int f = 0;
for (auto& face : faces) {
theTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f);
f++;
}
// GEnerate irradiance while we are at it
theTexture->generateIrradiance();
}
} else {
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
theTexture->autoGenerateMips(-1);
}
}
*/
QMetaObject::invokeMethod(texture.data(), "setImage",
Q_ARG(const QImage&, image),
Q_ARG(void*, theTexture),
// Q_ARG(bool, isTransparent),
// Q_ARG(const QColor&, averageColor),
Q_ARG(int, originalWidth), Q_ARG(int, originalHeight));
}
void NetworkTexture::setImage(const QImage& image, void* voidTexture,/* bool translucent, const QColor& averageColor, */ int originalWidth,
void NetworkTexture::setImage(const QImage& image, void* voidTexture, int originalWidth,
int originalHeight) {
// _translucent = translucent;
// _averageColor = averageColor;
_originalWidth = originalWidth;
_originalHeight = originalHeight;
gpu::Texture* texture = static_cast<gpu::Texture*>(voidTexture);
// Passing ownership
// _gpuTexture.reset(texture);
_textureStorage->resetTexture(texture);
auto gpuTexture = _textureStorage->getGPUTexture();
_textureSource->resetTexture(texture);
auto gpuTexture = _textureSource->getGPUTexture();
if (gpuTexture) {
_width = gpuTexture->getWidth();

View file

@ -29,7 +29,7 @@ class NetworkTexture;
typedef QSharedPointer<NetworkTexture> NetworkTexturePointer;
enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE, CUBE_TEXTURE };
enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, CUBE_TEXTURE, CUSTOM_TEXTURE };
/// Stores cached textures, including render-to-texture targets.
class TextureCache : public ResourceCache, public Dependency {
@ -97,9 +97,8 @@ public:
Texture();
~Texture();
//const gpu::TexturePointer& getGPUTexture() const { return _gpuTexture; }
const gpu::TexturePointer getGPUTexture() const { return _textureStorage->getGPUTexture(); }
model::TextureStoragePointer _textureStorage;
const gpu::TexturePointer getGPUTexture() const { return _textureSource->getGPUTexture(); }
model::TextureSourcePointer _textureSource;
protected:
@ -118,18 +117,10 @@ public:
NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content);
NetworkTexture(const QUrl& url, const TextureLoaderFunc& textureLoader, const QByteArray& content);
/// Checks whether it "looks like" this texture is translucent
/// (majority of pixels neither fully opaque or fully transparent).
// bool isTranslucent() const { return _translucent; }
/// Returns the lazily-computed average texture color.
// const QColor& getAverageColor() const { return _averageColor; }
int getOriginalWidth() const { return _originalWidth; }
int getOriginalHeight() const { return _originalHeight; }
int getWidth() const { return _width; }
int getHeight() const { return _height; }
// TextureType getType() const { return _type; }
TextureLoaderFunc getTextureLoader() const;
@ -139,8 +130,7 @@ protected:
Q_INVOKABLE void loadContent(const QByteArray& content);
// FIXME: This void* should be a gpu::Texture* but i cannot get it to work for now, moving on...
Q_INVOKABLE void setImage(const QImage& image, void* texture, /*bool translucent, const QColor& averageColor, */int originalWidth,
int originalHeight);
Q_INVOKABLE void setImage(const QImage& image, void* texture, int originalWidth, int originalHeight);
virtual void imageLoaded(const QImage& image);
@ -148,8 +138,6 @@ protected:
private:
TextureLoaderFunc _textureLoader;
bool _translucent;
QColor _averageColor;
int _originalWidth;
int _originalHeight;
int _width;

View file

@ -19,25 +19,25 @@
using namespace model;
using namespace gpu;
// TextureStorage
TextureStorage::TextureStorage()
// TextureSource
TextureSource::TextureSource()
{/* : Texture::Storage()//,
// _gpuTexture(Texture::createFromStorage(this))*/
}
TextureStorage::~TextureStorage() {
TextureSource::~TextureSource() {
}
void TextureStorage::reset(const QUrl& url, const TextureUsage& usage) {
void TextureSource::reset(const QUrl& url, const TextureUsage& usage) {
_imageUrl = url;
_usage = usage;
}
void TextureStorage::resetTexture(gpu::Texture* texture) {
void TextureSource::resetTexture(gpu::Texture* texture) {
_gpuTexture.reset(texture);
}
bool TextureStorage::isDefined() const {
bool TextureSource::isDefined() const {
if (_gpuTexture) {
return _gpuTexture->isDefined();
} else {
@ -46,21 +46,21 @@ bool TextureStorage::isDefined() const {
}
void TextureMap::setTextureStorage(TextureStoragePointer& texStorage) {
_textureStorage = texStorage;
void TextureMap::setTextureSource(TextureSourcePointer& texStorage) {
_textureSource = texStorage;
}
bool TextureMap::isDefined() const {
if (_textureStorage) {
return _textureStorage->isDefined();
if (_textureSource) {
return _textureSource->isDefined();
} else {
return false;
}
}
gpu::TextureView TextureMap::getTextureView() const {
if (_textureStorage) {
return gpu::TextureView(_textureStorage->getGPUTexture(), 0);
if (_textureSource) {
return gpu::TextureView(_textureSource->getGPUTexture(), 0);
} else {
return gpu::TextureView();
}
@ -78,7 +78,7 @@ void TextureMap::setLightmapOffsetScale(float offset, float scale) {
gpu::Texture* TextureStorage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
gpu::Texture* TextureSource::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
QImage image = srcImage;
int imageArea = image.width() * image.height();
@ -145,7 +145,7 @@ gpu::Texture* TextureStorage::create2DTextureFromImage(const QImage& srcImage, c
if ((image.width() > 0) && (image.height() > 0)) {
// bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
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));
@ -163,6 +163,94 @@ gpu::Texture* TextureStorage::create2DTextureFromImage(const QImage& srcImage, c
return theTexture;
}
int clampPixelCoordinate(int coordinate, int maxCoordinate) {
return coordinate - ((int)(coordinate < 0) * coordinate) + ((int)(coordinate > maxCoordinate) * (maxCoordinate - coordinate));
}
const int RGBA_MAX = 255;
// transform -1 - 1 to 0 - 255 (from sobel value to rgb)
double mapComponent(double sobelValue) {
const double factor = RGBA_MAX / 2.0;
return (sobelValue + 1.0) * factor;
}
gpu::Texture* TextureSource::createNormalTextureFromBumpImage(const QImage& srcImage, const std::string& srcImageName) {
QImage image = srcImage;
// PR 5540 by AlessandroSigna
// integrated here as a specialized TextureLoader for bumpmaps
// The conversion is done using the Sobel Filter to calculate the derivatives from the grayscale image
const double pStrength = 2.0;
int width = image.width();
int height = image.height();
QImage result(width, height, image.format());
for (int i = 0; i < width; i++) {
const int iNextClamped = clampPixelCoordinate(i + 1, width - 1);
const int iPrevClamped = clampPixelCoordinate(i - 1, width - 1);
for (int j = 0; j < height; j++) {
const int jNextClamped = clampPixelCoordinate(j + 1, height - 1);
const int jPrevClamped = clampPixelCoordinate(j - 1, height - 1);
// surrounding pixels
const QRgb topLeft = image.pixel(iPrevClamped, jPrevClamped);
const QRgb top = image.pixel(iPrevClamped, j);
const QRgb topRight = image.pixel(iPrevClamped, jNextClamped);
const QRgb right = image.pixel(i, jNextClamped);
const QRgb bottomRight = image.pixel(iNextClamped, jNextClamped);
const QRgb bottom = image.pixel(iNextClamped, j);
const QRgb bottomLeft = image.pixel(iNextClamped, jPrevClamped);
const QRgb left = image.pixel(i, jPrevClamped);
// take their gray intensities
// since it's a grayscale image, the value of each component RGB is the same
const double tl = qRed(topLeft);
const double t = qRed(top);
const double tr = qRed(topRight);
const double r = qRed(right);
const double br = qRed(bottomRight);
const double b = qRed(bottom);
const double bl = qRed(bottomLeft);
const double l = qRed(left);
// apply the sobel filter
const double dX = (tr + pStrength * r + br) - (tl + pStrength * l + bl);
const double dY = (bl + pStrength * b + br) - (tl + pStrength * t + tr);
const double dZ = RGBA_MAX / pStrength;
glm::vec3 v(dX, dY, dZ);
glm::normalize(v);
// convert to rgb from the value obtained computing the filter
QRgb qRgbValue = qRgb(mapComponent(v.x), mapComponent(v.y), mapComponent(v.z));
result.setPixel(i, j, qRgbValue);
}
}
gpu::Texture* theTexture = nullptr;
if ((image.width() > 0) && (image.height() > 0)) {
// bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
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 (image.hasAlphaChannel()) {
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
}
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
theTexture->autoGenerateMips(-1);
}
return theTexture;
}
class CubeLayout {
public:
int _widthRatio = 1;
@ -197,7 +285,7 @@ public:
_faceZNeg(fZN) {}
};
gpu::Texture* TextureStorage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
gpu::Texture* TextureSource::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
QImage image = srcImage;
int imageArea = image.width() * image.height();

View file

@ -32,13 +32,13 @@ public:
int _environmentUsage = 0;
};
// TextureStorage is a specialized version of the gpu::Texture::Storage
// TextureSource 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 {
class TextureSource {
public:
TextureStorage();
~TextureStorage();
TextureSource();
~TextureSource();
const QUrl& getUrl() const { return _imageUrl; }
gpu::Texture::Type getType() const { return _usage._type; }
@ -51,6 +51,7 @@ public:
bool isDefined() const;
static gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName);
protected:
@ -58,7 +59,7 @@ protected:
TextureUsage _usage;
QUrl _imageUrl;
};
typedef std::shared_ptr< TextureStorage > TextureStoragePointer;
typedef std::shared_ptr< TextureSource > TextureSourcePointer;
@ -66,7 +67,7 @@ class TextureMap {
public:
TextureMap() {}
void setTextureStorage(TextureStoragePointer& texStorage);
void setTextureSource(TextureSourcePointer& texStorage);
bool isDefined() const;
gpu::TextureView getTextureView() const;
@ -78,7 +79,7 @@ public:
const glm::vec2& getLightmapOffsetScale() const { return _lightmapOffsetScale; }
protected:
TextureStoragePointer _textureStorage;
TextureSourcePointer _textureSource;
Transform _texcoordTransform;
glm::vec2 _lightmapOffsetScale{ 0.0f, 1.0f };
@ -87,5 +88,5 @@ typedef std::shared_ptr< TextureMap > TextureMapPointer;
};
#endif // hifi_model_TextureStorage_h
#endif // hifi_model_TextureMap_h

View file

@ -2072,17 +2072,17 @@ static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const
networkMaterial->diffuseTextureName = material.diffuseTexture.name;
auto diffuseMap = model::TextureMapPointer(new model::TextureMap());
diffuseMap->setTextureStorage(networkMaterial->diffuseTexture->_textureStorage);
diffuseMap->setTextureSource(networkMaterial->diffuseTexture->_textureSource);
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, material.normalTexture.content);
networkMaterial->normalTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.normalTexture.filename)), (material.normalTexture.isBumpmap ? BUMP_TEXTURE : NORMAL_TEXTURE), material.normalTexture.content);
networkMaterial->normalTextureName = material.normalTexture.name;
auto normalMap = model::TextureMapPointer(new model::TextureMap());
normalMap->setTextureStorage(networkMaterial->normalTexture->_textureStorage);
normalMap->setTextureSource(networkMaterial->normalTexture->_textureSource);
material._material->setTextureMap(model::MaterialKey::NORMAL_MAP, normalMap);
}
@ -2091,7 +2091,7 @@ static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const
networkMaterial->specularTextureName = material.specularTexture.name;
auto glossMap = model::TextureMapPointer(new model::TextureMap());
glossMap->setTextureStorage(networkMaterial->specularTexture->_textureStorage);
glossMap->setTextureSource(networkMaterial->specularTexture->_textureSource);
material._material->setTextureMap(model::MaterialKey::GLOSS_MAP, glossMap);
}
@ -2102,7 +2102,7 @@ static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const
checkForTexcoordLightmap = true;
auto lightmapMap = model::TextureMapPointer(new model::TextureMap());
lightmapMap->setTextureStorage(networkMaterial->emissiveTexture->_textureStorage);
lightmapMap->setTextureSource(networkMaterial->emissiveTexture->_textureSource);
lightmapMap->setTextureTransform(material.emissiveTexture.transform);
lightmapMap->setLightmapOffsetScale(material.emissiveParams.x, material.emissiveParams.y);