Merge pull request #7191 from samcake/orange

Better Shading Model and support fr Stingray material
This commit is contained in:
Brad Hefta-Gaub 2016-03-01 18:24:09 -08:00
commit cfce5af8d4
84 changed files with 1556 additions and 662 deletions

View file

@ -0,0 +1,51 @@
//
// ddebugFramBuffer.js
// examples/utilities/tools/render
//
// Sam Gateau created on 2/18/2016.
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
var DDB = Render.RenderDeferredTask.DebugDeferredBuffer;
oldConfig = DDB.toJSON();
DDB.enabled = true;
// Set up the qml ui
var qml = Script.resolvePath('framebuffer.qml');
var window = new OverlayWindow({
title: 'Framebuffer Debug',
source: qml,
width: 400, height: 400,
});
window.setPosition(25, 50);
window.closed.connect(function() { Script.stop(); });
// Debug buffer sizing
var resizing = false;
Controller.mousePressEvent.connect(function (e) {
if (shouldStartResizing(e.x)) {
resizing = true;
}
});
Controller.mouseReleaseEvent.connect(function() { resizing = false; });
Controller.mouseMoveEvent.connect(function (e) { resizing && setDebugBufferSize(e.x); });
function shouldStartResizing(eventX) {
var x = Math.abs(eventX - Window.innerWidth * (1.0 + DDB.size.x) / 2.0);
var mode = DDB.mode;
return mode !== -1 && x < 20;
}
function setDebugBufferSize(x) {
x = (2.0 * (x / Window.innerWidth) - 1.0); // scale
x = Math.min(Math.max(-1, x), 1); // clamp
DDB.size = { x: x, y: -1, z: 1, w: 1 };
}
Script.scriptEnding.connect(function () { DDB.fromJSON(oldConfig); });

View file

@ -0,0 +1,52 @@
//
// main.qml
// examples/utilities/tools/render
//
// Created by Zach Pomerantz on 2/8/2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
Column {
spacing: 8
Column {
id: debug
property var config: Render.getConfig("DebugDeferredBuffer")
function setDebugMode(mode) {
debug.config.enabled = (mode != -1);
debug.config.mode = mode;
}
Label { text: qsTr("Debug Buffer") }
ExclusiveGroup { id: bufferGroup }
Repeater {
model: [
"Off",
"Depth",
"Albedo",
"Normal",
"Roughness",
"Metallic",
"Emissive",
"Occlusion",
"Lightmap",
"Lighting",
"Shadow",
"Pyramid Depth",
"Ambient Occlusion",
"Custom Shader"
]
RadioButton {
text: qsTr(modelData)
exclusiveGroup: bufferGroup
checked: index == 0
onCheckedChanged: if (checked) debug.setDebugMode(index - 1);
}
}
}
}

View file

