GOing home, this is in the middle of adding the Roughness texture and potentially cleaning up the different compinations of shaders regarding the material textures

This commit is contained in:
samcake 2016-02-22 18:19:36 -08:00
parent 377ee5a486
commit 00782b0e76
19 changed files with 155 additions and 38 deletions

View file

@ -11,7 +11,7 @@
using namespace gpu;
const Element Element::COLOR_RGBA_32{ VEC4, NUINT8, RGBA };
const Element Element::COLOR_RGBA{ VEC4, FLOAT, RGBA };
const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA };
const Element Element::VEC2F_UV{ VEC2, FLOAT, UV };
const Element Element::VEC2F_XY{ VEC2, FLOAT, XY };
const Element Element::VEC3F_XYZ{ VEC3, FLOAT, XYZ };

View file

@ -247,7 +247,7 @@ public:
}
static const Element COLOR_RGBA_32;
static const Element COLOR_RGBA;
static const Element VEC4F_COLOR_RGBA;
static const Element VEC2F_UV;
static const Element VEC2F_XY;
static const Element VEC3F_XYZ;

View file

@ -14,6 +14,7 @@
#include "Resource.h"
#include <algorithm> //min max and more
#include <bitset>
#include <QUrl>
@ -139,6 +140,53 @@ protected:
class Texture : public Resource {
public:
class Usage {
public:
enum FlagBit {
COLOR = 0, // Texture is a color map
NORMAL, // Texture is a normal map
ALPHA, // Texture has an alpha channel
ALPHA_MASK, // Texture alpha channel is a Mask 0/1
NUM_FLAGS,
};
typedef std::bitset<NUM_FLAGS> Flags;
// The key is the Flags
Flags _flags;
Usage() : _flags(0) {}
Usage(const Flags& flags) : _flags(flags) {}
bool operator== (const Usage& rhs) const { return _flags == rhs._flags; }
bool operator!= (const Usage& rhs) const { return _flags != rhs._flags; }
class Builder {
friend class Usage;
Flags _flags{ 0 };
public:
Builder() {}
Usage build() const { return Usage(_flags); }
Builder& withColor() { _flags.set(COLOR); return (*this); }
Builder& withNormal() { _flags.set(NORMAL); return (*this); }
Builder& withAlpha() { _flags.set(ALPHA); return (*this); }
Builder& withAlphaMask() { _flags.set(ALPHA_MASK); return (*this); }
};
Usage(const Builder& builder) : Usage(builder._flags) {}
bool isColor() const { return _flags[COLOR]; }
bool isNormal() const { return _flags[NORMAL]; }
bool isAlpha() const { return _flags[ALPHA]; }
bool isAlphaMask() const { return _flags[ALPHA_MASK]; }
bool operator==(const Usage& usage) { return (_flags == usage._flags); }
bool operator!=(const Usage& usage) { return (_flags != usage._flags); }
};
class Pixels {
public:
Pixels() {}
@ -343,6 +391,10 @@ public:
bool isDefined() const { return _defined; }
// Usage is a a set of flags providing Semantic about the usage of the Texture.
void setUsage(const Usage& usage) { _usage = usage; }
Usage getUsage() const { return _usage; }
// For Cube Texture, it's possible to generate the irradiance spherical harmonics and make them availalbe with the texture
bool generateIrradiance();
const SHPointer& getIrradiance(uint16 slice = 0) const { return _irradiance; }
@ -380,6 +432,8 @@ protected:
Type _type = TEX_1D;
Usage _usage;
SHPointer _irradiance;
bool _autoGenerateMips = false;
bool _isIrradianceValid = false;

View file

@ -316,7 +316,7 @@ static NetworkMesh* buildNetworkMesh(const FBXMesh& mesh, const QUrl& textureBas
return networkMesh;
}
static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl) {
static NetworkMaterial* buildNetworkMaterial(NetworkGeometry* geometry, const FBXMaterial& material, const QUrl& textureBaseUrl) {
auto textureCache = DependencyManager::get<TextureCache>();
NetworkMaterial* networkMaterial = new NetworkMaterial();
@ -324,6 +324,9 @@ static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const
if (!material.albedoTexture.filename.isEmpty()) {
networkMaterial->albedoTexture = textureCache->getTexture(textureBaseUrl.resolved(QUrl(material.albedoTexture.filename)), DEFAULT_TEXTURE, material.albedoTexture.content);
QObject::connect(networkMaterial->albedoTexture.data(), &NetworkTexture::networkTextureCreated,
geometry, &NetworkGeometry::textureLoaded);
networkMaterial->albedoTextureName = material.albedoTexture.name;
auto albedoMap = model::TextureMapPointer(new model::TextureMap());
@ -407,7 +410,7 @@ void NetworkGeometry::modelParseSuccess(FBXGeometry* geometry) {
QHash<QString, size_t> fbxMatIDToMatID;
foreach(const FBXMaterial& material, _geometry->materials) {
fbxMatIDToMatID[material.materialID] = _materials.size();
_materials.emplace_back(buildNetworkMaterial(material, _textureBaseUrl));
_materials.emplace_back(buildNetworkMaterial(this, material, _textureBaseUrl));
}
@ -453,3 +456,6 @@ const NetworkMaterial* NetworkGeometry::getShapeMaterial(int shapeID) {
}
}
void NetworkGeometry::textureLoaded(const QWeakPointer<NetworkTexture>& networkTexture) {
numTextureLoaded++;
}

View file

@ -105,6 +105,9 @@ signals:
// Fired when something went wrong.
void onFailure(NetworkGeometry& networkGeometry, Error error);
public slots:
void textureLoaded(const QWeakPointer<NetworkTexture>& networkTexture);
protected slots:
void mappingRequestDone(const QByteArray& data);
void mappingRequestError(QNetworkReply::NetworkError error);
@ -115,6 +118,7 @@ protected slots:
void modelParseSuccess(FBXGeometry* geometry);
void modelParseError(int error, QString str);
protected:
void attemptRequestInternal();
void requestMapping(const QUrl& url);
@ -133,6 +137,7 @@ protected:
QUrl _modelUrl;
QVariantHash _mapping;
QUrl _textureBaseUrl;
int numTextureLoaded = 0;
Resource* _resource = nullptr;
std::unique_ptr<FBXGeometry> _geometry; // This should go away evenutally once we can put everything we need in the model::AssetPointer
@ -173,6 +178,7 @@ public:
class NetworkMaterial {
public:
model::MaterialPointer _material;
QString albedoTextureName;
QSharedPointer<NetworkTexture> albedoTexture;
@ -186,6 +192,7 @@ public:
QSharedPointer<NetworkTexture> emissiveTexture;
QString lightmapTextureName;
QSharedPointer<NetworkTexture> lightmapTexture;
};

View file

@ -339,10 +339,6 @@ void NetworkTexture::setImage(const QImage& image, void* voidTexture, int origin
finishedLoading(true);
imageLoaded(image);
}
void NetworkTexture::imageLoaded(const QImage& image) {
// nothing by default
emit networkTextureCreated(qWeakPointerCast<NetworkTexture, Resource> (_self));
}

View file

@ -83,8 +83,6 @@ private:
gpu::TexturePointer _blueTexture;
gpu::TexturePointer _blackTexture;
gpu::TexturePointer _normalFittingTexture;
QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures;
};
/// A simple object wrapper for an OpenGL texture.
@ -114,7 +112,11 @@ public:
int getHeight() const { return _height; }
TextureLoaderFunc getTextureLoader() const;
signals:
void networkTextureCreated(const QWeakPointer<NetworkTexture>& self);
protected:
virtual void downloadFinished(const QByteArray& data) override;
@ -123,8 +125,6 @@ protected:
// 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, int originalWidth, int originalHeight);
virtual void imageLoaded(const QImage& image);
private:
TextureType _type;

View file

@ -46,11 +46,13 @@ Material::~Material() {
void Material::setEmissive(const Color& emissive, bool isSRGB) {
_key.setEmissive(glm::any(glm::greaterThan(emissive, Color(0.0f))));
_schemaBuffer.edit<Schema>()._key = (uint32) _key._flags.to_ulong();
_schemaBuffer.edit<Schema>()._emissive = (isSRGB ? ColorUtils::toLinearVec3(emissive) : emissive);
}
void Material::setOpacity(float opacity) {
_key.setTransparent((opacity < 1.0f));
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
_schemaBuffer.edit<Schema>()._opacity = opacity;
}
@ -62,6 +64,7 @@ void Material::setAlbedo(const Color& albedo, bool isSRGB) {
void Material::setRoughness(float roughness) {
roughness = std::min(1.0f, std::max(roughness, 0.0f));
_key.setGlossy((roughness < 1.0f));
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
_schemaBuffer.edit<Schema>()._roughness = roughness;
}
@ -72,6 +75,7 @@ void Material::setFresnel(const Color& fresnel, bool isSRGB) {
void Material::setMetallic(float metallic) {
_key.setMetallic(metallic > 0.0f);
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
_schemaBuffer.edit<Schema>()._metallic = metallic;
}
@ -79,9 +83,11 @@ void Material::setMetallic(float metallic) {
void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) {
if (textureMap) {
_key.setMapChannel(channel, (true));
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
_textureMaps[channel] = textureMap;
} else {
_key.setMapChannel(channel, (false));
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
_textureMaps.erase(channel);
}
}

View file

@ -252,7 +252,9 @@ public:
float _metallic{ 0.0f }; // Not Metallic
glm::vec4 _spare0{ 0.0f };
glm::vec3 _spare0{ 0.0f };
uint32_t _key{ 0 }; // a copy of the materialKey
// for alignment beauty, Material size == Mat4x4

View file

@ -37,4 +37,5 @@ float getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }
float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }
<@endif@>

View file

@ -54,22 +54,38 @@ void TextureMap::setLightmapOffsetScale(float offset, float scale) {
gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
QImage image = srcImage;
bool validAlpha = false;
bool alphaAsMask = true;
const uint8 OPAQUE_ALPHA = 255;
const uint8 TRANSLUCENT_ALPHA = 0;
if (image.hasAlphaChannel()) {
std::map<uint8, uint32> alphaHistogram;
if (image.format() != QImage::Format_ARGB32) {
image = image.convertToFormat(QImage::Format_ARGB32);
}
// Actual alpha channel?
// Actual alpha channel? create the histogram
for (int y = 0; y < image.height(); ++y) {
const QRgb* data = reinterpret_cast<const QRgb*>(image.constScanLine(y));
for (int x = 0; x < image.width(); ++x) {
auto alpha = qAlpha(data[x]);
if (alpha != 255) {
alphaHistogram[alpha] ++;
if (alpha != OPAQUE_ALPHA) {
validAlpha = true;
break;
}
}
}
// If alpha was meaningfull refine
if (validAlpha && (alphaHistogram.size() > 1)) {
auto totalNumPixels = image.height() * image.width();
auto numOpaques = alphaHistogram[OPAQUE_ALPHA];
auto numTranslucents = alphaHistogram[TRANSLUCENT_ALPHA];
auto numTransparents = totalNumPixels - numOpaques - numTranslucents;
alphaAsMask = ((numTransparents / (double)totalNumPixels) < 0.05);
}
}
if (!validAlpha && image.format() != QImage::Format_RGB888) {
@ -89,10 +105,21 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con
}
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
auto usage = gpu::Texture::Usage::Builder().withColor();
if (validAlpha) {
usage.withAlpha();
if (alphaAsMask) {
usage.withAlphaMask();
}
}
theTexture->setUsage(usage.build());
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
theTexture->autoGenerateMips(-1);
// FIXME queue for transfer to GPU and block on completion
}
return theTexture;

View file

@ -15,8 +15,8 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D albedoMap;
uniform sampler2D roughnessMap;
in vec4 _position;
in vec3 _normal;
@ -25,8 +25,9 @@ in vec2 _texCoord0;
void main(void) {
// Fetch albedo map
// Fetch maps
vec4 albedo = texture(albedoMap, _texCoord0);
float roughness = texture(roughnessMap, _texCoord0);
Material mat = getMaterial();
@ -34,7 +35,7 @@ void main(void) {
normalize(_normal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat),
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat),
getMaterialFresnel(mat));
}

View file

@ -18,6 +18,7 @@
// the albedo texture
uniform sampler2D albedoMap;
uniform sampler2D roughnessMap;
// the emissive map texture and parameters
uniform sampler2D emissiveMap;
@ -30,7 +31,9 @@ in vec3 _normal;
in vec3 _color;
void main(void) {
// Fetch maps
vec4 albedo = texture(albedoMap, _texCoord0);
float roughness = texture(roughnessMap, _texCoord0);
vec4 emissive = texture(emissiveMap, _texCoord1);
Material mat = getMaterial();
@ -39,7 +42,7 @@ void main(void) {
normalize(_normal),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat),
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat),
getMaterialFresnel(mat),
(vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb));

View file

@ -18,6 +18,7 @@
// the albedo texture
uniform sampler2D albedoMap;
uniform sampler2D roughnessMap;
// the normal map texture
uniform sampler2D normalMap;
@ -34,17 +35,19 @@ in vec3 _tangent;
in vec3 _color;
void main(void) {
// Fetch maps
vec4 albedo = texture(albedoMap, _texCoord0);
float roughness = texture(roughness, _texCoord0);
vec4 emissive = texture(emissiveMap, _texCoord1);
vec3 localNormal = vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5);
// compute the view normal from the various bits
vec3 normalizedNormal = normalize(_normal);
vec3 normalizedTangent = normalize(_tangent);
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
vec3 localNormal = vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5);
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
// set the diffuse, normal, specular data
vec4 albedo = texture(albedoMap, _texCoord0);
vec4 emissive = texture(emissiveMap, _texCoord1);
Material mat = getMaterial();

View file

@ -18,6 +18,7 @@
// the albedo texture
uniform sampler2D albedoMap;
uniform sampler2D roughnessMap;
// the emissive map texture and parameters
uniform sampler2D emissiveMap;
@ -37,18 +38,19 @@ in vec3 _tangent;
in vec3 _color;
void main(void) {
// Fetch maps
vec4 albedo = texture(albedoMap, _texCoord0);
float roughness = texture(roughnessMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
vec4 emissive = texture(emissiveMap, _texCoord1);
vec3 localNormal = vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5);
// compute the view normal from the various bits
vec3 normalizedNormal = normalize(_normal);
vec3 normalizedTangent = normalize(_tangent);
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
vec3 localNormal = vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5);
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
// set the albedo, normal, specular data
vec4 albedo = texture(albedoMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
vec4 emissive = texture(emissiveMap, _texCoord1);
Material mat = getMaterial();
@ -56,7 +58,7 @@ void main(void) {
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat),
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat),
specular, // no use of getMaterialFresnel(mat)
(vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb));

View file

@ -18,6 +18,7 @@
// the albedo texture
uniform sampler2D albedoMap;
uniform sampler2D roughnessMap;
// the emissive map texture and parameters
uniform sampler2D emissiveMap;
@ -33,8 +34,9 @@ in vec3 _normal;
in vec3 _color;
void main(void) {
// set the albedo, normal, specular data
// Fetch maps
vec4 albedo = texture(albedoMap, _texCoord0);
float roughness = texture(roughnessMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
vec4 emissive = texture(emissiveMap, _texCoord1);
@ -44,7 +46,7 @@ void main(void) {
normalize(_normal),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat),
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat),
specular, // no use of getMaterialFresnel(mat)
(vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb));

View file

@ -15,9 +15,11 @@
<@include DeferredBufferWrite.slh@>
<@include model/Material.slh@>
<@include model/MaterialTextures.slh@>
// the albedo texture
uniform sampler2D albedoMap;
uniform sampler2D roughnessMap;
// the normal map texture
uniform sampler2D normalMap;
@ -38,6 +40,7 @@ void main(void) {
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
vec4 albedo = texture(albedoMap, _texCoord0.st);
float roughness = texture(roughnessMap, _texCoord0);
Material mat = getMaterial();
@ -45,7 +48,7 @@ void main(void) {
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat),
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat),
getMaterialFresnel(mat));
}

View file

@ -18,6 +18,7 @@
// the albedo texture
uniform sampler2D albedoMap;
uniform sampler2D roughnessMap;
// the normal map texture
uniform sampler2D normalMap;
@ -42,6 +43,7 @@ void main(void) {
// set the albedo, normal, specular data
vec4 albedo = texture(albedoMap, _texCoord0);
vec4 roughness = texture(roughnessMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
Material mat = getMaterial();
@ -50,7 +52,7 @@ void main(void) {
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat),
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat),
specular //getMaterialFresnel(mat)
);

View file

@ -18,6 +18,7 @@
// the albedo texture
uniform sampler2D albedoMap;
uniform sampler2D roughnessMap;
// the specular texture
uniform sampler2D specularMap;
@ -31,6 +32,7 @@ in vec3 _color;
void main(void) {
// set the albedo, normal, specular data
vec4 albedo = texture(albedoMap, _texCoord0);
float roughness = texture(roughnessMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
Material mat = getMaterial();
@ -39,7 +41,7 @@ void main(void) {
normalize(_normal),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat),
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat),
specular //getMaterialFresnel(mat)
);