@ -3816,7 +3816,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
// Setup the current Zone Entity lighting
{
auto stage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(stage->getSunLight(), stage->getSkybox()->getCubemap());
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(stage->getSunLight());
}
{

View file

@ -342,9 +342,9 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
void ModelPackager::listTextures() {
_textures.clear();
foreach (const FBXMaterial mat, _geometry->materials) {
if (!mat.diffuseTexture.filename.isEmpty() && mat.diffuseTexture.content.isEmpty() &&
!_textures.contains(mat.diffuseTexture.filename)) {
_textures << mat.diffuseTexture.filename;
if (!mat.albedoTexture.filename.isEmpty() && mat.albedoTexture.content.isEmpty() &&
!_textures.contains(mat.albedoTexture.filename)) {
_textures << mat.albedoTexture.filename;
}
if (!mat.normalTexture.filename.isEmpty() && mat.normalTexture.content.isEmpty() &&
!_textures.contains(mat.normalTexture.filename)) {

View file

@ -273,6 +273,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
if (_hasPreviousZone) {
sceneKeyLight->resetAmbientSphere();
sceneKeyLight->setAmbientMap(nullptr);
sceneKeyLight->setColor(_previousKeyLightColor);
sceneKeyLight->setIntensity(_previousKeyLightIntensity);
sceneKeyLight->setAmbientIntensity(_previousKeyLightAmbientIntensity);
@ -321,10 +322,11 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
_ambientTexture.clear();
} else {
_ambientTexture = textureCache->getTexture(zone->getKeyLightProperties().getAmbientURL(), CUBE_TEXTURE);
if (_ambientTexture->getGPUTexture()) {
if (_ambientTexture && _ambientTexture->isLoaded() && _ambientTexture->getGPUTexture()) {
_pendingAmbientTexture = false;
if (_ambientTexture->getGPUTexture()->getIrradiance()) {
sceneKeyLight->setAmbientSphere(_ambientTexture->getGPUTexture()->getIrradiance());
sceneKeyLight->setAmbientMap(_ambientTexture->getGPUTexture());
isAmbientTextureSet = true;
}
} else {
@ -354,12 +356,13 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
// Update the Texture of the Skybox with the one pointed by this zone
_skyboxTexture = textureCache->getTexture(zone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
if (_skyboxTexture->getGPUTexture()) {
if (_skyboxTexture && _skyboxTexture->isLoaded() && _skyboxTexture->getGPUTexture()) {
auto texture = _skyboxTexture->getGPUTexture();
skybox->setCubemap(texture);
_pendingSkyboxTexture = false;
if (!isAmbientTextureSet && texture->getIrradiance()) {
sceneKeyLight->setAmbientSphere(texture->getIrradiance());
sceneKeyLight->setAmbientMap(texture);
isAmbientTextureSet = true;
}
} else {
@ -381,6 +384,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
if (!isAmbientTextureSet) {
sceneKeyLight->resetAmbientSphere();
sceneKeyLight->setAmbientMap(nullptr);
}
}

View file

@ -15,7 +15,7 @@
<@include DeferredBufferWrite.slh@>
// the diffuse texture
// the albedo texture
uniform sampler2D originalTexture;
// the interpolated normal

View file

@ -28,9 +28,6 @@ void main(void) {
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
worldNormal = normalize(worldNormal);
vec3 specular = DEFAULT_SPECULAR;
float shininess = DEFAULT_SHININESS;
float inPositionX = (_worldPosition.x - 0.5) / voxelVolumeSize.x;
float inPositionY = (_worldPosition.y - 0.5) / voxelVolumeSize.y;
float inPositionZ = (_worldPosition.z - 0.5) / voxelVolumeSize.z;
@ -44,5 +41,5 @@ void main(void) {
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
packDeferredFragment(_normal, 1.0, vec3(diffuse), specular, shininess);
packDeferredFragment(_normal, 1.0, vec3(diffuse), DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_SPECULAR);
}

View file

@ -16,7 +16,7 @@
out vec4 _color;
void main(void) {
// pass along the diffuse color
// pass along the color
_color = colorToLinearRGBA(inColor);
TransformCamera cam = getTransformCamera();

View file

@ -865,6 +865,9 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
}
} else if (object.name == "Material") {
FBXMaterial material;
if (object.properties.at(1).toByteArray().contains("StingrayPBS")) {
material.isPBSMaterial = true;
}
foreach (const FBXNode& subobject, object.children) {
bool properties = false;
QByteArray propertyName;
@ -879,7 +882,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
propertyName = "P";
index = 4;
}
if (properties) {
if (!material.isPBSMaterial && properties) {
foreach (const FBXNode& property, subobject.children) {
if (property.name == propertyName) {
if (property.properties.at(0) == "DiffuseColor") {
@ -914,6 +917,44 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
#endif
}
}
} else if (material.isPBSMaterial && properties) {
std::vector<std::string> unknowns;
foreach(const FBXNode& property, subobject.children) {
if (property.name == propertyName) {
if (property.properties.at(0) == "Maya|use_normal_map") {
material.useNormalMap = (bool)property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|base_color") {
material.diffuseColor = getVec3(property.properties, index);
} else if (property.properties.at(0) == "Maya|use_color_map") {
material.useAlbedoMap = (bool) property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|roughness") {
material.roughness = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|use_roughness_map") {
material.useRoughnessMap = (bool)property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|metallic") {
material.metallic = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|use_metallic_map") {
material.useMetallicMap = (bool)property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|emissive") {
material.emissiveColor = getVec3(property.properties, index);
} else if (property.properties.at(0) == "Maya|emissive_intensity") {
material.emissiveIntensity = property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|use_emissive_map") {
material.useEmissiveMap = (bool)property.properties.at(index).value<double>();
} else if (property.properties.at(0) == "Maya|use_ao_map") {
material.useOcclusionMap = (bool)property.properties.at(index).value<double>();
} else {
const QString propname = property.properties.at(0).toString();
unknowns.push_back(propname.toStdString());
}
}
}
}
#if defined(DEBUG_FBXREADER)
else {
@ -1030,18 +1071,35 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
if (connection.properties.at(0) == "OP") {
int counter = 0;
QByteArray type = connection.properties.at(3).toByteArray().toLower();
if (type.contains("diffuse")) {
if ((type.contains("diffuse") && !type.contains("tex_global_diffuse"))) {
diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("tex_color_map")) {
diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} 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));
transparentTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} 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")) {
} else if (type.contains("tex_normal_map")) {
normalTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if ((type.contains("specular") && !type.contains("tex_global_specular")) || type.contains("reflection")) {
specularTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("tex_metallic_map")) {
metallicTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("shininess")) {
shininessTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("tex_roughness_map")) {
roughnessTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("emissive")) {
emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("tex_emissive_map")) {
emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("ambient")) {
ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("tex_ao_map")) {
occlusionTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type == "lcl rotation") {
localRotations.insert(getID(connection.properties, 2), getID(connection.properties, 1));
@ -1055,14 +1113,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
} else if (type == "d|z") {
zComponents.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (type.contains("shininess")) {
counter++;
} else if (_loadLightmaps && type.contains("emissive")) {
emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else if (_loadLightmaps && type.contains("ambient")) {
ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} else {
QString typenam = type.data();
counter++;

View file

@ -111,7 +111,7 @@ public:
QString texcoordSetName;
bool isBumpmap{ false };
bool isNull() const { return name.isEmpty() && filename.isEmpty() && content.isEmpty(); }
};
@ -130,11 +130,10 @@ class FBXMaterial {
public:
FBXMaterial() {};
FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor,
const glm::vec2& emissiveParams, float shininess, float opacity) :
float shininess, float opacity) :
diffuseColor(diffuseColor),
specularColor(specularColor),
emissiveColor(emissiveColor),
emissiveParams(emissiveParams),
shininess(shininess),
opacity(opacity) {}
@ -144,18 +143,39 @@ public:
float specularFactor = 1.0f;
glm::vec3 emissiveColor{ 0.0f };
glm::vec2 emissiveParams{ 0.0f, 1.0f };
float shininess = 23.0f;
float opacity = 1.0f;
float metallic{ 0.0f };
float roughness{ 1.0f };
float emissiveIntensity{ 1.0f };
QString materialID;
model::MaterialPointer _material;
FBXTexture diffuseTexture;
FBXTexture opacityTexture;
FBXTexture normalTexture;
FBXTexture albedoTexture;
FBXTexture opacityTexture;
FBXTexture glossTexture;
FBXTexture roughnessTexture;
FBXTexture specularTexture;
FBXTexture metallicTexture;
FBXTexture emissiveTexture;
FBXTexture occlusionTexture;
FBXTexture lightmapTexture;
glm::vec2 lightmapParams{ 0.0f, 1.0f };
bool isPBSMaterial{ false };
// THe use XXXMap are not really used to drive which map are going or not, debug only
bool useNormalMap{ false };
bool useAlbedoMap{ false };
bool useOpacityMap{ false };
bool useRoughnessMap{ false };
bool useSpecularMap{ false };
bool useMetallicMap{ false };
bool useEmissiveMap{ false };
bool useOcclusionMap{ false };
bool needTangentSpace() const;
};
@ -397,11 +417,16 @@ public:
QHash<QString, QString> diffuseTextures;
QHash<QString, QString> transparentTextures;
QHash<QString, QString> bumpTextures;
QHash<QString, QString> normalTextures;
QHash<QString, QString> specularTextures;
QHash<QString, QString> metallicTextures;
QHash<QString, QString> roughnessTextures;
QHash<QString, QString> shininessTextures;
QHash<QString, QString> emissiveTextures;
QHash<QString, QString> ambientTextures;
QHash<QString, QString> occlusionTextures;
QHash<QString, FBXMaterial> _fbxMaterials;

View file

@ -79,11 +79,20 @@ void FBXReader::consolidateFBXMaterials() {
}
}
material.diffuseTexture = diffuseTexture;
material.albedoTexture = diffuseTexture;
detectDifferentUVs = (diffuseTexture.texcoordSet != 0) || (!diffuseTexture.transform.isIdentity());
}
FBXTexture transparentTexture;
QString transparentTextureID = transparentTextures.value(material.materialID);
if (!transparentTextureID.isNull()) {
transparentTexture = getTexture(transparentTextureID);
material.opacityTexture = transparentTexture;
detectDifferentUVs |= (transparentTexture.texcoordSet != 0) || (!transparentTexture.transform.isIdentity());
}
FBXTexture normalTexture;
QString bumpTextureID = bumpTextures.value(material.materialID);
QString normalTextureID = normalTextures.value(material.materialID);
@ -100,37 +109,66 @@ void FBXReader::consolidateFBXMaterials() {
material.normalTexture = normalTexture;
detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity());
}
FBXTexture specularTexture;
QString specularTextureID = specularTextures.value(material.materialID);
if (!specularTextureID.isNull()) {
specularTexture = getTexture(specularTextureID);
detectDifferentUVs |= (specularTexture.texcoordSet != 0) || (!specularTexture.transform.isIdentity());
material.specularTexture = specularTexture;
}
FBXTexture metallicTexture;
QString metallicTextureID = metallicTextures.value(material.materialID);
if (!metallicTextureID.isNull()) {
metallicTexture = getTexture(metallicTextureID);
detectDifferentUVs |= (metallicTexture.texcoordSet != 0) || (!metallicTexture.transform.isIdentity());
material.metallicTexture = metallicTexture;
}
FBXTexture roughnessTexture;
QString roughnessTextureID = roughnessTextures.value(material.materialID);
if (!roughnessTextureID.isNull()) {
roughnessTexture = getTexture(roughnessTextureID);
material.roughnessTexture = roughnessTexture;
detectDifferentUVs |= (roughnessTexture.texcoordSet != 0) || (!roughnessTexture.transform.isIdentity());
}
FBXTexture shininessTexture;
QString shininessTextureID = shininessTextures.value(material.materialID);
if (!shininessTextureID.isNull()) {
shininessTexture = getTexture(shininessTextureID);
material.glossTexture = shininessTexture;
detectDifferentUVs |= (shininessTexture.texcoordSet != 0) || (!shininessTexture.transform.isIdentity());
}
FBXTexture emissiveTexture;
glm::vec2 emissiveParams(0.f, 1.f);
emissiveParams.x = _lightmapOffset;
emissiveParams.y = _lightmapLevel;
QString emissiveTextureID = emissiveTextures.value(material.materialID);
QString ambientTextureID = ambientTextures.value(material.materialID);
if (_loadLightmaps && (!emissiveTextureID.isNull() || !ambientTextureID.isNull())) {
if (!emissiveTextureID.isNull()) {
emissiveTexture = getTexture(emissiveTextureID);
emissiveParams.y = 4.0f;
} else if (!ambientTextureID.isNull()) {
emissiveTexture = getTexture(ambientTextureID);
}
material.emissiveParams = emissiveParams;
material.emissiveTexture = emissiveTexture;
if (!emissiveTextureID.isNull()) {
emissiveTexture = getTexture(emissiveTextureID);
detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity());
material.emissiveTexture = emissiveTexture;
}
FBXTexture occlusionTexture;
QString occlusionTextureID = occlusionTextures.value(material.materialID);
if (!occlusionTextureID.isNull()) {
occlusionTexture = getTexture(occlusionTextureID);
detectDifferentUVs |= (occlusionTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity());
material.occlusionTexture = occlusionTexture;
}
glm::vec2 lightmapParams(0.f, 1.f);
lightmapParams.x = _lightmapOffset;
lightmapParams.y = _lightmapLevel;
FBXTexture ambientTexture;
QString ambientTextureID = ambientTextures.value(material.materialID);
if (_loadLightmaps && !ambientTextureID.isNull()) {
ambientTexture = getTexture(ambientTextureID);
detectDifferentUVs |= (ambientTexture.texcoordSet != 0) || (!ambientTexture.transform.isIdentity());
material.lightmapTexture = ambientTexture;
material.lightmapParams = lightmapParams;
}
// Finally create the true material representation
@ -140,13 +178,16 @@ void FBXReader::consolidateFBXMaterials() {
auto diffuse = material.diffuseColor;
// FIXME: Do not use the Diffuse Factor yet as some FBX models have it set to 0
// diffuse *= material.diffuseFactor;
material._material->setDiffuse(diffuse);
material._material->setAlbedo(diffuse);
float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z));
// FIXME: Do not use the Specular Factor yet as some FBX models have it set to 0
// metallic *= material.specularFactor;
material._material->setMetallic(metallic);
material._material->setGloss(material.shininess);
if (material.isPBSMaterial) {
material._material->setRoughness(material.roughness);
material._material->setMetallic(material.metallic);
} else {
material._material->setRoughness(model::Material::shininessToRoughness(material.shininess));
float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z));
material._material->setMetallic(metallic);
}
if (material.opacity <= 0.0f) {
material._material->setOpacity(1.0f);

View file

@ -558,7 +558,6 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping,
geometry.materials[materialID] = FBXMaterial(objMaterial.diffuseColor,
objMaterial.specularColor,
glm::vec3(0.0f),
glm::vec2(0.0f, 1.0f),
objMaterial.shininess,
objMaterial.opacity);
FBXMaterial& fbxMaterial = geometry.materials[materialID];
@ -567,13 +566,13 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping,
model::MaterialPointer modelMaterial = fbxMaterial._material;
if (!objMaterial.diffuseTextureFilename.isEmpty()) {
fbxMaterial.diffuseTexture.filename = objMaterial.diffuseTextureFilename;
fbxMaterial.albedoTexture.filename = objMaterial.diffuseTextureFilename;
}
modelMaterial->setEmissive(fbxMaterial.emissiveColor);
modelMaterial->setDiffuse(fbxMaterial.diffuseColor);
modelMaterial->setAlbedo(fbxMaterial.diffuseColor);
modelMaterial->setMetallic(glm::length(fbxMaterial.specularColor));
modelMaterial->setGloss(fbxMaterial.shininess);
modelMaterial->setRoughness(model::Material::shininessToRoughness(fbxMaterial.shininess));
if (fbxMaterial.opacity <= 0.0f) {
modelMaterial->setOpacity(1.0f);
@ -617,7 +616,7 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) {
qCDebug(modelformat) << " specularColor =" << meshPart.specularColor << "mat =" << meshPart._material->getMetallic();
qCDebug(modelformat) << " emissiveColor =" << meshPart.emissiveColor << "mat =" << meshPart._material->getEmissive();
qCDebug(modelformat) << " emissiveParams =" << meshPart.emissiveParams;
qCDebug(modelformat) << " gloss =" << meshPart.shininess << "mat =" << meshPart._material->getGloss();
qCDebug(modelformat) << " gloss =" << meshPart.shininess << "mat =" << meshPart._material->getRoughness();
qCDebug(modelformat) << " opacity =" << meshPart.opacity << "mat =" << meshPart._material->getOpacity();
*/
qCDebug(modelformat) << " materialID =" << meshPart.materialID;

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

@ -162,8 +162,6 @@ GLBackend::GLShader* compileShader(const Shader& shader) {
char* temp = new char[infoLength] ;
glGetShaderInfoLog(glshader, infoLength, NULL, temp);
qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:";
qCWarning(gpulogging) << temp;
/*
filestream.open("debugshader.glsl.info.txt");
@ -172,6 +170,11 @@ GLBackend::GLShader* compileShader(const Shader& shader) {
filestream.close();
}
*/
qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:";
qCWarning(gpulogging) << srcstr;
qCWarning(gpulogging) << "GLShader::compileShader - errors:";
qCWarning(gpulogging) << temp;
delete[] temp;
glDeleteShader(glshader);

View file

@ -145,6 +145,8 @@ public:
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
case gpu::SRGB:
case gpu::SRGBA:
texel.internalFormat = GL_RED;
switch (dstFormat.getType()) {
case gpu::UINT32: {
@ -196,7 +198,11 @@ public:
break;
}
case gpu::NUINT8: {
texel.internalFormat = GL_R8;
if ((dstFormat.getSemantic() == gpu::SRGB || dstFormat.getSemantic() == gpu::SRGBA)) {
texel.internalFormat = GL_SLUMINANCE;
} else {
texel.internalFormat = GL_R8;
}
break;
}
case gpu::NINT8: {
@ -209,6 +215,7 @@ public:
}
break;
case gpu::DEPTH:
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
texel.internalFormat = GL_DEPTH_COMPONENT;

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

@ -136,10 +136,13 @@ bool NetworkGeometry::isLoadedWithTextures() const {
if (!_isLoadedWithTextures) {
for (auto&& material : _materials) {
if ((material->diffuseTexture && !material->diffuseTexture->isLoaded()) ||
if ((material->albedoTexture && !material->albedoTexture->isLoaded()) ||
(material->normalTexture && !material->normalTexture->isLoaded()) ||
(material->specularTexture && !material->specularTexture->isLoaded()) ||
(material->emissiveTexture && !material->emissiveTexture->isLoaded())) {
(material->roughnessTexture && !material->roughnessTexture->isLoaded()) ||
(material->metallicTexture && !material->metallicTexture->isLoaded()) ||
(material->occlusionTexture && !material->occlusionTexture->isLoaded()) ||
(material->emissiveTexture && !material->emissiveTexture->isLoaded()) ||
(material->lightmapTexture && !material->lightmapTexture->isLoaded())) {
return false;
}
}
@ -154,15 +157,15 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u
for (auto&& material : _materials) {
auto networkMaterial = material->_material;
auto oldTextureMaps = networkMaterial->getTextureMaps();
if (material->diffuseTextureName == name) {
material->diffuseTexture = textureCache->getTexture(url, DEFAULT_TEXTURE);
if (material->albedoTextureName == name) {
material->albedoTexture = textureCache->getTexture(url, DEFAULT_TEXTURE);
auto diffuseMap = model::TextureMapPointer(new model::TextureMap());
diffuseMap->setTextureSource(material->diffuseTexture->_textureSource);
diffuseMap->setTextureTransform(
oldTextureMaps[model::MaterialKey::DIFFUSE_MAP]->getTextureTransform());
auto albedoMap = model::TextureMapPointer(new model::TextureMap());
albedoMap->setTextureSource(material->albedoTexture->_textureSource);
albedoMap->setTextureTransform(
oldTextureMaps[model::MaterialKey::ALBEDO_MAP]->getTextureTransform());
networkMaterial->setTextureMap(model::MaterialKey::DIFFUSE_MAP, diffuseMap);
networkMaterial->setTextureMap(model::MaterialKey::ALBEDO_MAP, albedoMap);
} else if (material->normalTextureName == name) {
material->normalTexture = textureCache->getTexture(url);
@ -170,15 +173,31 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u
normalMap->setTextureSource(material->normalTexture->_textureSource);
networkMaterial->setTextureMap(model::MaterialKey::NORMAL_MAP, normalMap);
} else if (material->specularTextureName == name) {
material->specularTexture = textureCache->getTexture(url);
} else if (material->roughnessTextureName == name) {
// FIXME: If passing a gloss map instead of a roughmap how to say that ? looking for gloss in the name ?
material->roughnessTexture = textureCache->getTexture(url, ROUGHNESS_TEXTURE);
auto roughnessMap = model::TextureMapPointer(new model::TextureMap());
roughnessMap->setTextureSource(material->roughnessTexture->_textureSource);
networkMaterial->setTextureMap(model::MaterialKey::ROUGHNESS_MAP, roughnessMap);
} else if (material->metallicTextureName == name) {
// FIXME: If passing a specular map instead of a metallic how to say that ? looking for wtf in the name ?
material->metallicTexture = textureCache->getTexture(url, METALLIC_TEXTURE);
auto glossMap = model::TextureMapPointer(new model::TextureMap());
glossMap->setTextureSource(material->specularTexture->_textureSource);
glossMap->setTextureSource(material->metallicTexture->_textureSource);
networkMaterial->setTextureMap(model::MaterialKey::GLOSS_MAP, glossMap);
networkMaterial->setTextureMap(model::MaterialKey::METALLIC_MAP, glossMap);
} else if (material->emissiveTextureName == name) {
material->emissiveTexture = textureCache->getTexture(url);
material->emissiveTexture = textureCache->getTexture(url, EMISSIVE_TEXTURE);
auto emissiveMap = model::TextureMapPointer(new model::TextureMap());
emissiveMap->setTextureSource(material->emissiveTexture->_textureSource);
networkMaterial->setTextureMap(model::MaterialKey::EMISSIVE_MAP, emissiveMap);
} else if (material->lightmapTextureName == name) {
material->emissiveTexture = textureCache->getTexture(url, LIGHTMAP_TEXTURE);
auto lightmapMap = model::TextureMapPointer(new model::TextureMap());
lightmapMap->setTextureSource(material->emissiveTexture->_textureSource);
@ -200,9 +219,14 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u
QStringList NetworkGeometry::getTextureNames() const {
QStringList result;
for (auto&& material : _materials) {
if (!material->diffuseTextureName.isEmpty() && material->diffuseTexture) {
QString textureURL = material->diffuseTexture->getURL().toString();
result << material->diffuseTextureName + ":\"" + textureURL + "\"";
if (!material->emissiveTextureName.isEmpty() && material->emissiveTexture) {
QString textureURL = material->emissiveTexture->getURL().toString();
result << material->emissiveTextureName + ":\"" + textureURL + "\"";
}
if (!material->albedoTextureName.isEmpty() && material->albedoTexture) {
QString textureURL = material->albedoTexture->getURL().toString();
result << material->albedoTextureName + ":\"" + textureURL + "\"";
}
if (!material->normalTextureName.isEmpty() && material->normalTexture) {
@ -210,14 +234,24 @@ QStringList NetworkGeometry::getTextureNames() const {
result << material->normalTextureName + ":\"" + textureURL + "\"";
}
if (!material->specularTextureName.isEmpty() && material->specularTexture) {
QString textureURL = material->specularTexture->getURL().toString();
result << material->specularTextureName + ":\"" + textureURL + "\"";
if (!material->roughnessTextureName.isEmpty() && material->roughnessTexture) {
QString textureURL = material->roughnessTexture->getURL().toString();
result << material->roughnessTextureName + ":\"" + textureURL + "\"";
}
if (!material->emissiveTextureName.isEmpty() && material->emissiveTexture) {
QString textureURL = material->emissiveTexture->getURL().toString();
result << material->emissiveTextureName + ":\"" + textureURL + "\"";
if (!material->metallicTextureName.isEmpty() && material->metallicTexture) {
QString textureURL = material->metallicTexture->getURL().toString();
result << material->metallicTextureName + ":\"" + textureURL + "\"";
}
if (!material->occlusionTextureName.isEmpty() && material->occlusionTexture) {
QString textureURL = material->occlusionTexture->getURL().toString();
result << material->occlusionTextureName + ":\"" + textureURL + "\"";
}
if (!material->lightmapTextureName.isEmpty() && material->lightmapTexture) {
QString textureURL = material->lightmapTexture->getURL().toString();
result << material->lightmapTextureName + ":\"" + textureURL + "\"";
}
}
@ -304,7 +338,8 @@ static NetworkMesh* buildNetworkMesh(const FBXMesh& mesh, const QUrl& textureBas
return networkMesh;
}
static model::TextureMapPointer setupNetworkTextureMap(const QUrl& textureBaseUrl,
static model::TextureMapPointer setupNetworkTextureMap(NetworkGeometry* geometry, const QUrl& textureBaseUrl,
const FBXTexture& texture, TextureType type,
NetworkTexturePointer& networkTexture, QString& networkTextureName) {
auto textureCache = DependencyManager::get<TextureCache>();
@ -314,6 +349,7 @@ static model::TextureMapPointer setupNetworkTextureMap(const QUrl& textureBaseUr
const auto filename = baseUrl.resolved(QUrl(texture.filename));
networkTexture = textureCache->getTexture(filename, type, texture.content);
QObject::connect(networkTexture.data(), &NetworkTexture::networkTextureCreated, geometry, &NetworkGeometry::textureLoaded);
networkTextureName = texture.name;
auto map = std::make_shared<model::TextureMap>();
@ -321,33 +357,66 @@ static model::TextureMapPointer setupNetworkTextureMap(const QUrl& textureBaseUr
return map;
}
static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl) {
static NetworkMaterial* buildNetworkMaterial(NetworkGeometry* geometry, const FBXMaterial& material, const QUrl& textureBaseUrl) {
NetworkMaterial* networkMaterial = new NetworkMaterial();
networkMaterial->_material = material._material;
if (!material.diffuseTexture.filename.isEmpty()) {
auto diffuseMap = setupNetworkTextureMap(textureBaseUrl, material.diffuseTexture, DEFAULT_TEXTURE,
networkMaterial->diffuseTexture, networkMaterial->diffuseTextureName);
diffuseMap->setTextureTransform(material.diffuseTexture.transform);
networkMaterial->_material->setTextureMap(model::MaterialKey::DIFFUSE_MAP, diffuseMap);
if (!material.albedoTexture.filename.isEmpty()) {
auto albedoMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.albedoTexture, DEFAULT_TEXTURE,
networkMaterial->albedoTexture, networkMaterial->albedoTextureName);
albedoMap->setTextureTransform(material.albedoTexture.transform);
material._material->setTextureMap(model::MaterialKey::ALBEDO_MAP, albedoMap);
}
if (!material.normalTexture.filename.isEmpty()) {
auto normalMap = setupNetworkTextureMap(textureBaseUrl, material.normalTexture,
auto normalMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.normalTexture,
(material.normalTexture.isBumpmap ? BUMP_TEXTURE : NORMAL_TEXTURE),
networkMaterial->normalTexture, networkMaterial->normalTextureName);
networkMaterial->_material->setTextureMap(model::MaterialKey::NORMAL_MAP, normalMap);
}
if (!material.specularTexture.filename.isEmpty()) {
auto glossMap = setupNetworkTextureMap(textureBaseUrl, material.specularTexture, SPECULAR_TEXTURE,
networkMaterial->specularTexture, networkMaterial->specularTextureName);
networkMaterial->_material->setTextureMap(model::MaterialKey::GLOSS_MAP, glossMap);
// Roughness first or gloss maybe
if (!material.roughnessTexture.filename.isEmpty()) {
auto roughnessMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.roughnessTexture, ROUGHNESS_TEXTURE,
networkMaterial->roughnessTexture, networkMaterial->roughnessTextureName);
material._material->setTextureMap(model::MaterialKey::ROUGHNESS_MAP, roughnessMap);
} else if (!material.glossTexture.filename.isEmpty()) {
auto roughnessMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.glossTexture, GLOSS_TEXTURE,
networkMaterial->roughnessTexture, networkMaterial->roughnessTextureName);
material._material->setTextureMap(model::MaterialKey::ROUGHNESS_MAP, roughnessMap);
}
// Metallic first or specular maybe
if (!material.metallicTexture.filename.isEmpty()) {
auto metallicMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.metallicTexture, METALLIC_TEXTURE,
networkMaterial->metallicTexture, networkMaterial->metallicTextureName);
material._material->setTextureMap(model::MaterialKey::METALLIC_MAP, metallicMap);
} else if (!material.specularTexture.filename.isEmpty()) {
auto metallicMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.specularTexture, SPECULAR_TEXTURE,
networkMaterial->metallicTexture, networkMaterial->metallicTextureName);
material._material->setTextureMap(model::MaterialKey::METALLIC_MAP, metallicMap);
}
if (!material.occlusionTexture.filename.isEmpty()) {
auto occlusionMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.occlusionTexture, OCCLUSION_TEXTURE,
networkMaterial->occlusionTexture, networkMaterial->occlusionTextureName);
material._material->setTextureMap(model::MaterialKey::OCCLUSION_MAP, occlusionMap);
}
if (!material.emissiveTexture.filename.isEmpty()) {
auto lightmapMap = setupNetworkTextureMap(textureBaseUrl, material.emissiveTexture, LIGHTMAP_TEXTURE,
auto emissiveMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.emissiveTexture, EMISSIVE_TEXTURE,
networkMaterial->emissiveTexture, networkMaterial->emissiveTextureName);
lightmapMap->setTextureTransform(material.emissiveTexture.transform);
lightmapMap->setLightmapOffsetScale(material.emissiveParams.x, material.emissiveParams.y);
networkMaterial->_material->setTextureMap(model::MaterialKey::LIGHTMAP_MAP, lightmapMap);
material._material->setTextureMap(model::MaterialKey::EMISSIVE_MAP, emissiveMap);
}
if (!material.lightmapTexture.filename.isEmpty()) {
auto lightmapMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.lightmapTexture, LIGHTMAP_TEXTURE,
networkMaterial->lightmapTexture, networkMaterial->lightmapTextureName);
lightmapMap->setTextureTransform(material.lightmapTexture.transform);
lightmapMap->setLightmapOffsetScale(material.lightmapParams.x, material.lightmapParams.y);
material._material->setTextureMap(model::MaterialKey::LIGHTMAP_MAP, lightmapMap);
}
return networkMaterial;
@ -367,7 +436,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));
}
@ -413,3 +482,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,15 +178,23 @@ public:
class NetworkMaterial {
public:
model::MaterialPointer _material;
QString diffuseTextureName;
QSharedPointer<NetworkTexture> diffuseTexture;
QString normalTextureName;
QSharedPointer<NetworkTexture> normalTexture;
QString specularTextureName;
QSharedPointer<NetworkTexture> specularTexture;
QString emissiveTextureName;
QSharedPointer<NetworkTexture> emissiveTexture;
QString albedoTextureName;
QSharedPointer<NetworkTexture> albedoTexture;
QString normalTextureName;
QSharedPointer<NetworkTexture> normalTexture;
QString roughnessTextureName;
QSharedPointer<NetworkTexture> roughnessTexture;
QString metallicTextureName;
QSharedPointer<NetworkTexture> metallicTexture;
QString occlusionTextureName;
QSharedPointer<NetworkTexture> occlusionTexture;
QString lightmapTextureName;
QSharedPointer<NetworkTexture> lightmapTexture;
};

View file

@ -212,12 +212,23 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromNormalImage);
break;
}
case ROUGHNESS_TEXTURE: {
return TextureLoaderFunc(model::TextureUsage::createRoughnessTextureFromImage);
break;
}
case GLOSS_TEXTURE: {
return TextureLoaderFunc(model::TextureUsage::createRoughnessTextureFromGlossImage);
break;
}
case SPECULAR_TEXTURE: {
return TextureLoaderFunc(model::TextureUsage::createMetallicTextureFromImage);
break;
}
case CUSTOM_TEXTURE: {
return _textureLoader;
break;
}
case DEFAULT_TEXTURE:
case SPECULAR_TEXTURE:
case EMISSIVE_TEXTURE:
default: {
return TextureLoaderFunc(model::TextureUsage::create2DTextureFromImage);
@ -335,10 +346,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

@ -29,7 +29,20 @@ class NetworkTexture;
typedef QSharedPointer<NetworkTexture> NetworkTexturePointer;
enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, CUBE_TEXTURE, LIGHTMAP_TEXTURE, CUSTOM_TEXTURE };
enum TextureType {
DEFAULT_TEXTURE,
NORMAL_TEXTURE,
BUMP_TEXTURE,
SPECULAR_TEXTURE,
METALLIC_TEXTURE = SPECULAR_TEXTURE, // for now spec and metallic texture are the same, converted to grey
ROUGHNESS_TEXTURE,
GLOSS_TEXTURE,
EMISSIVE_TEXTURE,
CUBE_TEXTURE,
OCCLUSION_TEXTURE,
LIGHTMAP_TEXTURE,
CUSTOM_TEXTURE
};
/// Stores cached textures, including render-to-texture targets.
class TextureCache : public ResourceCache, public Dependency {
@ -83,8 +96,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 +125,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 +138,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

@ -130,7 +130,7 @@ void Light::setShowContour(float show) {
if (show <= 0.f) {
show = 0.0f;
}
editSchema()._control.w = show;
editSchema()._control.z = show;
}
void Light::setAmbientSphere(const gpu::SphericalHarmonics& sphere) {
@ -140,3 +140,16 @@ void Light::setAmbientSphere(const gpu::SphericalHarmonics& sphere) {
void Light::setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset) {
editSchema()._ambientSphere.assignPreset(preset);
}
void Light::setAmbientMap(gpu::TexturePointer ambientMap) {
_ambientMap = ambientMap;
if (ambientMap) {
setAmbientMapNumMips(_ambientMap->evalNumMips());
} else {
setAmbientMapNumMips(0);
}
}
void Light::setAmbientMapNumMips(uint16_t numMips) {
editSchema()._ambientMapNumMips = (float)numMips;
}

View file

@ -97,7 +97,7 @@ public:
// For editing purpose, show the light volume contour.
// Set to non 0 to show it, the value is used as the intensity of the contour color
void setShowContour(float show);
float getShowContour() const { return getSchema()._control.w; }
float getShowContour() const { return getSchema()._control.z; }
// If the light has an ambient (Indirect) component, then the Ambientintensity can be used to control its contribution to the lighting
void setAmbientIntensity(float intensity);
@ -108,6 +108,12 @@ public:
const gpu::SphericalHarmonics& getAmbientSphere() const { return getSchema()._ambientSphere; }
void setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset);
void setAmbientMap(gpu::TexturePointer ambientMap);
gpu::TexturePointer getAmbientMap() const { return _ambientMap; }
void setAmbientMapNumMips(uint16_t numMips);
uint16_t getAmbientMapNumMips() const { return (uint16_t) getSchema()._ambientMapNumMips; }
// Schema to access the attribute values of the light
class Schema {
public:
@ -120,7 +126,8 @@ public:
Vec4 _spot{0.0f, 0.0f, 0.0f, 0.0f};
Vec4 _shadow{0.0f};
Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f};
float _ambientMapNumMips{ 0.0f };
Vec3 _control{ 0.0f, 0.0f, 0.0f };
gpu::SphericalHarmonics _ambientSphere;
};
@ -133,6 +140,8 @@ protected:
UniformBufferView _schemaBuffer;
Transform _transform;
gpu::TexturePointer _ambientMap;
const Schema& getSchema() const { return _schemaBuffer.get<Schema>(); }
Schema& editSchema() { return _schemaBuffer.edit<Schema>(); }

View file

@ -109,6 +109,10 @@ SphericalHarmonics getLightAmbientSphere(Light l) {
return l._ambientSphere;
}
float getLightAmbientMapNumMips(Light l) {
return l._control.x;
}
<@if GPU_FEATURE_PROFILE == GPU_CORE @>
uniform lightBuffer {
Light light;

View file

@ -44,37 +44,51 @@ Material& Material::operator= (const Material& material) {
Material::~Material() {
}
void Material::setDiffuse(const Color& diffuse, bool isSRGB) {
_key.setDiffuse(glm::any(glm::greaterThan(diffuse, Color(0.0f))));
_schemaBuffer.edit<Schema>()._diffuse = (isSRGB ? ColorUtils::toLinearVec3(diffuse) : diffuse);
}
void Material::setMetallic(float metallic) {
_key.setMetallic(metallic > 0.0f);
_schemaBuffer.edit<Schema>()._metallic = glm::vec3(metallic);
}
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::setGloss(float gloss) {
_key.setGloss((gloss > 0.0f));
_schemaBuffer.edit<Schema>()._gloss = gloss;
}
void Material::setOpacity(float opacity) {
_key.setTransparent((opacity < 1.0f));
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
_schemaBuffer.edit<Schema>()._opacity = opacity;
}
void Material::setAlbedo(const Color& albedo, bool isSRGB) {
_key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f))));
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
_schemaBuffer.edit<Schema>()._albedo = (isSRGB ? ColorUtils::toLinearVec3(albedo) : albedo);
}
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;
}
void Material::setFresnel(const Color& fresnel, bool isSRGB) {
//_key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f))));
_schemaBuffer.edit<Schema>()._fresnel = (isSRGB ? ColorUtils::toLinearVec3(fresnel) : fresnel);
}
void Material::setMetallic(float metallic) {
_key.setMetallic(metallic > 0.0f);
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
_schemaBuffer.edit<Schema>()._metallic = 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

@ -28,17 +28,18 @@ class MaterialKey {
public:
enum FlagBit {
EMISSIVE_VAL_BIT = 0,
DIFFUSE_VAL_BIT,
ALBEDO_VAL_BIT,
METALLIC_VAL_BIT,
GLOSS_VAL_BIT,
GLOSSY_VAL_BIT,
TRANSPARENT_VAL_BIT,
EMISSIVE_MAP_BIT,
DIFFUSE_MAP_BIT,
ALBEDO_MAP_BIT,
METALLIC_MAP_BIT,
GLOSS_MAP_BIT,
ROUGHNESS_MAP_BIT,
TRANSPARENT_MAP_BIT,
NORMAL_MAP_BIT,
OCCLUSION_MAP_BIT,
LIGHTMAP_MAP_BIT,
NUM_FLAGS,
@ -47,11 +48,12 @@ public:
enum MapChannel {
EMISSIVE_MAP = 0,
DIFFUSE_MAP,
ALBEDO_MAP,
METALLIC_MAP,
GLOSS_MAP,
ROUGHNESS_MAP,
TRANSPARENT_MAP,
NORMAL_MAP,
OCCLUSION_MAP,
LIGHTMAP_MAP,
NUM_MAP_CHANNELS,
@ -71,22 +73,23 @@ public:
MaterialKey build() const { return MaterialKey(_flags); }
Builder& withEmissive() { _flags.set(EMISSIVE_VAL_BIT); return (*this); }
Builder& withDiffuse() { _flags.set(DIFFUSE_VAL_BIT); return (*this); }
Builder& withAlbedo() { _flags.set(ALBEDO_VAL_BIT); return (*this); }
Builder& withMetallic() { _flags.set(METALLIC_VAL_BIT); return (*this); }
Builder& withGloss() { _flags.set(GLOSS_VAL_BIT); return (*this); }
Builder& withGlossy() { _flags.set(GLOSSY_VAL_BIT); return (*this); }
Builder& withTransparent() { _flags.set(TRANSPARENT_VAL_BIT); return (*this); }
Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT); return (*this); }
Builder& withDiffuseMap() { _flags.set(DIFFUSE_MAP_BIT); return (*this); }
Builder& withAlbedoMap() { _flags.set(ALBEDO_MAP_BIT); return (*this); }
Builder& withMetallicMap() { _flags.set(METALLIC_MAP_BIT); return (*this); }
Builder& withGlossMap() { _flags.set(GLOSS_MAP_BIT); return (*this); }
Builder& withRoughnessMap() { _flags.set(ROUGHNESS_MAP_BIT); return (*this); }
Builder& withTransparentMap() { _flags.set(TRANSPARENT_MAP_BIT); return (*this); }
Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); }
Builder& withOcclusionMap() { _flags.set(OCCLUSION_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(); }
static MaterialKey opaqueAlbedo() { return Builder().withAlbedo().build(); }
};
void setEmissive(bool value) { _flags.set(EMISSIVE_VAL_BIT, value); }
@ -95,11 +98,11 @@ public:
void setEmissiveMap(bool value) { _flags.set(EMISSIVE_MAP_BIT, value); }
bool isEmissiveMap() const { return _flags[EMISSIVE_MAP_BIT]; }
void setDiffuse(bool value) { _flags.set(DIFFUSE_VAL_BIT, value); }
bool isDiffuse() const { return _flags[DIFFUSE_VAL_BIT]; }
void setAlbedo(bool value) { _flags.set(ALBEDO_VAL_BIT, value); }
bool isAlbedo() const { return _flags[ALBEDO_VAL_BIT]; }
void setDiffuseMap(bool value) { _flags.set(DIFFUSE_MAP_BIT, value); }
bool isDiffuseMap() const { return _flags[DIFFUSE_MAP_BIT]; }
void setAlbedoMap(bool value) { _flags.set(ALBEDO_MAP_BIT, value); }
bool isAlbedoMap() const { return _flags[ALBEDO_MAP_BIT]; }
void setMetallic(bool value) { _flags.set(METALLIC_VAL_BIT, value); }
bool isMetallic() const { return _flags[METALLIC_VAL_BIT]; }
@ -107,11 +110,12 @@ public:
void setMetallicMap(bool value) { _flags.set(METALLIC_MAP_BIT, value); }
bool isMetallicMap() const { return _flags[METALLIC_MAP_BIT]; }
void setGloss(bool value) { _flags.set(GLOSS_VAL_BIT, value); }
bool isGloss() const { return _flags[GLOSS_VAL_BIT]; }
void setGlossy(bool value) { _flags.set(GLOSSY_VAL_BIT, value); }
bool isGlossy() const { return _flags[GLOSSY_VAL_BIT]; }
bool isRough() const { return !_flags[GLOSSY_VAL_BIT]; }
void setGlossMap(bool value) { _flags.set(GLOSS_MAP_BIT, value); }
bool isGlossMap() const { return _flags[GLOSS_MAP_BIT]; }
void setRoughnessMap(bool value) { _flags.set(ROUGHNESS_MAP_BIT, value); }
bool isRoughnessMap() const { return _flags[ROUGHNESS_MAP_BIT]; }
void setTransparent(bool value) { _flags.set(TRANSPARENT_VAL_BIT, value); }
bool isTransparent() const { return _flags[TRANSPARENT_VAL_BIT]; }
@ -123,6 +127,9 @@ public:
void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); }
bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; }
void setOcclusionMap(bool value) { _flags.set(OCCLUSION_MAP_BIT, value); }
bool isOcclusionMap() const { return _flags[OCCLUSION_MAP_BIT]; }
void setLightmapMap(bool value) { _flags.set(LIGHTMAP_MAP_BIT, value); }
bool isLightmapMap() const { return _flags[LIGHTMAP_MAP_BIT]; }
@ -154,11 +161,11 @@ public:
Builder& withoutEmissiveMap() { _value.reset(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT); return (*this); }
Builder& withEmissiveMap() { _value.set(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT); return (*this); }
Builder& withoutDiffuse() { _value.reset(MaterialKey::DIFFUSE_VAL_BIT); _mask.set(MaterialKey::DIFFUSE_VAL_BIT); return (*this); }
Builder& withDiffuse() { _value.set(MaterialKey::DIFFUSE_VAL_BIT); _mask.set(MaterialKey::DIFFUSE_VAL_BIT); return (*this); }
Builder& withoutAlbedo() { _value.reset(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); }
Builder& withAlbedo() { _value.set(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); }
Builder& withoutDiffuseMap() { _value.reset(MaterialKey::DIFFUSE_MAP_BIT); _mask.set(MaterialKey::DIFFUSE_MAP_BIT); return (*this); }
Builder& withDiffuseMap() { _value.set(MaterialKey::DIFFUSE_MAP_BIT); _mask.set(MaterialKey::DIFFUSE_MAP_BIT); return (*this); }
Builder& withoutAlbedoMap() { _value.reset(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); }
Builder& withAlbedoMap() { _value.set(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); }
Builder& withoutMetallic() { _value.reset(MaterialKey::METALLIC_VAL_BIT); _mask.set(MaterialKey::METALLIC_VAL_BIT); return (*this); }
Builder& withMetallic() { _value.set(MaterialKey::METALLIC_VAL_BIT); _mask.set(MaterialKey::METALLIC_VAL_BIT); return (*this); }
@ -166,11 +173,11 @@ public:
Builder& withoutMetallicMap() { _value.reset(MaterialKey::METALLIC_MAP_BIT); _mask.set(MaterialKey::METALLIC_MAP_BIT); return (*this); }
Builder& withMetallicMap() { _value.set(MaterialKey::METALLIC_MAP_BIT); _mask.set(MaterialKey::METALLIC_MAP_BIT); return (*this); }
Builder& withoutGloss() { _value.reset(MaterialKey::GLOSS_VAL_BIT); _mask.set(MaterialKey::GLOSS_VAL_BIT); return (*this); }
Builder& withGloss() { _value.set(MaterialKey::GLOSS_VAL_BIT); _mask.set(MaterialKey::GLOSS_VAL_BIT); return (*this); }
Builder& withoutGlossy() { _value.reset(MaterialKey::GLOSSY_VAL_BIT); _mask.set(MaterialKey::GLOSSY_VAL_BIT); return (*this); }
Builder& withGlossy() { _value.set(MaterialKey::GLOSSY_VAL_BIT); _mask.set(MaterialKey::GLOSSY_VAL_BIT); return (*this); }
Builder& withoutGlossMap() { _value.reset(MaterialKey::GLOSS_MAP_BIT); _mask.set(MaterialKey::GLOSS_MAP_BIT); return (*this); }
Builder& withGlossMap() { _value.set(MaterialKey::GLOSS_MAP_BIT); _mask.set(MaterialKey::GLOSS_MAP_BIT); return (*this); }
Builder& withoutRoughnessMap() { _value.reset(MaterialKey::ROUGHNESS_MAP_BIT); _mask.set(MaterialKey::ROUGHNESS_MAP_BIT); return (*this); }
Builder& withRoughnessMap() { _value.set(MaterialKey::ROUGHNESS_MAP_BIT); _mask.set(MaterialKey::ROUGHNESS_MAP_BIT); return (*this); }
Builder& withoutTransparent() { _value.reset(MaterialKey::TRANSPARENT_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_VAL_BIT); return (*this); }
Builder& withTransparent() { _value.set(MaterialKey::TRANSPARENT_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_VAL_BIT); return (*this); }
@ -181,11 +188,14 @@ 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& withoutOcclusionMap() { _value.reset(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_MAP_BIT); return (*this); }
Builder& withOcclusionMap() { _value.set(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_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(); }
static MaterialFilter opaqueAlbedo() { return Builder().withAlbedo().withoutTransparent().build(); }
};
// Item Filter operator testing if a key pass the filter
@ -223,29 +233,39 @@ public:
void setEmissive(const Color& emissive, bool isSRGB = true);
Color getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._emissive) : _schemaBuffer.get<Schema>()._emissive); }
void setDiffuse(const Color& diffuse, bool isSRGB = true);
Color getDiffuse(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._diffuse) : _schemaBuffer.get<Schema>()._diffuse); }
void setMetallic(float metallic);
float getMetallic() const { return _schemaBuffer.get<Schema>()._metallic.x; }
void setGloss(float gloss);
float getGloss() const { return _schemaBuffer.get<Schema>()._gloss; }
void setOpacity(float opacity);
float getOpacity() const { return _schemaBuffer.get<Schema>()._opacity; }
void setAlbedo(const Color& albedo, bool isSRGB = true);
Color getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._albedo) : _schemaBuffer.get<Schema>()._albedo); }
void setFresnel(const Color& fresnel, bool isSRGB = true);
Color getFresnel(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._fresnel) : _schemaBuffer.get<Schema>()._fresnel); }
void setMetallic(float metallic);
float getMetallic() const { return _schemaBuffer.get<Schema>()._metallic; }
void setRoughness(float roughness);
float getRoughness() const { return _schemaBuffer.get<Schema>()._roughness; }
// Schema to access the attribute values of the material
class Schema {
public:
glm::vec3 _diffuse{ 0.5f };
float _opacity{1.f};
glm::vec3 _metallic{ 0.03f };
float _gloss{0.1f};
glm::vec3 _emissive{ 0.0f };
float _spare0{0.0f};
glm::vec4 _spareVec4{0.0f}; // for alignment beauty, Material size == Mat4x4
glm::vec3 _emissive{ 0.0f }; // No Emissive
float _opacity{ 1.0f }; // Opacity = 1 => Not Transparent
glm::vec3 _albedo{ 0.5f }; // Grey albedo => isAlbedo
float _roughness{ 1.0f }; // Roughness = 1 => Not Glossy
glm::vec3 _fresnel{ 0.03f }; // Fresnel value for a default non metallic
float _metallic{ 0.0f }; // Not Metallic
glm::vec3 _spare0{ 0.0f };
uint32_t _key{ 0 }; // a copy of the materialKey
// for alignment beauty, Material size == Mat4x4
Schema() {}
};
@ -256,6 +276,9 @@ public:
void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap);
const TextureMaps& getTextureMaps() const { return _textureMaps; }
// conversion from legacy material properties to PBR equivalent
static float shininessToRoughness(float shininess) { return 1.0f - shininess / 100.0f; }
protected:
MaterialKey _key;

View file

@ -12,9 +12,9 @@
<@def MODEL_MATERIAL_SLH@>
struct Material {
vec4 _diffuse;
vec4 _specular;
vec4 _emissive;
vec4 _emissiveOpacity;
vec4 _albedoRoughness;
vec4 _fresnelMetallic;
vec4 _spare;
};
@ -26,41 +26,36 @@ Material getMaterial() {
return _mat;
}
<! // TODO: use this code for correct gamma correction
/*
float componentSRGBToLinear(float cs) {
// sRGB to linear conversion
// { cs / 12.92, cs <= 0.04045
// cl = {
// { ((cs + 0.055)/1.055)^2.4, cs > 0.04045
// constants:
// T = 0.04045
// A = 1 / 1.055 = 0.94786729857
// B = 0.055 * A = 0.05213270142
// C = 1 / 12.92 = 0.0773993808
// G = 2.4
const float T = 0.04045;
const float A = 0.947867;
const float B = 0.052132;
const float C = 0.077399;
const float G = 2.4;
vec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }
float getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }
if (cs > T) {
return pow((cs * A + B), G);
} else {
return cs * C;
}
}
vec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }
float getMaterialRoughness(Material m) { return m._albedoRoughness.a; }
vec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; }
float getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }
float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }
int getMaterialKey(Material m) { return floatBitsToInt(m._spare.w); }
const int EMISSIVE_VAL_BIT = 0x00000001;
const int ALBEDO_VAL_BIT = 0x00000002;
const int METALLIC_VAL_BIT = 0x00000004;
const int GLOSSY_VAL_BIT = 0x00000008;
const int TRANSPARENT_VAL_BIT = 0x00000010;
const int EMISSIVE_MAP_BIT = 0x00000020;
const int ALBEDO_MAP_BIT = 0x00000040;
const int METALLIC_MAP_BIT = 0x00000080;
const int ROUGHNESS_MAP_BIT = 0x00000100;
const int TRANSPARENT_MAP_BIT = 0x00000200;
const int NORMAL_MAP_BIT = 0x00000400;
const int OCCLUSION_MAP_BIT = 0x00000800;
const int LIGHTMAP_MAP_BIT = 0x00001000;
vec3 SRGBToLinear(vec3 srgb) {
return vec3(componentSRGBToLinear(srgb.x),componentSRGBToLinear(srgb.y),componentSRGBToLinear(srgb.z));
}
vec3 getMaterialDiffuse(Material m) { return (gl_FragCoord.x < 800 ? SRGBToLinear(m._diffuse.rgb) : m._diffuse.rgb); }
*/!>
float getMaterialOpacity(Material m) { return m._diffuse.a; }
vec3 getMaterialDiffuse(Material m) { return m._diffuse.rgb; }
vec3 getMaterialSpecular(Material m) { return m._specular.rgb; }
float getMaterialShininess(Material m) { return m._specular.a; }
<@endif@>

View file

@ -212,6 +212,9 @@ void SunSkyStage::setSunAmbientSphere(const gpu::SHPointer& sphere) {
_sunLight->setAmbientSpherePreset(DEFAULT_AMBIENT_SPHERE);
}
}
void SunSkyStage::setSunAmbientMap(const gpu::TexturePointer& map) {
_sunLight->setAmbientMap(map);
}
void SunSkyStage::setSunDirection(const Vec3& direction) {
if (!isSunModelEnabled()) {

View file

@ -150,6 +150,7 @@ public:
void setSunAmbientIntensity(float intensity) { _sunLight->setAmbientIntensity(intensity); }
float getSunAmbientIntensity() const { return getSunLight()->getAmbientIntensity(); }
void setSunAmbientSphere(const gpu::SHPointer& sphere);
void setSunAmbientMap(const gpu::TexturePointer& map);
// The sun direction is expressed in the world space
void setSunDirection(const Vec3& direction);

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;
@ -223,6 +250,99 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm
return theTexture;
}
gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
QImage image = srcImage;
if (!image.hasAlphaChannel()) {
if (image.format() != QImage::Format_RGB888) {
image = image.convertToFormat(QImage::Format_RGB888);
}
} else {
if (image.format() != QImage::Format_ARGB32) {
image = image.convertToFormat(QImage::Format_ARGB32);
}
}
image = image.convertToFormat(QImage::Format_Grayscale8);
gpu::Texture* theTexture = nullptr;
if ((image.width() > 0) && (image.height() > 0)) {
gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB);
gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB);
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);
// FIXME queue for transfer to GPU and block on completion
}
return theTexture;
}
gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& srcImage, const std::string& srcImageName) {
QImage image = srcImage;
if (!image.hasAlphaChannel()) {
if (image.format() != QImage::Format_RGB888) {
image = image.convertToFormat(QImage::Format_RGB888);
}
} else {
if (image.format() != QImage::Format_ARGB32) {
image = image.convertToFormat(QImage::Format_ARGB32);
}
}
// Gloss turned into Rough
image.invertPixels(QImage::InvertRgba);
image = image.convertToFormat(QImage::Format_Grayscale8);
gpu::Texture* theTexture = nullptr;
if ((image.width() > 0) && (image.height() > 0)) {
gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB);
gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB);
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);
// FIXME queue for transfer to GPU and block on completion
}
return theTexture;
}
gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
QImage image = srcImage;
if (!image.hasAlphaChannel()) {
if (image.format() != QImage::Format_RGB888) {
image = image.convertToFormat(QImage::Format_RGB888);
}
} else {
if (image.format() != QImage::Format_ARGB32) {
image = image.convertToFormat(QImage::Format_ARGB32);
}
}
image = image.convertToFormat(QImage::Format_Grayscale8);
gpu::Texture* theTexture = nullptr;
if ((image.width() > 0) && (image.height() > 0)) {
gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB);
gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB);
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);
// FIXME queue for transfer to GPU and block on completion
}
return theTexture;
}
class CubeLayout {
public:
int _widthRatio = 1;
@ -473,8 +593,8 @@ gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, c
theTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f);
f++;
}
// GEnerate irradiance while we are at it
// Generate irradiance while we are at it
theTexture->generateIrradiance();
}
}

View file

@ -27,13 +27,16 @@ typedef glm::vec3 Color;
class TextureUsage {
public:
gpu::Texture::Type _type{ gpu::Texture::TEX_2D };
Material::MapFlags _materialUsage{ MaterialKey::DIFFUSE_MAP };
Material::MapFlags _materialUsage{ MaterialKey::ALBEDO_MAP };
int _environmentUsage = 0;
static gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createRoughnessTextureFromImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createRoughnessTextureFromGlossImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createMetallicTextureFromImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName);
static gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName);

View file

@ -20,6 +20,7 @@
#include "GeometryCache.h"
#include "FramebufferCache.h"
#include "TextureCache.h"
#include "DeferredLightingEffect.h"
#include "debug_deferred_buffer_vert.h"
@ -39,7 +40,7 @@ void DebugDeferredBufferConfig::setMode(int newMode) {
}
enum Slot {
Diffuse = 0,
Albedo = 0,
Normal,
Specular,
Depth,
@ -52,27 +53,54 @@ enum Slot {
static const std::string DEFAULT_DIFFUSE_SHADER {
static const std::string DEFAULT_ALBEDO_SHADER {
"vec4 getFragmentColor() {"
" return vec4(pow(texture(diffuseMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);"
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
" return vec4(pow(frag.diffuse, vec3(1.0 / 2.2)), 1.0);"
" }"
};
static const std::string DEFAULT_SPECULAR_SHADER {
static const std::string DEFAULT_METALLIC_SHADER {
"vec4 getFragmentColor() {"
" return vec4(texture(specularMap, uv).xyz, 1.0);"
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
" return vec4(vec3(pow(frag.metallic, 1.0 / 2.2)), 1.0);"
" }"
};
static const std::string DEFAULT_ROUGHNESS_SHADER {
"vec4 getFragmentColor() {"
" return vec4(vec3(texture(specularMap, uv).a), 1.0);"
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
" return vec4(vec3(pow(frag.roughness, 1.0 / 2.2)), 1.0);"
" }"
};
static const std::string DEFAULT_NORMAL_SHADER {
"vec4 getFragmentColor() {"
" return vec4(normalize(texture(normalMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);"
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
" return vec4(vec3(0.5) + (frag.normal * 0.5), 1.0);"
" }"
};
static const std::string DEFAULT_OCCLUSION_SHADER{
"vec4 getFragmentColor() {"
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
" return vec4(vec3(frag.obscurance), 1.0);"
" }"
};
static const std::string DEFAULT_EMISSIVE_SHADER{
"vec4 getFragmentColor() {"
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
" return (frag.mode != LIGHT_MAPPED ? vec4(pow(frag.emissive, vec3(1.0 / 2.2)), 1.0) : vec4(vec3(0.0), 1.0));"
" }"
};
static const std::string DEFAULT_LIGHTMAP_SHADER{
"vec4 getFragmentColor() {"
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
" return (frag.mode == LIGHT_MAPPED ? vec4(frag.emissive, 1.0) : vec4(vec3(0.0), 1.0));"
" }"
};
static const std::string DEFAULT_DEPTH_SHADER {
"vec4 getFragmentColor() {"
" return vec4(vec3(texture(depthMap, uv).x), 1.0);"
@ -105,7 +133,7 @@ static const std::string DEFAULT_PYRAMID_DEPTH_SHADER {
static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER{
"vec4 getFragmentColor() {"
" return vec4(vec3(texture(occlusionMap, uv).x), 1.0);"
" return vec4(vec3(texture(obscuranceMap, uv).x), 1.0);"
// When drawing color " return vec4(vec3(texture(occlusionMap, uv).xyz), 1.0);"
// when drawing normal " return vec4(normalize(texture(occlusionMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);"
" }"
@ -144,16 +172,22 @@ DebugDeferredBuffer::DebugDeferredBuffer() {
std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string customFile) {
switch (mode) {
case DiffuseMode:
return DEFAULT_DIFFUSE_SHADER;
case SpecularMode:
return DEFAULT_SPECULAR_SHADER;
case AlbedoMode:
return DEFAULT_ALBEDO_SHADER;
case MetallicMode:
return DEFAULT_METALLIC_SHADER;
case RoughnessMode:
return DEFAULT_ROUGHNESS_SHADER;
case NormalMode:
return DEFAULT_NORMAL_SHADER;
case DepthMode:
return DEFAULT_DEPTH_SHADER;
case EmissiveMode:
return DEFAULT_EMISSIVE_SHADER;
case OcclusionMode:
return DEFAULT_OCCLUSION_SHADER;
case LightmapMode:
return DEFAULT_LIGHTMAP_SHADER;
case LightingMode:
return DEFAULT_LIGHTING_SHADER;
case ShadowMode:
@ -206,14 +240,14 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Mode mode, std::str
const auto program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding("diffuseMap", Diffuse));
slotBindings.insert(gpu::Shader::Binding("albedoMap", Albedo));
slotBindings.insert(gpu::Shader::Binding("normalMap", Normal));
slotBindings.insert(gpu::Shader::Binding("specularMap", Specular));
slotBindings.insert(gpu::Shader::Binding("depthMap", Depth));
slotBindings.insert(gpu::Shader::Binding("obscuranceMap", AmbientOcclusion));
slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting));
slotBindings.insert(gpu::Shader::Binding("shadowMap", Shadow));
slotBindings.insert(gpu::Shader::Binding("pyramidMap", Pyramid));
slotBindings.insert(gpu::Shader::Binding("occlusionMap", AmbientOcclusion));
slotBindings.insert(gpu::Shader::Binding("occlusionBlurredMap", AmbientOcclusionBlurred));
gpu::Shader::makeProgram(*program, slotBindings);
@ -247,6 +281,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
const auto geometryBuffer = DependencyManager::get<GeometryCache>();
const auto framebufferCache = DependencyManager::get<FramebufferCache>();
const auto textureCache = DependencyManager::get<TextureCache>();
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
glm::mat4 projMat;
@ -262,14 +297,19 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
batch.setPipeline(getPipeline(_mode, first));
batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture());
batch.setResourceTexture(Albedo, framebufferCache->getDeferredColorTexture());
batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture());
batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture());
batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture());
batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture());
batch.setResourceTexture(Shadow, lightStage.lights[0]->shadow.framebuffer->getDepthStencilBuffer());
batch.setResourceTexture(Pyramid, framebufferCache->getDepthPyramidTexture());
batch.setResourceTexture(AmbientOcclusion, framebufferCache->getOcclusionTexture());
if (DependencyManager::get<DeferredLightingEffect>()->isAmbientOcclusionEnabled()) {
batch.setResourceTexture(AmbientOcclusion, framebufferCache->getOcclusionTexture());
} else {
// need to assign the white texture if ao is off
batch.setResourceTexture(AmbientOcclusion, textureCache->getWhiteTexture());
}
batch.setResourceTexture(AmbientOcclusionBlurred, framebufferCache->getOcclusionBlurredTexture());
const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);

View file

@ -47,11 +47,14 @@ protected:
enum Mode : uint8_t {
// Use Mode suffix to avoid collisions
DiffuseMode = 0,
SpecularMode,
RoughnessMode,
DepthMode = 0,
AlbedoMode,
NormalMode,
DepthMode,
RoughnessMode,
MetallicMode,
EmissiveMode,
OcclusionMode,
LightmapMode,
LightingMode,
ShadowMode,
PyramidDepthMode,

View file

@ -12,8 +12,8 @@
<@def DEFERRED_BUFFER_SLH@>
// the diffuse texture
uniform sampler2D diffuseMap;
// the albedo texture
uniform sampler2D albedoMap;
// the normal texture
uniform sampler2D normalMap;
@ -34,8 +34,8 @@ uniform sampler2D lightingMap;
struct DeferredTransform {
mat4 projection;
mat4 viewInverse;
vec4 stereoSide_spareABC;
float stereoSide;
vec3 _spareABC;
};
layout(std140) uniform deferredTransformBuffer {
@ -46,10 +46,10 @@ DeferredTransform getDeferredTransform() {
}
bool getStereoMode(DeferredTransform deferredTransform) {
return (deferredTransform.stereoSide_spareABC.x != 0.0);
return (deferredTransform.stereoSide != 0.0);
}
float getStereoSide(DeferredTransform deferredTransform) {
return (deferredTransform.stereoSide_spareABC.x);
return (deferredTransform.stereoSide);
}
vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, vec2 texcoord) {
@ -64,52 +64,82 @@ vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, v
}
struct DeferredFragment {
float depthVal;
vec4 normalVal;
vec4 diffuseVal;
vec4 specularVal;
vec4 position;
vec3 normal;
float metallic;
vec3 diffuse;
float obscurance;
vec3 specular;
float gloss;
float roughness;
vec3 emissive;
int mode;
float depthVal;
};
const int LIGHT_MAPPED = 1;
DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec2 texcoord) {
DeferredFragment frag;
frag.depthVal = texture(depthMap, texcoord).r;
frag.normalVal = texture(normalMap, texcoord);
frag.diffuseVal = texture(diffuseMap, texcoord);
frag.specularVal = texture(specularMap, texcoord);
frag.obscurance = texture(obscuranceMap, texcoord).x;
vec4 unpackDeferredPosition(DeferredTransform deferredTransform, float depthValue, vec2 texcoord) {
if (getStereoMode(deferredTransform)) {
if (texcoord.x > 0.5) {
texcoord.x -= 0.5;
}
texcoord.x *= 2.0;
}
frag.position = evalEyePositionFromZ(deferredTransform, frag.depthVal, texcoord);
return evalEyePositionFromZ(deferredTransform, depthValue, texcoord);
}
DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {
DeferredFragment frag;
frag.depthVal = -1;
frag.normalVal = texture(normalMap, texcoord);
frag.diffuseVal = texture(albedoMap, texcoord);
frag.specularVal = texture(specularMap, texcoord);
frag.obscurance = texture(obscuranceMap, texcoord).x;
// Unpack the normal from the map
frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0));
frag.mode = 0;
if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
frag.emissive = frag.specularVal.xyz;
if (frag.normalVal.a < 0.5) {
frag.mode = 0;
frag.roughness = 2.0 * frag.normalVal.a;
} else {
frag.mode = LIGHT_MAPPED;
frag.roughness = 2.0 * frag.normalVal.a - 1.0;
}
frag.metallic = frag.diffuseVal.a;
frag.diffuse = frag.diffuseVal.xyz;
frag.specular = frag.specularVal.xyz;
frag.gloss = frag.specularVal.w;
if (frag.metallic <= 0.5) {
frag.metallic = 0.0;
frag.specular = vec3(0.03); // Default Di-electric fresnel value
} else {
frag.specular = vec3(frag.diffuseVal.xyz);
frag.metallic = 1.0;
}
frag.obscurance = min(frag.specularVal.w, frag.obscurance);
return frag;
}
DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec2 texcoord) {
float depthValue = texture(depthMap, texcoord).r;
DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord);
frag.depthVal = depthValue;
frag.position = unpackDeferredPosition(deferredTransform, frag.depthVal, texcoord);
return frag;
}
<@endif@>

View file

@ -40,37 +40,41 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));
}
const vec3 DEFAULT_SPECULAR = vec3(0.1);
const float DEFAULT_ROUGHNESS = 0.9;
const float DEFAULT_SHININESS = 10;
const float DEFAULT_METALLIC = 0;
const vec3 DEFAULT_SPECULAR = vec3(0.1);
const vec3 DEFAULT_EMISSIVE = vec3(0.0);
const float DEFAULT_OCCLUSION = 1.0;
void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion) {
if (alpha != 1.0) {
discard;
}
_fragColor0 = vec4(diffuse.rgb, 1.0); // Opaque
_fragColor1 = vec4(bestFitNormal(normal), 1.0);
_fragColor2 = vec4(specular, shininess / 128.0);
_fragColor0 = vec4(albedo, metallic);
_fragColor1 = vec4(bestFitNormal(normal), 0.5 * clamp(roughness, 0.0, 1.0));
_fragColor2 = vec4(emissive, occlusion);
}
void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) {
void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 emissive) {
if (alpha != 1.0) {
discard;
}
_fragColor0 = vec4(diffuse.rgb, 0.5);
_fragColor1 = vec4(bestFitNormal(normal), 0.5);
_fragColor2 = vec4(emissive, shininess / 128.0);
_fragColor0 = vec4(albedo, metallic);
_fragColor1 = vec4(bestFitNormal(normal), 0.5 + 0.5 * clamp(roughness, 0.0, 1.0));
_fragColor2 = vec4(emissive, 1.0);
}
void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {
if (alpha <= 0.0) {
discard;
}
_fragColor0 = vec4(diffuse.rgb, alpha);
_fragColor0 = vec4(albedo.rgb, alpha);
// _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
// _fragColor2 = vec4(specular, shininess / 128.0);
// _fragColor2 = vec4(fresnel, roughness);
}
<@endif@>

View file

@ -11,109 +11,116 @@
<@if not DEFERRED_GLOBAL_LIGHT_SLH@>
<@def DEFERRED_GLOBAL_LIGHT_SLH@>
<@include model/Light.slh@>
<@include DeferredLighting.slh@>
<@func declareSkyboxMap()@>
// declareSkyboxMap
uniform samplerCube skyboxMap;
vec4 evalSkyboxLight(vec3 direction, float lod) {
// FIXME
//vec4 skytexel = textureLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap));
vec4 skytexel = texture(skyboxMap, direction);
return skytexel;
// textureQueryLevels is not available until #430, so we require explicit lod
// float mipmapLevel = lod * textureQueryLevels(skyboxMap);
return textureLod(skyboxMap, direction, lod);
}
<@endfunc@>
// Everything about light
<@include model/Light.slh@>
<@func prepareGlobalLight()@>
// prepareGlobalLight
// Transform directions to worldspace
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
vec3 fragEyeVector = vec3(invViewMat * vec4(-position, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
// Get light
Light light = getLight();
vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
if (metallic > 0.5) {
fresnel = albedo;
metallic = 1.0;
}
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, fresnel, roughness);
vec3 color = vec3(albedo * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light);
color += emissive;
<@endfunc@>
<@func declareAmbientFresnel()@>
vec3 fresnelSchlickAmbient(vec3 fresnelColor, vec3 lightDir, vec3 halfDir, float gloss) {
return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * pow(1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0), 5);
}
<@endfunc@>
<@func declareEvalAmbientGlobalColor()@>
vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Need the light now
Light light = getLight();
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec3 color = diffuse.rgb * getLightColor(light) * obscurance * getLightAmbientIntensity(light);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
color += vec3(diffuse * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light);
vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) {
<$prepareGlobalLight()$>
color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(light);
return color;
}
<@endfunc@>
<@func declareEvalAmbientSphereGlobalColor()@>
<$declareAmbientFresnel()$>
vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Need the light now
Light light = getLight();
vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0)));
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec3 ambientNormal = fragNormal.xyz;
vec3 color = diffuse.rgb * evalSphericalLight(getLightAmbientSphere(light), ambientNormal).xyz * obscurance * getLightAmbientIntensity(light);
vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) {
<$prepareGlobalLight()$>
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
// Diffuse from ambient
color += (1 - metallic) * albedo * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light);
color += vec3(diffuse * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light);
// Specular highlight from ambient
vec3 direction = -reflect(fragEyeDir, fragNormal);
vec3 skyboxLight = evalSphericalLight(getLightAmbientSphere(light), direction).xyz;
vec3 ambientFresnel = fresnelSchlickAmbient(fresnel, fragEyeDir, fragNormal, 1 - roughness);
color += ambientFresnel * skyboxLight.rgb * obscurance * getLightAmbientIntensity(light);
return color;
}
<@endfunc@>
<@func declareEvalSkyboxGlobalColor()@>
<$declareSkyboxMap()$>
<$declareAmbientFresnel()$>
vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Need the light now
Light light = getLight();
vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0)));
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec3 color = diffuse.rgb * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light);
vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) {
<$prepareGlobalLight()$>
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
// Diffuse from ambient
color += (1 - metallic) * albedo * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light);
color += vec3(diffuse * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light);
// Specular highlight from ambient
vec3 direction = -reflect(fragEyeDir, fragNormal);
float levels = getLightAmbientMapNumMips(light);
float lod = min(floor((roughness) * levels), levels);
vec4 skyboxLight = evalSkyboxLight(direction, lod);
vec3 ambientFresnel = fresnelSchlickAmbient(fresnel, fragEyeDir, fragNormal, 1 - roughness);
color += ambientFresnel * skyboxLight.rgb * obscurance * getLightAmbientIntensity(light);
return color;
}
<@endfunc@>
<@func declareEvalLightmappedColor()@>
vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 diffuse, vec3 lightmap) {
vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {
Light light = getLight();
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
float diffuseDot = dot(fragNormal, -getLightDirection(light));
// need to catch normals perpendicular to the projection plane hence the magic number for the threshold
// it should be just 0, but we have innacurracy so we need to overshoot
// Catch normals perpendicular to the projection plane, hence the magic number for the threshold
// It should be just 0, but we have inaccuracy so we overshoot
const float PERPENDICULAR_THRESHOLD = -0.005;
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace
float diffuseDot = dot(fragNormal, -getLightDirection(light));
float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot);
//float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot);
// evaluate the shadow test but only relevant for light facing fragments
// Reevaluate the shadow attenuation for light facing fragments
float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation;
// diffuse light is the lightmap dimmed by shadow
// Diffuse light is the lightmap dimmed by shadow
vec3 diffuseLight = lightAttenuation * lightmap;
// ambient is a tiny percentage of the lightmap and only when in the shadow
// Ambient light is the lightmap when in shadow
vec3 ambientLight = (1 - lightAttenuation) * lightmap * getLightAmbientIntensity(light);
return obscurance * diffuse * (ambientLight + diffuseLight);
return obscurance * albedo * (diffuseLight + ambientLight);
}
<@endfunc@>

View file

@ -13,41 +13,55 @@
<@func declareEvalPBRShading()@>
vec3 fresnelSchlick(vec3 fresnelColor, vec3 lightDir, vec3 halfDir) {
return fresnelColor + (1.0 - fresnelColor) * pow(1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0), 5);
}
float specularDistribution(float roughness, vec3 normal, vec3 halfDir) {
float ndoth = clamp(dot(halfDir, normal), 0.0, 1.0);
float gloss2 = pow(0.001 + roughness, 4);
float denom = (ndoth * ndoth*(gloss2 - 1) + 1);
float power = gloss2 / (3.14159 * denom * denom);
return power;
}
<! //NOTE: ANother implementation for specularDistribution
float specularDistribution(float roughness, vec3 normal, vec3 halfDir) {
float gloss = exp2(10 * (1.0 - roughness) + 1);
float power = pow(clamp(dot(halfDir, normal), 0.0, 1.0), gloss);
power *= (gloss * 0.125 + 0.25);
return power;
}
!>
// Frag Shading returns the diffuse amount as W and the specular rgb as xyz
vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float roughness) {
// Diffuse Lighting
float diffuseDot = dot(fragNormal, fragLightDir);
float facingLight = step(0.0, diffuseDot);
float diffuse = diffuseDot * facingLight;
// Specular Lighting depends on the half vector and the gloss
float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0);
// Specular Lighting
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
vec3 fresnelColor = fresnelSchlick(fresnel, fragLightDir,halfDir);
float power = specularDistribution(roughness, fragNormal, halfDir);
vec3 specular = power * fresnelColor * diffuse;
float specularPower = pow(max(0.0, dot(halfDir, fragNormal)), gloss * 128.0);
specularPower *= (gloss * 128.0 * 0.125 + 0.25);
float shlickPower = (1.0 - dot(fragLightDir,halfDir));
float shlickPower2 = shlickPower * shlickPower;
float shlickPower5 = shlickPower2 * shlickPower2 * shlickPower;
vec3 fresnel = specular * (1.0 - shlickPower5) + vec3(shlickPower5);
vec3 reflect = specularPower * fresnel * diffuse;
return vec4(reflect, diffuse * (1 - fresnel.x));
return vec4(specular, (1.0 - metallic) * diffuse * (1 - fresnelColor.x));
}
<@endfunc@>
<@func declareEvalBlinnRShading()@>
vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float roughness) {
// Diffuse Lighting
float diffuseDot = dot(fragNormal, fragLightDir);
float facingLight = step(0.0, diffuseDot);
float diffuse = diffuseDot * facingLight;
// Specular Lighting depends on the half vector and the gloss
// Specular Lighting depends on the half vector and the roughness
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss * 128.0);
float gloss = (1.0 - roughness) * 128.0;
glos *= gloss;
float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss);
vec3 reflect = specularPower * specular * diffuse;
return vec4(reflect, diffuse);
@ -59,8 +73,8 @@ vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3
<$declareEvalPBRShading()$>
// Return xyz the specular/reflection component and w the diffuse component
vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss);
vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 specular, float roughness) {
return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, specular, roughness);
}
<@endif@>

View file

@ -92,6 +92,11 @@ void DeferredLightingEffect::init() {
// Add the global light to the light stage (for later shadow rendering)
_lightStage.addLight(lp);
lp->setDirection(glm::vec3(-1.0f));
lp->setColor(glm::vec3(1.0f));
lp->setIntensity(1.0f);
lp->setType(model::Light::SUN);
lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE);
}
void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color,
@ -311,22 +316,23 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
{
auto& program = _shadowMapEnabled ? _directionalLightShadow : _directionalLight;
LightLocationsPtr locations = _shadowMapEnabled ? _directionalLightShadowLocations : _directionalLightLocations;
const auto& keyLight = _allocatedLights[_globalLights.front()];
// Setup the global directional pass pipeline
{
if (_shadowMapEnabled) {
if (_skyboxTexture) {
if (keyLight->getAmbientMap()) {
program = _directionalSkyboxLightShadow;
locations = _directionalSkyboxLightShadowLocations;
} else if (_ambientLightMode > -1) {
} else {
program = _directionalAmbientSphereLightShadow;
locations = _directionalAmbientSphereLightShadowLocations;
}
} else {
if (_skyboxTexture) {
if (keyLight->getAmbientMap()) {
program = _directionalSkyboxLight;
locations = _directionalSkyboxLightLocations;
} else if (_ambientLightMode > -1) {
} else {
program = _directionalAmbientSphereLight;
locations = _directionalAmbientSphereLightLocations;
}
@ -351,7 +357,7 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
geometryCache->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);
}
if (_skyboxTexture) {
if (keyLight->getAmbientMap()) {
batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr);
}
}
@ -490,14 +496,14 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int skyboxCubemapUnit) {
PerformanceTimer perfTimer("DLE->setupBatch()");
auto globalLight = _allocatedLights[_globalLights.front()];
auto keyLight = _allocatedLights[_globalLights.front()];
if (lightBufferUnit >= 0) {
batch.setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());
batch.setUniformBuffer(lightBufferUnit, keyLight->getSchemaBuffer());
}
if (_skyboxTexture && (skyboxCubemapUnit >= 0)) {
batch.setResourceTexture(skyboxCubemapUnit, _skyboxTexture);
if (keyLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) {
batch.setResourceTexture(skyboxCubemapUnit, keyLight->getAmbientMap());
}
}
@ -508,7 +514,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), DEFERRED_BUFFER_COLOR_UNIT));
slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), DEFERRED_BUFFER_COLOR_UNIT));
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), DEFERRED_BUFFER_NORMAL_UNIT));
slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), DEFERRED_BUFFER_EMISSIVE_UNIT));
slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), DEFERRED_BUFFER_DEPTH_UNIT));
@ -556,15 +562,14 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
}
void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light, const gpu::TexturePointer& skyboxTexture) {
void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) {
auto globalLight = _allocatedLights.front();
globalLight->setDirection(light->getDirection());
globalLight->setColor(light->getColor());
globalLight->setIntensity(light->getIntensity());
globalLight->setAmbientIntensity(light->getAmbientIntensity());
globalLight->setAmbientSphere(light->getAmbientSphere());
_skyboxTexture = skyboxTexture;
globalLight->setAmbientMap(light->getAmbientMap());
}
model::MeshPointer DeferredLightingEffect::getSpotLightMesh() {

View file

@ -49,11 +49,12 @@ public:
void setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int skyboxCubemapUnit);
// update global lighting
void setGlobalLight(const model::LightPointer& light, const gpu::TexturePointer& skyboxTexture);
void setGlobalLight(const model::LightPointer& light);
const LightStage& getLightStage() { return _lightStage; }
void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; };
void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; }
bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; }
private:
DeferredLightingEffect() = default;
@ -95,15 +96,12 @@ private:
std::vector<int> _pointLights;
std::vector<int> _spotLights;
int _ambientLightMode = 0;
gpu::TexturePointer _skyboxTexture;
// Class describing the uniform buffer with all the parameters common to the deferred shaders
class DeferredTransform {
public:
glm::mat4 projection;
glm::mat4 viewInverse;
float stereoSide{ 0.f };
float stereoSide { 0.f };
float spareA, spareB, spareC;
DeferredTransform() {}

View file

@ -506,7 +506,7 @@ GeometryCache::GeometryCache() :
std::make_shared<render::ShapePipeline>(getSimplePipeline(), nullptr,
[](const render::ShapePipeline&, gpu::Batch& batch) {
// Set the defaults needed for a simple program
batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP,
batch.setResourceTexture(render::ShapePipeline::Slot::ALBEDO_MAP,
DependencyManager::get<TextureCache>()->getWhiteTexture());
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
@ -1734,9 +1734,9 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) {
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool emissive, bool depthBiased) {
batch.setPipeline(getSimplePipeline(textured, culled, emissive, depthBiased));
// If not textured, set a default diffuse map
// If not textured, set a default albedo map
if (!textured) {
batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP,
batch.setResourceTexture(render::ShapePipeline::Slot::ALBEDO_MAP,
DependencyManager::get<TextureCache>()->getWhiteTexture());
}
// Set a default normal map

View file

@ -0,0 +1,139 @@
<!
// MaterialTextures.slh
// fragment shader
//
// Created by Sam Gateau on 2/22/16
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
!>
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
<@def MODEL_MATERIAL_TEXTURES_SLH@>
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion)@>
<@if withAlbedo@>
uniform sampler2D albedoMap;
vec4 fetchAlbedoMap(vec2 uv) {
return texture(albedoMap, uv);
}
<@endif@>
<@if withRoughness@>
uniform sampler2D roughnessMap;
float fetchRoughnessMap(vec2 uv) {
return (texture(roughnessMap, uv).r);
}
<@endif@>
<@if withNormal@>
uniform sampler2D normalMap;
vec3 fetchNormalMap(vec2 uv) {
return texture(normalMap, uv).xyz;
}
<@endif@>
<@if withMetallic@>
uniform sampler2D metallicMap;
float fetchMetallicMap(vec2 uv) {
return (texture(metallicMap, uv).r);
}
<@endif@>
<@if withEmissive@>
uniform sampler2D emissiveMap;
vec3 fetchEmissiveMap(vec2 uv) {
return texture(emissiveMap, uv).rgb;
}
<@endif@>
<@if withOcclusion@>
uniform sampler2D occlusionMap;
float fetchOcclusionMap(vec2 uv) {
return texture(occlusionMap, uv).r;
}
<@endif@>
<@endfunc@>
<@func fetchMaterialTextures(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, occlusion)@>
<@if albedo@>
vec4 <$albedo$> = (((<$matKey$> & ALBEDO_MAP_BIT) != 0) ? fetchAlbedoMap(<$texcoord0$>) : vec4(1.0));
<@endif@>
<@if roughness@>
float <$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(<$texcoord0$>) : 1.0);
<@endif@>
<@if normal@>
vec3 <$normal$> = (((<$matKey$> & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(<$texcoord0$>) : vec3(0.0, 1.0, 0.0));
<@endif@>
<@if metallic@>
float <$metallic$> = (((<$matKey$> & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(<$texcoord0$>) : 0.0);
<@endif@>
<@if emissive@>
vec3 <$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(<$texcoord0$>) : vec3(0.0));
<@endif@>
<@if occlusion@>
float <$occlusion$> = (((<$matKey$> & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(<$texcoord0$>) : 1.0);
<@endif@>
<@endfunc@>
<@func declareMaterialLightmap()@>
uniform sampler2D emissiveMap;
uniform vec2 emissiveParams;
vec3 fetchLightmapMap(vec2 uv) {
return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);
}
<@endfunc@>
<@func fetchMaterialLightmap(texcoord1, lightmapVal)@>
vec3 <$lightmapVal$> = fetchLightmapMap(<$texcoord1$>);
<@endfunc@>
<@func tangentToViewSpace(fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@>
{
vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz);
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
vec3 localNormal = normalize(<$fetchedNormal$> - vec3(0.5, 0.5, 0.5));
<$normal$> = vec3(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z);
}
<@endfunc@>
<@func evalMaterialAlbedo(fetchedAlbedo, materialAlbedo, matKey, albedo)@>
{
<$albedo$>.xyz = (((<$matKey$> & ALBEDO_VAL_BIT) != 0) ? <$materialAlbedo$> : vec3(1.0));
if (((<$matKey$> & ALBEDO_MAP_BIT) != 0)) {
<$albedo$>.xyz *= <$fetchedAlbedo$>.xyz;
}
}
<@endfunc@>
<@func evalMaterialRoughness(fetchedRoughness, materialRoughness, matKey, roughness)@>
{
<$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? <$fetchedRoughness$> : <$materialRoughness$>);
}
<@endfunc@>
<@func evalMaterialMetallic(fetchedMetallic, materialMetallic, matKey, metallic)@>
{
<$metallic$> = (((<$matKey$> & METALLIC_MAP_BIT) != 0) ? <$fetchedMetallic$> : <$materialMetallic$>);
}
<@endfunc@>
<@func evalMaterialEmissive(fetchedEmissive, materialEmissive, matKey, emissive)@>
{
<$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? <$fetchedEmissive$> : <$materialEmissive$>);
}
<@endfunc@>
<@func evalMaterialOcclusion(fetchedOcclusion, matKey, occlusion)@>
{
<$occlusion$> = <$fetchedOcclusion$>;
}
<@endfunc@>
<@endif@>

View file

@ -106,7 +106,7 @@ ShapeKey MeshPartPayload::getShapeKey() const {
if (drawMaterialKey.isNormalMap()) {
builder.withTangents();
}
if (drawMaterialKey.isGlossMap()) {
if (drawMaterialKey.isMetallicMap()) {
builder.withSpecular();
}
if (drawMaterialKey.isLightmapMap()) {
@ -145,20 +145,34 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
auto textureMaps = _drawMaterial->getTextureMaps();
glm::mat4 texcoordTransform[2];
// Diffuse
if (materialKey.isDiffuseMap()) {
auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP];
if (diffuseMap && diffuseMap->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, diffuseMap->getTextureView());
// Albedo
if (materialKey.isAlbedoMap()) {
auto albedoMap = textureMaps[model::MaterialKey::ALBEDO_MAP];
if (albedoMap && albedoMap->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO_MAP, albedoMap->getTextureView());
if (!diffuseMap->getTextureTransform().isIdentity()) {
diffuseMap->getTextureTransform().getMatrix(texcoordTransform[0]);
if (!albedoMap->getTextureTransform().isIdentity()) {
albedoMap->getTextureTransform().getMatrix(texcoordTransform[0]);
}
} else {
batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getGrayTexture());
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO_MAP, textureCache->getGrayTexture());
}
} else {
batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getWhiteTexture());
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO_MAP, textureCache->getWhiteTexture());
}
// Roughness map
if (materialKey.isRoughnessMap()) {
auto roughnessMap = textureMaps[model::MaterialKey::ROUGHNESS_MAP];
if (roughnessMap && roughnessMap->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::ROUGHNESS_MAP, roughnessMap->getTextureView());
// texcoord are assumed to be the same has albedo
} else {
batch.setResourceTexture(ShapePipeline::Slot::ROUGHNESS_MAP, textureCache->getWhiteTexture());
}
} else {
batch.setResourceTexture(ShapePipeline::Slot::ROUGHNESS_MAP, textureCache->getWhiteTexture());
}
// Normal map
@ -167,7 +181,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
if (normalMap && normalMap->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, normalMap->getTextureView());
// texcoord are assumed to be the same has diffuse
// texcoord are assumed to be the same has albedo
} else {
batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, textureCache->getBlueTexture());
}
@ -175,26 +189,40 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, nullptr);
}
// TODO: For now gloss map is used as the "specular map in the shading, we ll need to fix that
if (materialKey.isGlossMap()) {
auto specularMap = textureMaps[model::MaterialKey::GLOSS_MAP];
// Metallic map
if (materialKey.isMetallicMap()) {
auto specularMap = textureMaps[model::MaterialKey::METALLIC_MAP];
if (specularMap && specularMap->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, specularMap->getTextureView());
batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, specularMap->getTextureView());
// texcoord are assumed to be the same has diffuse
// texcoord are assumed to be the same has albedo
} else {
batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, textureCache->getBlackTexture());
batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, textureCache->getBlackTexture());
}
} else {
batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, nullptr);
batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, nullptr);
}
// TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too
// Occlusion map
if (materialKey.isOcclusionMap()) {
auto specularMap = textureMaps[model::MaterialKey::OCCLUSION_MAP];
if (specularMap && specularMap->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, specularMap->getTextureView());
// texcoord are assumed to be the same has albedo
} else {
batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, textureCache->getWhiteTexture());
}
} else {
batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, nullptr);
}
// Emissive / Lightmap
if (materialKey.isLightmapMap()) {
auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP];
if (lightmapMap && lightmapMap->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, lightmapMap->getTextureView());
batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, lightmapMap->getTextureView());
auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale();
batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y);
@ -203,10 +231,18 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]);
}
} else {
batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, textureCache->getGrayTexture());
batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, textureCache->getGrayTexture());
}
} else if (materialKey.isEmissiveMap()) {
auto emissiveMap = textureMaps[model::MaterialKey::EMISSIVE_MAP];
if (emissiveMap && emissiveMap->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, emissiveMap->getTextureView());
} else {
batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, textureCache->getBlackTexture());
}
} else {
batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, nullptr);
batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, nullptr);
}
// Texcoord transforms ?
@ -378,7 +414,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
bool isTranslucent = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap();
bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty();
bool hasSpecular = drawMaterialKey.isGlossMap();
bool hasSpecular = drawMaterialKey.isMetallicMap();
bool hasLightmap = drawMaterialKey.isLightmapMap();
bool isSkinned = _isSkinned;

View file

@ -1205,9 +1205,9 @@ void Model::segregateMeshGroups() {
if (showingCollisionHull) {
if (!_collisionHullMaterial) {
_collisionHullMaterial = std::make_shared<model::Material>();
_collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f));
_collisionHullMaterial->setAlbedo(glm::vec3(1.0f, 0.5f, 0.0f));
_collisionHullMaterial->setMetallic(0.02f);
_collisionHullMaterial->setGloss(1.0f);
_collisionHullMaterial->setRoughness(0.5f);
}
_renderItemsSet << std::make_shared<MeshPartPayload>(networkMesh._mesh, partIndex, _collisionHullMaterial, transform, offset);
} else {

View file

@ -66,16 +66,16 @@ void initStencilPipeline(gpu::PipelinePointer& pipeline) {
gpu::BufferView getDefaultMaterialBuffer() {
model::Material::Schema schema;
schema._diffuse = vec3(1.0f);
schema._albedo = vec3(1.0f);
schema._opacity = 1.0f;
schema._metallic = vec3(0.1f);
schema._gloss = 10.0f;
schema._metallic = 0.1f;
schema._roughness = 0.9f;
return gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(model::Material::Schema), (const gpu::Byte*) &schema));
}
void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
// Set a default diffuse map
batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP,
// Set a default albedo map
batch.setResourceTexture(render::ShapePipeline::Slot::ALBEDO_MAP,
DependencyManager::get<TextureCache>()->getWhiteTexture());
// Set a default normal map
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,

View file

@ -16,7 +16,7 @@
out vec4 _color;
void main(void) {
// pass along the diffuse color
// pass along the color
_color = colorToLinearRGBA(inColor.rgba);
TransformCamera cam = getTransformCamera();

View file

@ -44,8 +44,9 @@ void main(void) {
frag.position.xyz,
frag.normal,
frag.diffuse,
frag.specular,
frag.gloss);
frag.metallic,
frag.emissive,
frag.roughness);
_fragColor = vec4(color, frag.normalVal.a);
}
}

View file

@ -46,8 +46,9 @@ void main(void) {
frag.position.xyz,
frag.normal,
frag.diffuse,
frag.specular,
frag.gloss);
frag.metallic,
frag.emissive,
frag.roughness);
_fragColor = vec4(color, frag.normalVal.a);
}
}

View file

@ -45,8 +45,9 @@ void main(void) {
frag.position.xyz,
frag.normal,
frag.diffuse,
frag.specular,
frag.gloss);
frag.metallic,
frag.emissive,
frag.roughness);
_fragColor = vec4(color, frag.normalVal.a);
}
}

View file

@ -47,8 +47,9 @@ void main(void) {
frag.position.xyz,
frag.normal,
frag.diffuse,
frag.specular,
frag.gloss);
frag.metallic,
frag.emissive,
frag.roughness);
_fragColor = vec4(color, frag.normalVal.a);
}
}

View file

@ -45,8 +45,9 @@ void main(void) {
frag.position.xyz,
frag.normal,
frag.diffuse,
frag.specular,
frag.gloss);
frag.metallic,
frag.emissive,
frag.roughness);
_fragColor = vec4(color, frag.normalVal.a);
}

View file

@ -47,8 +47,9 @@ void main(void) {
frag.position.xyz,
frag.normal,
frag.diffuse,
frag.specular,
frag.gloss);
frag.metallic,
frag.emissive,
frag.roughness);
_fragColor = vec4(color, frag.normalVal.a);
}

View file

@ -15,8 +15,8 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D diffuseMap;
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
in vec4 _position;
in vec3 _normal;
@ -25,15 +25,26 @@ in vec2 _texCoord0;
void main(void) {
// Fetch diffuse map
vec4 diffuse = texture(diffuseMap, _texCoord0);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
<$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$>
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
float roughness = getMaterialRoughness(mat);
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
packDeferredFragment(
normalize(_normal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a),
getMaterialDiffuse(mat) * diffuse.rgb * _color,
getMaterialSpecular(mat),
getMaterialShininess(mat));
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a),
albedo,
roughness,
getMaterialMetallic(mat),
emissive,
occlusionTex);
}

View file

@ -15,7 +15,7 @@
<@include DeferredBufferWrite.slh@>
<@include model/Material.slh@>
uniform sampler2D diffuseMap;
uniform sampler2D albedoMap;
in vec2 _texCoord0;
in vec3 _normal;
@ -23,16 +23,17 @@ in vec3 _color;
in float _alpha;
void main(void) {
vec4 texel = texture(diffuseMap, _texCoord0);
vec4 texel = texture(albedoMap, _texCoord0);
Material mat = getMaterial();
vec3 fragColor = getMaterialDiffuse(mat) * texel.rgb * _color;
vec3 fragColor = getMaterialAlbedo(mat) * texel.rgb * _color;
packDeferredFragmentLightmap(
normalize(_normal),
texel.a,
vec3(1.0),
getMaterialSpecular(mat),
getMaterialShininess(mat),
getMaterialRoughness(mat),
getMaterialMetallic(mat),
getMaterialFresnel(mat),
fragColor);
}

View file

@ -16,12 +16,9 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D diffuseMap;
// the emissive map texture and parameters
uniform sampler2D emissiveMap;
uniform vec2 emissiveParams;
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS)$>
<$declareMaterialLightmap()$>
in vec4 _position;
in vec2 _texCoord0;
@ -30,16 +27,18 @@ in vec3 _normal;
in vec3 _color;
void main(void) {
vec4 diffuse = texture(diffuseMap, _texCoord0);
vec4 emissive = texture(emissiveMap, _texCoord1);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
<$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness)$>
<$fetchMaterialLightmap(_texCoord1, emissive)$>
packDeferredFragmentLightmap(
normalize(_normal),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a),
getMaterialDiffuse(mat) * diffuse.rgb * _color,
getMaterialSpecular(mat),
getMaterialShininess(mat),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat),
getMaterialFresnel(mat),
(vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb));
}

View file

@ -28,7 +28,7 @@ out vec3 _normal;
out vec3 _color;
void main(void) {
// pass along the diffuse color in linear space
// pass along the color in linear space
_color = colorToLinearRGB(inColor.xyz);
// and the texture coordinates

View file

@ -16,15 +16,9 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D diffuseMap;
// the normal map texture
uniform sampler2D normalMap;
// the emissive map texture and parameters
uniform sampler2D emissiveMap;
uniform vec2 emissiveParams;
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$>
<$declareMaterialLightmap()$>
in vec4 _position;
in vec2 _texCoord0;
@ -34,25 +28,20 @@ in vec3 _tangent;
in vec3 _color;
void main(void) {
// 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 diffuse = texture(diffuseMap, _texCoord0);
vec4 emissive = texture(emissiveMap, _texCoord1);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
<$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, normalTexel)$>
<$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
vec3 viewNormal;
<$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$>
packDeferredFragmentLightmap(
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a),
getMaterialDiffuse(mat) * diffuse.rgb * _color,
getMaterialSpecular(mat),
getMaterialShininess(mat),
(vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb));
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat),
getMaterialMetallic(mat),
getMaterialFresnel(mat),
lightmapVal);
}

View file

@ -29,7 +29,7 @@ out vec3 _tangent;
out vec3 _color;
void main(void) {
// pass along the diffuse color in linear space
// pass along the color in linear space
_color = colorToLinearRGB(inColor.xyz);
// and the texture coordinates

View file

@ -16,18 +16,9 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D diffuseMap;
// the emissive map texture and parameters
uniform sampler2D emissiveMap;
uniform vec2 emissiveParams;
// the normal map texture
uniform sampler2D normalMap;
// the specular map texture
uniform sampler2D specularMap;
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$>
<$declareMaterialLightmap()$>
in vec4 _position;
in vec2 _texCoord0;
@ -37,26 +28,20 @@ in vec3 _tangent;
in vec3 _color;
void main(void) {
// 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 diffuse = texture(diffuseMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
vec4 emissive = texture(emissiveMap, _texCoord1);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
<$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
<$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
vec3 viewNormal;
<$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$>
packDeferredFragmentLightmap(
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a),
getMaterialDiffuse(mat) * diffuse.rgb * _color,
specular, // no use of getMaterialSpecular(mat)
getMaterialShininess(mat),
(vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb));
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat) * metallicTex,
/*specular, // no use of */ getMaterialFresnel(mat),
lightmapVal);
}

View file

@ -16,15 +16,9 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D diffuseMap;
// the emissive map texture and parameters
uniform sampler2D emissiveMap;
uniform vec2 emissiveParams;
// the specular texture
uniform sampler2D specularMap;
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$>
<$declareMaterialLightmap()$>
in vec4 _position;
in vec2 _texCoord0;
@ -33,18 +27,17 @@ in vec3 _normal;
in vec3 _color;
void main(void) {
// set the diffuse, normal, specular data
vec4 diffuse = texture(diffuseMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
vec4 emissive = texture(emissiveMap, _texCoord1);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
<$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$>
<$fetchMaterialLightmap(_texCoord1, lightmapVal)$>
packDeferredFragmentLightmap(
normalize(_normal),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a),
getMaterialDiffuse(mat) * diffuse.rgb * _color,
specular, // no use of getMaterialSpecular(mat)
getMaterialShininess(mat),
(vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb));
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat) * metallicTex,
/*metallicTex, // no use of */getMaterialFresnel(mat),
lightmapVal);
}

View file

@ -16,11 +16,8 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D diffuseMap;
// the normal map texture
uniform sampler2D normalMap;
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
in vec4 _position;
in vec2 _texCoord0;
@ -29,22 +26,29 @@ in vec3 _tangent;
in vec3 _color;
void main(void) {
// compute the view normal from the various bits
vec3 normalizedNormal = normalize(_normal.xyz);
vec3 normalizedTangent = normalize(_tangent.xyz);
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
vec3 localNormal = normalize(vec3(texture(normalMap, _texCoord0.st)) - vec3(0.5, 0.5, 0.5));
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
vec4 diffuse = texture(diffuseMap, _texCoord0.st);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
<$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, occlusionTex)$>
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
float roughness = getMaterialRoughness(mat);
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 viewNormal;
<$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$>
packDeferredFragment(
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a),
getMaterialDiffuse(mat) * diffuse.rgb * _color,
getMaterialSpecular(mat),
getMaterialShininess(mat));
viewNormal,
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a),
albedo,
roughness,
getMaterialMetallic(mat),
emissive,
occlusionTex);
}

View file

@ -28,7 +28,7 @@ out vec3 _tangent;
out vec3 _color;
void main(void) {
// pass along the diffuse color
// pass along the color
_color = colorToLinearRGB(inColor.xyz);
// and the texture coordinates

View file

@ -16,14 +16,8 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D diffuseMap;
// the normal map texture
uniform sampler2D normalMap;
// the specular map texture
uniform sampler2D specularMap;
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
in vec4 _position;
in vec2 _texCoord0;
@ -32,24 +26,33 @@ in vec3 _tangent;
in vec3 _color;
void main(void) {
// compute the view normal from the various bits
vec3 normalizedNormal = normalize(_normal);
vec3 normalizedTangent = normalize(_tangent);
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
vec3 localNormal = normalize(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 diffuse = texture(diffuseMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
<$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, occlusionTex)$>
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
float roughness = getMaterialRoughness(mat);
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 viewNormal;
<$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$>
float metallic = getMaterialMetallic(mat);
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
packDeferredFragment(
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a),
getMaterialDiffuse(mat) * diffuse.rgb * _color,
specular, //getMaterialSpecular(mat),
getMaterialShininess(mat));
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a),
albedo,
roughness,
metallic,
emissive,
occlusionTex);
}

View file

@ -16,11 +16,8 @@
<@include model/Material.slh@>
// the diffuse texture
uniform sampler2D diffuseMap;
// the specular texture
uniform sampler2D specularMap;
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
in vec4 _position;
in vec2 _texCoord0;
@ -29,16 +26,29 @@ in vec3 _color;
void main(void) {
// set the diffuse, normal, specular data
vec4 diffuse = texture(diffuseMap, _texCoord0);
vec3 specular = texture(specularMap, _texCoord0).rgb;
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
<$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, occlusionTex)$>
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
float roughness = getMaterialRoughness(mat);
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
float metallic = getMaterialMetallic(mat);
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
packDeferredFragment(
normalize(_normal),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a),
getMaterialDiffuse(mat) * diffuse.rgb * _color,
specular, //getMaterialSpecular(mat),
getMaterialShininess(mat));
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a),
albedo,
roughness,
metallic,
emissive,
occlusionTex);
}

View file

@ -20,9 +20,7 @@
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
uniform sampler2D diffuseMap;
uniform sampler2D albedoMap;
in vec2 _texCoord0;
in vec4 _position;
@ -33,15 +31,16 @@ in float _alpha;
out vec4 _fragColor;
void main(void) {
vec4 diffuse = texture(diffuseMap, _texCoord0);
vec4 albedo = texture(albedoMap, _texCoord0);
Material mat = getMaterial();
vec3 fragPosition = _position.xyz;
vec3 fragNormal = normalize(_normal);
vec3 fragDiffuse = getMaterialDiffuse(mat) * diffuse.rgb * _color;
vec3 fragSpecular = getMaterialSpecular(mat);
float fragGloss = getMaterialShininess(mat) / 128;
float fragOpacity = getMaterialOpacity(mat) * diffuse.a * _alpha;
vec3 fragAlbedo = getMaterialAlbedo(mat) * albedo.rgb * _color;
float fragMetallic = getMaterialMetallic(mat);
vec3 fragEmissive = getMaterialEmissive(mat);
float fragRoughness = getMaterialRoughness(mat);
float fragOpacity = getMaterialOpacity(mat) * albedo.a * _alpha;
TransformCamera cam = getTransformCamera();
@ -51,8 +50,9 @@ void main(void) {
1.0,
fragPosition,
fragNormal,
fragDiffuse,
fragSpecular,
fragGloss),
fragAlbedo,
fragMetallic,
fragEmissive,
fragRoughness),
fragOpacity);
}

View file

@ -14,7 +14,7 @@
<@include model/Material.slh@>
uniform sampler2D diffuseMap;
uniform sampler2D albedoMap;
in vec2 _texCoord0;
in vec3 _color;
@ -23,11 +23,11 @@ in float _alpha;
out vec4 _fragColor;
void main(void) {
vec4 diffuse = texture(diffuseMap, _texCoord0);
vec4 albedo = texture(albedoMap, _texCoord0);
Material mat = getMaterial();
vec3 fragColor = getMaterialDiffuse(mat) * diffuse.rgb * _color;
float fragOpacity = getMaterialOpacity(mat) * diffuse.a * _alpha;
vec3 fragColor = getMaterialAlbedo(mat) * albedo.rgb * _color;
float fragOpacity = getMaterialOpacity(mat) * albedo.a * _alpha;
_fragColor = vec4(fragColor, fragOpacity);
}

View file

@ -17,7 +17,7 @@
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss, float opacity) {
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 specular, float roughness, float opacity) {
// Need the light now
Light light = getLight();
@ -28,11 +28,11 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 d
vec3 fragEyeDir;
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
vec3 color = opacity * diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light);
vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(light);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, specular, roughness);
color += vec3(diffuse * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
color += vec3(albedo * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
return vec4(color, opacity);
}
@ -48,14 +48,15 @@ in float _alpha;
out vec4 _fragColor;
void main(void) {
vec4 diffuse = texture(originalTexture, _texCoord0);
vec4 albedo = texture(originalTexture, _texCoord0);
vec3 fragPosition = _position.xyz;
vec3 fragNormal = normalize(_normal);
vec3 fragDiffuse = diffuse.rgb * _color;
vec3 fragAlbedo = albedo.rgb * _color;
float fragMetallic = 0.0;
vec3 fragSpecular = vec3(0.1);
float fragGloss = 10.0 / 128.0;
float fragOpacity = diffuse.a;
float fragRoughness = 0.9;
float fragOpacity = albedo.a;
if (fragOpacity <= 0.1) {
discard;
@ -64,9 +65,10 @@ void main(void) {
vec4 color = evalGlobalColor(1.0,
fragPosition,
fragNormal,
fragDiffuse,
fragAlbedo,
fragMetallic,
fragSpecular,
fragGloss,
fragRoughness,
fragOpacity);
// Apply standard tone mapping

View file

@ -20,12 +20,12 @@ in vec3 _color;
out vec4 _fragColor;
void main(void) {
vec4 diffuse = texture(originalTexture, _texCoord0);
vec4 albedo = texture(originalTexture, _texCoord0);
if (diffuse.a <= 0.1) {
if (albedo.a <= 0.1) {
discard;
}
vec4 color = vec4(diffuse.rgb * _color, diffuse.a);
vec4 color = vec4(albedo.rgb * _color, albedo.a);
// Apply standard tone mapping
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);

View file

@ -18,7 +18,7 @@
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss, float opacity) {
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 specular, float roughness, float opacity) {
// Need the light now
Light light = getLight();
@ -29,11 +29,11 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 d
vec3 fragEyeDir;
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
vec3 color = opacity * diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light);
vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(light);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, specular, roughness);
color += vec3(diffuse * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
color += vec3(albedo * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
return vec4(color, opacity);
}
@ -49,21 +49,23 @@ in float _alpha;
out vec4 _fragColor;
void main(void) {
vec4 diffuse = texture(originalTexture, _texCoord0);
vec4 albedo = texture(originalTexture, _texCoord0);
vec3 fragPosition = _position.xyz;
vec3 fragNormal = normalize(_normal);
vec3 fragDiffuse = diffuse.rgb * _color;
vec3 fragAlbedo = albedo.rgb * _color;
float fragMetallic = 0.0;
vec3 fragSpecular = vec3(0.1);
float fragGloss = 10.0 / 128.0;
float fragOpacity = diffuse.a * _alpha;
float fragRoughness = 0.9;
float fragOpacity = albedo.a * _alpha;
vec4 color = evalGlobalColor(1.0,
fragPosition,
fragNormal,
fragDiffuse,
fragAlbedo,
fragMetallic,
fragSpecular,
fragGloss,
fragRoughness,
fragOpacity);
// Apply standard tone mapping

View file

@ -21,7 +21,7 @@ in float _alpha;
out vec4 _fragColor;
void main(void) {
vec4 diffuse = texture(originalTexture, _texCoord0);
vec4 albedo = texture(originalTexture, _texCoord0);
_fragColor = vec4(diffuse.rgb * _color, diffuse.a * _alpha);
_fragColor = vec4(albedo.rgb * _color, albedo.a * _alpha);
}

View file

@ -60,7 +60,7 @@ void main(void) {
vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0));
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss);
vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.metallic, frag.specular, frag.roughness);
// Eval attenuation
float radialAttenuation = evalLightAttenuation(light, fragLightDistance);

View file

@ -10,6 +10,8 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
<@include DeferredBufferWrite.slh@>
uniform sampler2D Font;
uniform bool Outline;
uniform vec4 Color;
@ -17,12 +19,11 @@ uniform vec4 Color;
// the interpolated normal
in vec3 _normal;
in vec2 _texCoord0;
/*
layout(location = 0) out vec4 _fragColor0;
layout(location = 1) out vec4 _fragColor1;
layout(location = 2) out vec4 _fragColor2;
const float DEFAULT_SHININESS = 10;
*/
const float gamma = 2.2;
const float smoothing = 256.0;
@ -53,7 +54,16 @@ void main() {
}
// final color
_fragColor0 = vec4(Color.rgb, Color.a * a);
/* _fragColor0 = vec4(Color.rgb, Color.a * a);
_fragColor1 = vec4(normalize(_normal.xyz), 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);
_fragColor2 = vec4(Color.rgb, DEFAULT_SHININESS / 128.0);
_fragColor2 = vec4(Color.rgb, 10 / 128.0);
*/
packDeferredFragmentLightmap(
normalize(_normal),
Color.a * a,
Color.rgb,
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_SPECULAR,
Color.rgb);
}

View file

@ -51,9 +51,9 @@ void main(void) {
if (emissiveAmount > 0.0) {
packDeferredFragmentLightmap(
normal, 1.0, diffuse, specular, shininess, specular);
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, specular);
} else {
packDeferredFragment(
normal, 1.0, diffuse, specular, shininess);
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), length(specular), DEFAULT_EMISSIVE, DEFAULT_OCCLUSION);
}
}

View file

@ -2,7 +2,7 @@
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// simple.frag
// simple_textured.slf
// fragment shader
//
// Created by Clément Brisset on 5/29/15.
@ -15,7 +15,7 @@
<@include DeferredBufferWrite.slh@>
<@include model/Material.slh@>
// the diffuse texture
// the albedo texture
uniform sampler2D originalTexture;
// the interpolated normal
@ -31,5 +31,8 @@ void main(void) {
normalize(_normal.xyz),
texel.a,
_color.rgb * texel.rgb,
DEFAULT_SPECULAR, DEFAULT_SHININESS);
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION);
}

View file

@ -14,7 +14,7 @@
<@include DeferredBufferWrite.slh@>
// the diffuse texture
// the albedo texture
uniform sampler2D originalTexture;
// the interpolated normal
@ -29,6 +29,8 @@ void main(void) {
normalize(_normal),
texel.a,
_color.rgb,
DEFAULT_SPECULAR, DEFAULT_SHININESS,
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_SPECULAR,
texel.rgb);
}

View file

@ -32,7 +32,7 @@ void main(void) {
skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal);
// pass along the diffuse color
// pass along the color
_color = colorToLinearRGB(inColor.rgb);
// and the texture coordinates

View file

@ -34,7 +34,7 @@ void main(void) {
skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz);
// pass along the diffuse color
// pass along the color
_color = colorToLinearRGB(inColor.rgb);
// and the texture coordinates

View file

@ -66,7 +66,7 @@ void main(void) {
vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0));
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss);
vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.metallic, frag.specular, frag.roughness);
// Eval attenuation
float radialAttenuation = evalLightAttenuation(light, fragLightDistance);

View file

@ -53,10 +53,12 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::SKINNING_GPU));
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Slot::MATERIAL_GPU));
slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), Slot::DIFFUSE_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("albedoMap"), Slot::ALBEDO_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("roughnessMap"), Slot::ROUGHNESS_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Slot::NORMAL_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Slot::SPECULAR_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::LIGHTMAP_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("metallicMap"), Slot::METALLIC_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::EMISSIVE_LIGHTMAP_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::OCCLUSION_MAP));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::LIGHT_BUFFER));
slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slot::NORMAL_FITTING_MAP));
@ -66,10 +68,12 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
locations->texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices");
locations->emissiveParams = program->getUniforms().findLocation("emissiveParams");
locations->normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap");
locations->diffuseTextureUnit = program->getTextures().findLocation("diffuseMap");
locations->albedoTextureUnit = program->getTextures().findLocation("albedoMap");
locations->roughnessTextureUnit = program->getTextures().findLocation("roughnessMap");
locations->normalTextureUnit = program->getTextures().findLocation("normalMap");
locations->specularTextureUnit = program->getTextures().findLocation("specularMap");
locations->metallicTextureUnit = program->getTextures().findLocation("metallicMap");
locations->emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
locations->occlusionTextureUnit = program->getTextures().findLocation("occlusionMap");
locations->skinClusterBufferUnit = program->getBuffers().findLocation("skinClusterBuffer");
locations->materialBufferUnit = program->getBuffers().findLocation("materialBuffer");
locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer");

View file

@ -195,10 +195,13 @@ public:
public:
static const int SKINNING_GPU = 2;
static const int MATERIAL_GPU = 3;
static const int DIFFUSE_MAP = 0;
static const int ALBEDO_MAP = 0;
static const int NORMAL_MAP = 1;
static const int SPECULAR_MAP = 2;
static const int LIGHTMAP_MAP = 3;
static const int METALLIC_MAP = 2;
static const int EMISSIVE_LIGHTMAP_MAP = 3;
static const int ROUGHNESS_MAP = 4;
static const int OCCLUSION_MAP = 5;
static const int LIGHT_BUFFER = 4;
static const int NORMAL_FITTING_MAP = 10;
};
@ -206,10 +209,12 @@ public:
class Locations {
public:
int texcoordMatrices;
int diffuseTextureUnit;
int albedoTextureUnit;
int normalTextureUnit;
int specularTextureUnit;
int roughnessTextureUnit;
int metallicTextureUnit;
int emissiveTextureUnit;
int occlusionTextureUnit;
int emissiveParams;
int normalFittingMapUnit;
int skinClusterBufferUnit;

View file

@ -81,6 +81,11 @@ void SceneScripting::KeyLight::setAmbientSphere(const gpu::SHPointer& sphere) {
_skyStage->setSunAmbientSphere(sphere);
}
void SceneScripting::KeyLight::setAmbientMap(const gpu::TexturePointer& map) {
_skyStage->setSunAmbientMap(map);
}
glm::vec3 SceneScripting::KeyLight::getDirection() const {
return _skyStage->getSunDirection();
}

View file

@ -84,6 +84,7 @@ namespace SceneScripting {
// AmbientTexture is unscriptable - it must be set through the zone entity
void setAmbientSphere(const gpu::SHPointer& sphere);
void resetAmbientSphere() { setAmbientSphere(nullptr); }
void setAmbientMap(const gpu::TexturePointer& map);
protected:
model::SunSkyStagePointer _skyStage;

View file

@ -24,5 +24,5 @@ void main(void) {
normalize(_normal.xyz),
1.0,
_color.rgb,
DEFAULT_SPECULAR, DEFAULT_SHININESS);
DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION);
}

View file

@ -18,6 +18,8 @@ typedef TextTemplate::Block::Pointer BlockPointer;
typedef TextTemplate::Config::Pointer ConfigPointer;
typedef TextTemplate::Pointer TextTemplatePointer;
const std::string TextTemplate::Tag::NULL_VAR = "_SCRIBE_NULL";
//-----------------------------------------------------------------------------
TextTemplate::Config::Config() :
_includes(),
@ -370,7 +372,11 @@ bool TextTemplate::convertExpressionToFuncArguments(String& src, std::vector< St
token += c;
} else if (c == ',') {
if (!token.empty()) {
arguments.push_back(token);
if (token == Tag::NULL_VAR) {
arguments.push_back(Tag::NULL_VAR);
} else {
arguments.push_back(token);
}
nbTokens++;
}
token.clear();
@ -750,7 +756,9 @@ int TextTemplate::evalBlockGeneration(std::ostream& dst, const BlockPointer& blo
paramCache.push_back((*it).second);
(*it).second = val;
} else {
vars.insert(Vars::value_type(funcBlock->command.arguments[i], val));
if (val != Tag::NULL_VAR) {
vars.insert(Vars::value_type(funcBlock->command.arguments[i], val));
}
paramCache.push_back("");
}
}

View file

@ -42,6 +42,8 @@ public:
static const char VAR = '$';
static const char COM = '@';
static const char REM = '!';
static const std::string NULL_VAR;
};
class Command {