material entities support cullFaceMode and support gltf doubleSided

This commit is contained in:
HifiExperiments 2019-11-26 14:48:43 -08:00 committed by Kasen IO
parent 59c67e5590
commit e0a29d9367
18 changed files with 256 additions and 117 deletions

View file

@ -22,7 +22,7 @@ namespace render {
PerformanceTimer perfTimer("worldBox"); PerformanceTimer perfTimer("worldBox");
auto& batch = *args->_batch; auto& batch = *args->_batch;
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, false, false, true, args->_renderMethod == Args::RenderMethod::FORWARD); DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, false, true, args->_renderMethod == Args::RenderMethod::FORWARD);
WorldBoxRenderData::renderWorldBox(args, batch); WorldBoxRenderData::renderWorldBox(args, batch);
} }
} }

View file

@ -791,7 +791,7 @@ void Avatar::render(RenderArgs* renderArgs) {
pointerTransform.setTranslation(position); pointerTransform.setTranslation(position);
pointerTransform.setRotation(rotation); pointerTransform.setRotation(rotation);
batch.setModelTransform(pointerTransform); batch.setModelTransform(pointerTransform);
geometryCache->bindSimpleProgram(batch, false, false, true, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD); geometryCache->bindSimpleProgram(batch, false, false, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _leftPointerGeometryID); geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _leftPointerGeometryID);
} }
} }
@ -815,7 +815,7 @@ void Avatar::render(RenderArgs* renderArgs) {
pointerTransform.setTranslation(position); pointerTransform.setTranslation(position);
pointerTransform.setRotation(rotation); pointerTransform.setRotation(rotation);
batch.setModelTransform(pointerTransform); batch.setModelTransform(pointerTransform);
geometryCache->bindSimpleProgram(batch, false, false, true, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD); geometryCache->bindSimpleProgram(batch, false, false, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _rightPointerGeometryID); geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _rightPointerGeometryID);
} }
} }
@ -1103,7 +1103,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
{ {
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect"); PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true, true, forward); DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true, forward);
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height, DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
bevelDistance, backgroundColor, _nameRectGeometryID); bevelDistance, backgroundColor, _nameRectGeometryID);
} }

View file

@ -253,7 +253,7 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
}); });
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES; bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
geometryCache->bindSimpleProgram(batch, false, isTransparent(), false, wireframe, true, true, forward); geometryCache->bindSimpleProgram(batch, false, isTransparent(), wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
batch.setModelTransform(transform); batch.setModelTransform(transform);

View file

@ -50,7 +50,7 @@ void LineEntityRenderer::doRender(RenderArgs* args) {
transform.setRotation(modelTransform.getRotation()); transform.setRotation(modelTransform.getRotation());
batch.setModelTransform(transform); batch.setModelTransform(transform);
if (_linePoints.size() > 1) { if (_linePoints.size() > 1) {
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, false, false, true, DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, false, true,
_renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD);
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID); DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
} }

View file

@ -200,6 +200,7 @@ ShapeKey ShapeEntityRenderer::getShapeKey() {
if (drawMaterialKey.isUnlit()) { if (drawMaterialKey.isUnlit()) {
builder.withUnlit(); builder.withUnlit();
} }
builder.withCullFaceMode(mat->second.getCullFaceMode());
} else if (pipelineType == Pipeline::PROCEDURAL) { } else if (pipelineType == Pipeline::PROCEDURAL) {
builder.withOwnPipeline(); builder.withOwnPipeline();
} }
@ -263,7 +264,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
// FIXME, support instanced multi-shape rendering using multidraw indirect // FIXME, support instanced multi-shape rendering using multidraw indirect
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false, render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false,
renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode());
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) {
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
} else { } else {

View file

@ -1774,6 +1774,10 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& mat
hfmMat._material->setOpacityCutoff(material.alphaCutoff); hfmMat._material->setOpacityCutoff(material.alphaCutoff);
} }
if (material.defined["doubleSided"] && material.doubleSided) {
hfmMat._material->setCullFaceMode(graphics::MaterialKey::CullFaceMode::CULL_NONE);
}
if (material.defined["emissiveFactor"] && material.emissiveFactor.size() == 3) { if (material.defined["emissiveFactor"] && material.emissiveFactor.size() == 3) {
glm::vec3 emissive = glm::vec3(material.emissiveFactor[0], material.emissiveFactor[1], material.emissiveFactor[2]); glm::vec3 emissive = glm::vec3(material.emissiveFactor[0], material.emissiveFactor[1], material.emissiveFactor[2]);
hfmMat._material->setEmissive(emissive); hfmMat._material->setEmissive(emissive);

View file

@ -65,6 +65,7 @@ namespace scriptable {
* @property {Mat4|string} texCoordTransform1 * @property {Mat4|string} texCoordTransform1
* @property {string} lightmapParams * @property {string} lightmapParams
* @property {string} materialParams * @property {string} materialParams
* @property {string} cullFaceMode
* @property {boolean} defaultFallthrough * @property {boolean} defaultFallthrough
* @property {string} procedural * @property {string} procedural
*/ */
@ -99,6 +100,7 @@ namespace scriptable {
QString lightMap; QString lightMap;
QString scatteringMap; QString scatteringMap;
std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texCoordTransforms; std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texCoordTransforms;
QString cullFaceMode;
bool defaultFallthrough; bool defaultFallthrough;
std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script

View file

@ -495,6 +495,11 @@ namespace scriptable {
obj.setProperty("materialParams", FALLTHROUGH); obj.setProperty("materialParams", FALLTHROUGH);
} }
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::CULL_FACE_MODE)) {
obj.setProperty("cullFaceMode", FALLTHROUGH);
} else if (!material.cullFaceMode.isEmpty()) {
obj.setProperty("cullFaceMode", material.cullFaceMode);
}
} else if (material.model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { } else if (material.model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
obj.setProperty("procedural", material.procedural); obj.setProperty("procedural", material.procedural);
} }

View file

@ -45,6 +45,7 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const
occlusionMap = material.occlusionMap; occlusionMap = material.occlusionMap;
lightMap = material.lightMap; lightMap = material.lightMap;
scatteringMap = material.scatteringMap; scatteringMap = material.scatteringMap;
cullFaceMode = material.cullFaceMode;
} else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { } else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
procedural = material.procedural; procedural = material.procedural;
} }
@ -131,6 +132,8 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint
for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) {
texCoordTransforms[i] = material->getTexCoordTransform(i); texCoordTransforms[i] = material->getTexCoordTransform(i);
} }
cullFaceMode = QString(graphics::MaterialKey::getCullFaceModeName(material->getCullFaceMode()).c_str());
} else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { } else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
procedural = material->getProceduralString(); procedural = material->getProceduralString();
} }

View file

@ -27,7 +27,7 @@ const float Material::DEFAULT_ROUGHNESS { 1.0f };
const float Material::DEFAULT_SCATTERING{ 0.0f }; const float Material::DEFAULT_SCATTERING{ 0.0f };
const MaterialKey::OpacityMapMode Material::DEFAULT_OPACITY_MAP_MODE{ MaterialKey::OPACITY_MAP_OPAQUE }; const MaterialKey::OpacityMapMode Material::DEFAULT_OPACITY_MAP_MODE{ MaterialKey::OPACITY_MAP_OPAQUE };
const float Material::DEFAULT_OPACITY_CUTOFF { 0.5f }; const float Material::DEFAULT_OPACITY_CUTOFF { 0.5f };
const MaterialKey::CullFaceMode Material::DEFAULT_CULL_FACE_MODE { MaterialKey::CULL_BACK };
std::string MaterialKey::getOpacityMapModeName(OpacityMapMode mode) { std::string MaterialKey::getOpacityMapModeName(OpacityMapMode mode) {
const std::string names[3] = { "OPACITY_MAP_OPAQUE", "OPACITY_MAP_MASK", "OPACITY_MAP_BLEND" }; const std::string names[3] = { "OPACITY_MAP_OPAQUE", "OPACITY_MAP_MASK", "OPACITY_MAP_BLEND" };
@ -44,6 +44,21 @@ bool MaterialKey::getOpacityMapModeFromName(const std::string& modeName, Materia
return false; return false;
} }
std::string MaterialKey::getCullFaceModeName(CullFaceMode mode) {
const std::string names[3] = { "CULL_NONE", "CULL_FRONT", "CULL_BACK" };
return names[mode];
}
bool MaterialKey::getCullFaceModeFromName(const std::string& modeName, CullFaceMode& mode) {
for (int i = CULL_NONE; i < NUM_CULL_FACE_MODES; i++) {
mode = (CullFaceMode)i;
if (modeName == getCullFaceModeName(mode)) {
return true;
}
}
return false;
}
const std::string Material::HIFI_PBR { "hifi_pbr" }; const std::string Material::HIFI_PBR { "hifi_pbr" };
const std::string Material::HIFI_SHADER_SIMPLE { "hifi_shader_simple" }; const std::string Material::HIFI_SHADER_SIMPLE { "hifi_shader_simple" };
@ -67,6 +82,7 @@ Material::Material(const Material& material) :
_texcoordTransforms(material._texcoordTransforms), _texcoordTransforms(material._texcoordTransforms),
_lightmapParams(material._lightmapParams), _lightmapParams(material._lightmapParams),
_materialParams(material._materialParams), _materialParams(material._materialParams),
_cullFaceMode(material._cullFaceMode),
_textureMaps(material._textureMaps), _textureMaps(material._textureMaps),
_defaultFallthrough(material._defaultFallthrough), _defaultFallthrough(material._defaultFallthrough),
_propertyFallthroughs(material._propertyFallthroughs) _propertyFallthroughs(material._propertyFallthroughs)
@ -89,6 +105,7 @@ Material& Material::operator=(const Material& material) {
_texcoordTransforms = material._texcoordTransforms; _texcoordTransforms = material._texcoordTransforms;
_lightmapParams = material._lightmapParams; _lightmapParams = material._lightmapParams;
_materialParams = material._materialParams; _materialParams = material._materialParams;
_cullFaceMode = material._cullFaceMode;
_textureMaps = material._textureMaps; _textureMaps = material._textureMaps;
_defaultFallthrough = material._defaultFallthrough; _defaultFallthrough = material._defaultFallthrough;
@ -144,7 +161,7 @@ void Material::setOpacityMapMode(MaterialKey::OpacityMapMode opacityMapMode) {
_key.setOpacityMapMode(opacityMapMode); _key.setOpacityMapMode(opacityMapMode);
} }
MaterialKey::OpacityMapMode Material::getOpacityMapMode() const { MaterialKey::OpacityMapMode Material::getOpacityMapMode() const {
return _key.getOpacityMapMode(); return _key.getOpacityMapMode();
} }

View file

@ -83,6 +83,16 @@ public:
// find the enum value from a string, return true if match found // find the enum value from a string, return true if match found
static bool getOpacityMapModeFromName(const std::string& modeName, OpacityMapMode& mode); static bool getOpacityMapModeFromName(const std::string& modeName, OpacityMapMode& mode);
enum CullFaceMode {
CULL_NONE = 0,
CULL_FRONT,
CULL_BACK,
NUM_CULL_FACE_MODES
};
static std::string getCullFaceModeName(CullFaceMode mode);
static bool getCullFaceModeFromName(const std::string& modeName, CullFaceMode& mode);
// The signature is the Flags // The signature is the Flags
Flags _flags; Flags _flags;
@ -349,6 +359,10 @@ public:
void setOpacityCutoff(float opacityCutoff); void setOpacityCutoff(float opacityCutoff);
float getOpacityCutoff() const { return _opacityCutoff; } float getOpacityCutoff() const { return _opacityCutoff; }
static const MaterialKey::CullFaceMode DEFAULT_CULL_FACE_MODE;
void setCullFaceMode(MaterialKey::CullFaceMode cullFaceMode) { _cullFaceMode = cullFaceMode; }
MaterialKey::CullFaceMode getCullFaceMode() const { return _cullFaceMode; }
void setUnlit(bool value); void setUnlit(bool value);
bool isUnlit() const { return _key.isUnlit(); } bool isUnlit() const { return _key.isUnlit(); }
@ -403,6 +417,7 @@ public:
TEXCOORDTRANSFORM1, TEXCOORDTRANSFORM1,
LIGHTMAP_PARAMS, LIGHTMAP_PARAMS,
MATERIAL_PARAMS, MATERIAL_PARAMS,
CULL_FACE_MODE,
NUM_TOTAL_FLAGS NUM_TOTAL_FLAGS
}; };
@ -436,6 +451,7 @@ private:
std::array<glm::mat4, NUM_TEXCOORD_TRANSFORMS> _texcoordTransforms; std::array<glm::mat4, NUM_TEXCOORD_TRANSFORMS> _texcoordTransforms;
glm::vec2 _lightmapParams { 0.0, 1.0 }; glm::vec2 _lightmapParams { 0.0, 1.0 };
glm::vec2 _materialParams { 0.0, 1.0 }; glm::vec2 _materialParams { 0.0, 1.0 };
MaterialKey::CullFaceMode _cullFaceMode { DEFAULT_CULL_FACE_MODE };
TextureMaps _textureMaps; TextureMaps _textureMaps;
bool _defaultFallthrough { false }; bool _defaultFallthrough { false };
@ -524,6 +540,9 @@ public:
graphics::MaterialKey getMaterialKey() const { return graphics::MaterialKey(_schemaBuffer.get<graphics::MultiMaterial::Schema>()._key); } graphics::MaterialKey getMaterialKey() const { return graphics::MaterialKey(_schemaBuffer.get<graphics::MultiMaterial::Schema>()._key); }
const gpu::TextureTablePointer& getTextureTable() const { return _textureTable; } const gpu::TextureTablePointer& getTextureTable() const { return _textureTable; }
void setCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) { _cullFaceMode = cullFaceMode; }
graphics::MaterialKey::CullFaceMode getCullFaceMode() const { return _cullFaceMode; }
void setNeedsUpdate(bool needsUpdate) { _needsUpdate = needsUpdate; } void setNeedsUpdate(bool needsUpdate) { _needsUpdate = needsUpdate; }
void setTexturesLoading(bool value) { _texturesLoading = value; } void setTexturesLoading(bool value) { _texturesLoading = value; }
void setInitialized() { _initialized = true; } void setInitialized() { _initialized = true; }
@ -536,6 +555,7 @@ public:
private: private:
gpu::BufferView _schemaBuffer; gpu::BufferView _schemaBuffer;
graphics::MaterialKey::CullFaceMode _cullFaceMode { graphics::Material::DEFAULT_CULL_FACE_MODE };
gpu::TextureTablePointer _textureTable { std::make_shared<gpu::TextureTable>() }; gpu::TextureTablePointer _textureTable { std::make_shared<gpu::TextureTable>() };
bool _needsUpdate { false }; bool _needsUpdate { false };
bool _texturesLoading { false }; bool _texturesLoading { false };

View file

@ -143,7 +143,7 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
* @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the <code>albedoMap</code> * @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the <code>albedoMap</code>
* value for transparency. * value for transparency.
* <code>"hifi_pbr"</code> model only. * <code>"hifi_pbr"</code> model only.
* @property {number|string} opacityMapMode - The mode defining the interpretation of the opacity map. Values can be: * @property {string} opacityMapMode - The mode defining the interpretation of the opacity map. Values can be:
* <code>"OPACITY_MAP_OPAQUE"</code> for ignoring the opacity map information. * <code>"OPACITY_MAP_OPAQUE"</code> for ignoring the opacity map information.
* <code>"OPACITY_MAP_MASK"</code> for using the opacity map as a mask, where only the texel greater than opacityCutoff are visible and rendered opaque. * <code>"OPACITY_MAP_MASK"</code> for using the opacity map as a mask, where only the texel greater than opacityCutoff are visible and rendered opaque.
* <code>"OPACITY_MAP_BLEND"</code> for using the opacity map for alpha blending the material surface with the background. * <code>"OPACITY_MAP_BLEND"</code> for using the opacity map for alpha blending the material surface with the background.
@ -151,6 +151,13 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
* @property {number|string} opacityCutoff - The opacity cutoff threshold used to determine the opaque texels of the Opacity map * @property {number|string} opacityCutoff - The opacity cutoff threshold used to determine the opaque texels of the Opacity map
* when opacityMapMode is "OPACITY_MAP_MASK", range <code>0.0</code> &ndash; <code>1.0</code>. * when opacityMapMode is "OPACITY_MAP_MASK", range <code>0.0</code> &ndash; <code>1.0</code>.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only. * Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} cullFaceMode - The mode defining which side of the geometry should be rendered. Values can be:
* <ul>
* <li><code>"CULL_NONE"</code> for rendering both sides of the geometry.</li>
* <li><code>"CULL_FRONT"</code> for culling the front faces of the geometry.</li>
* <li><code>"CULL_BACK"</code> (the default) for culling the back faces of the geometry.</li>
* </ul>
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
* @property {string} roughnessMap - The URL of the roughness texture image. You can use this or <code>glossMap</code>, but not * @property {string} roughnessMap - The URL of the roughness texture image. You can use this or <code>glossMap</code>, but not
* both. * both.
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only. * Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
@ -285,7 +292,20 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
} else if (value.isDouble()) { } else if (value.isDouble()) {
material->setOpacityCutoff(value.toDouble()); material->setOpacityCutoff(value.toDouble());
} }
} else if (key == "scattering") { } else if (key == "cullFaceMode") {
auto value = materialJSON.value(key);
if (value.isString()) {
auto valueString = value.toString();
if (valueString == FALLTHROUGH) {
material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::CULL_FACE_MODE);
} else {
graphics::MaterialKey::CullFaceMode mode;
if (graphics::MaterialKey::getCullFaceModeFromName(valueString.toStdString(), mode)) {
material->setCullFaceMode(mode);
}
}
}
} else if (key == "scattering") {
auto value = materialJSON.value(key); auto value = materialJSON.value(key);
if (value.isString() && value.toString() == FALLTHROUGH) { if (value.isString() && value.toString() == FALLTHROUGH) {
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::SCATTERING_VAL_BIT); material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::SCATTERING_VAL_BIT);

View file

@ -723,7 +723,7 @@ gpu::ShaderPointer GeometryCache::_forwardUnlitShader;
gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader; gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader;
gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader; gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader;
std::map<std::tuple<bool, bool, bool>, render::ShapePipelinePointer> GeometryCache::_shapePipelines; std::map<std::tuple<bool, bool, bool, graphics::MaterialKey::CullFaceMode>, render::ShapePipelinePointer> GeometryCache::_shapePipelines;
GeometryCache::GeometryCache() : GeometryCache::GeometryCache() :
_nextID(0) { _nextID(0) {
@ -776,15 +776,18 @@ void GeometryCache::initializeShapePipelines() {
bool transparent = i & 1; bool transparent = i & 1;
bool unlit = i & 2; bool unlit = i & 2;
bool forward = i & 4; bool forward = i & 4;
_shapePipelines[std::make_tuple(transparent, unlit, forward)] = getShapePipeline(false, transparent, true, unlit, false, forward); for (int cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_NONE; cullFaceMode < graphics::MaterialKey::CullFaceMode::NUM_CULL_FACE_MODES; cullFaceMode++) {
auto cullMode = (graphics::MaterialKey::CullFaceMode)cullFaceMode;
_shapePipelines[std::make_tuple(transparent, unlit, forward, cullMode)] = getShapePipeline(false, transparent, unlit, false, forward, cullMode);
}
} }
} }
} }
render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled, render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool unlit, bool depthBias, bool forward,
bool unlit, bool depthBias, bool forward) { graphics::MaterialKey::CullFaceMode cullFaceMode) {
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true, forward), nullptr, return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, unlit, depthBias, false, true, forward, cullFaceMode), nullptr,
[](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { [](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture()); batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture());
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch); DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch);
@ -792,12 +795,12 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool
); );
} }
render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled, render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool unlit, bool depthBias, bool forward,
bool unlit, bool depthBias, bool forward) { graphics::MaterialKey::CullFaceMode cullFaceMode) {
auto fadeEffect = DependencyManager::get<FadeEffect>(); auto fadeEffect = DependencyManager::get<FadeEffect>();
auto fadeBatchSetter = fadeEffect->getBatchSetter(); auto fadeBatchSetter = fadeEffect->getBatchSetter();
auto fadeItemSetter = fadeEffect->getItemUniformSetter(); auto fadeItemSetter = fadeEffect->getItemUniformSetter();
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true, true, forward), nullptr, return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, unlit, depthBias, true, true, forward, cullFaceMode), nullptr,
[fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) { [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) {
batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture()); batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture());
fadeBatchSetter(shapePipeline, batch, args); fadeBatchSetter(shapePipeline, batch, args);
@ -2049,54 +2052,60 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo
class SimpleProgramKey { class SimpleProgramKey {
public: public:
enum FlagBit { enum FlagBit {
IS_TEXTURED_FLAG = 0, IS_TEXTURED_BIT = 0,
IS_TRANSPARENT_FLAG, IS_TRANSPARENT_BIT,
IS_CULLED_FLAG, IS_UNLIT_BIT,
IS_UNLIT_FLAG, IS_DEPTH_BIASED_BIT,
HAS_DEPTH_BIAS_FLAG, IS_FADING_BIT,
IS_FADING_FLAG, IS_ANTIALIASED_BIT,
IS_ANTIALIASED_FLAG, IS_FORWARD_BIT,
IS_FORWARD_FLAG, IS_CULL_FACE_NONE_BIT, // if neither of these are set, we're CULL_FACE_BACK
IS_CULL_FACE_FRONT_BIT,
NUM_FLAGS, NUM_FLAGS,
}; };
typedef std::bitset<NUM_FLAGS> Flags;
enum Flag { bool isTextured() const { return _flags[IS_TEXTURED_BIT]; }
IS_TEXTURED = (1 << IS_TEXTURED_FLAG), bool isTransparent() const { return _flags[IS_TRANSPARENT_BIT]; }
IS_TRANSPARENT = (1 << IS_TRANSPARENT_FLAG), bool isUnlit() const { return _flags[IS_UNLIT_BIT]; }
IS_CULLED = (1 << IS_CULLED_FLAG), bool hasDepthBias() const { return _flags[IS_DEPTH_BIASED_BIT]; }
IS_UNLIT = (1 << IS_UNLIT_FLAG), bool isFading() const { return _flags[IS_FADING_BIT]; }
HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG), bool isAntiAliased() const { return _flags[IS_ANTIALIASED_BIT]; }
IS_FADING = (1 << IS_FADING_FLAG), bool isForward() const { return _flags[IS_FORWARD_BIT]; }
IS_ANTIALIASED = (1 << IS_ANTIALIASED_FLAG), bool isCullFaceNone() const { return _flags[IS_CULL_FACE_NONE_BIT]; }
IS_FORWARD = (1 << IS_FORWARD_FLAG), bool isCullFaceFront() const { return _flags[IS_CULL_FACE_FRONT_BIT]; }
};
typedef unsigned short Flags;
bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }
bool isTextured() const { return isFlag(IS_TEXTURED); }
bool isTransparent() const { return isFlag(IS_TRANSPARENT); }
bool isCulled() const { return isFlag(IS_CULLED); }
bool isUnlit() const { return isFlag(IS_UNLIT); }
bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); }
bool isFading() const { return isFlag(IS_FADING); }
bool isAntiAliased() const { return isFlag(IS_ANTIALIASED); }
bool isForward() const { return isFlag(IS_FORWARD); }
Flags _flags = 0; Flags _flags = 0;
#if defined(__clang__)
__attribute__((unused))
#endif
short _spare = 0; // Padding
int getRaw() const { return *reinterpret_cast<const int*>(this); } unsigned long getRaw() const { return _flags.to_ulong(); }
SimpleProgramKey(bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false, bool fading = false,
bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CULL_BACK) {
_flags.set(IS_TEXTURED_BIT, textured);
_flags.set(IS_TRANSPARENT_BIT, transparent);
_flags.set(IS_UNLIT_BIT, unlit);
_flags.set(IS_DEPTH_BIASED_BIT, depthBias);
_flags.set(IS_FADING_BIT, fading);
_flags.set(IS_ANTIALIASED_BIT, isAntiAliased);
_flags.set(IS_FORWARD_BIT, forward);
SimpleProgramKey(bool textured = false, bool transparent = false, bool culled = true, switch (cullFaceMode) {
bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false) { case graphics::MaterialKey::CullFaceMode::CULL_NONE:
_flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) | _flags.set(IS_CULL_FACE_NONE_BIT);
(unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0) | (fading ? IS_FADING : 0) | (isAntiAliased ? IS_ANTIALIASED : 0) | (forward ? IS_FORWARD : 0); _flags.reset(IS_CULL_FACE_FRONT_BIT);
break;
case graphics::MaterialKey::CullFaceMode::CULL_FRONT:
_flags.reset(IS_CULL_FACE_NONE_BIT);
_flags.set(IS_CULL_FACE_FRONT_BIT);
break;
case graphics::MaterialKey::CullFaceMode::CULL_BACK:
_flags.reset(IS_CULL_FACE_NONE_BIT);
_flags.reset(IS_CULL_FACE_FRONT_BIT);
break;
default:
break;
}
} }
SimpleProgramKey(int bitmask) : _flags(bitmask) {} SimpleProgramKey(int bitmask) : _flags(bitmask) {}
@ -2141,8 +2150,9 @@ gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool
return _webPipelines[{ transparent, forward }]; return _webPipelines[{ transparent, forward }];
} }
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool isAntiAliased, bool forward) { void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool unlit, bool depthBiased, bool isAntiAliased,
batch.setPipeline(getSimplePipeline(textured, transparent, culled, unlit, depthBiased, false, isAntiAliased, forward)); bool forward, graphics::MaterialKey::CullFaceMode cullFaceMode) {
batch.setPipeline(getSimplePipeline(textured, transparent, unlit, depthBiased, false, isAntiAliased, forward, cullFaceMode));
// If not textured, set a default albedo map // If not textured, set a default albedo map
if (!textured) { if (!textured) {
@ -2151,8 +2161,9 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool tra
} }
} }
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool fading, bool isAntiAliased, bool forward) { gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool unlit, bool depthBiased, bool fading, bool isAntiAliased,
SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased, fading, isAntiAliased, forward }; bool forward, graphics::MaterialKey::CullFaceMode cullFaceMode) {
SimpleProgramKey config { textured, transparent, unlit, depthBiased, fading, isAntiAliased, forward, cullFaceMode };
// If the pipeline already exists, return it // If the pipeline already exists, return it
auto it = _simplePrograms.find(config); auto it = _simplePrograms.find(config);
@ -2189,10 +2200,12 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
// If the pipeline did not exist, make it // If the pipeline did not exist, make it
auto state = std::make_shared<gpu::State>(); auto state = std::make_shared<gpu::State>();
if (config.isCulled()) { if (config.isCullFaceNone()) {
state->setCullMode(gpu::State::CULL_BACK);
} else {
state->setCullMode(gpu::State::CULL_NONE); state->setCullMode(gpu::State::CULL_NONE);
} else if (config.isCullFaceFront()) {
state->setCullMode(gpu::State::CULL_FRONT);
} else {
state->setCullMode(gpu::State::CULL_BACK);
} }
state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setDepthTest(true, true, gpu::LESS_EQUAL);
if (config.hasDepthBias()) { if (config.hasDepthBias()) {

View file

@ -162,18 +162,19 @@ public:
static const int UNKNOWN_ID; static const int UNKNOWN_ID;
// Bind the pipeline and get the state to render static geometry // Bind the pipeline and get the state to render static geometry
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool culled = true, void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false,
bool unlit = false, bool depthBias = false, bool isAntiAliased = true, bool forward = false); bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
// Get the pipeline to render static geometry // Get the pipeline to render static geometry
static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false,
bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false); bool fading = false, bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
void bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward); void bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward);
gpu::PipelinePointer getWebBrowserProgram(bool transparent, bool forward); gpu::PipelinePointer getWebBrowserProgram(bool transparent, bool forward);
static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _webPipelines; static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _webPipelines;
static void initializeShapePipelines(); static void initializeShapePipelines();
render::ShapePipelinePointer getShapePipelinePointer(bool transparent, bool unlit, bool forward) { return _shapePipelines[std::make_tuple(transparent, unlit, forward)]; } render::ShapePipelinePointer getShapePipelinePointer(bool transparent, bool unlit, bool forward,
graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CULL_BACK) { return _shapePipelines[std::make_tuple(transparent, unlit, forward, cullFaceMode)]; }
// Static (instanced) geometry // Static (instanced) geometry
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
@ -456,13 +457,13 @@ private:
static gpu::ShaderPointer _forwardSimpleFadeShader; static gpu::ShaderPointer _forwardSimpleFadeShader;
static gpu::ShaderPointer _forwardUnlitFadeShader; static gpu::ShaderPointer _forwardUnlitFadeShader;
static std::map<std::tuple<bool, bool, bool>, render::ShapePipelinePointer> _shapePipelines; static std::map<std::tuple<bool, bool, bool, graphics::MaterialKey::CullFaceMode>, render::ShapePipelinePointer> _shapePipelines;
static QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms; static QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool unlit = false,
bool unlit = false, bool depthBias = false, bool forward = false); bool depthBias = false, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true, static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool unlit = false,
bool unlit = false, bool depthBias = false, bool forward = false); bool depthBias = false, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
}; };
#endif // hifi_GeometryCache_h #endif // hifi_GeometryCache_h

View file

@ -143,6 +143,9 @@ ShapeKey MeshPartPayload::getShapeKey() const {
if (drawMaterialKey.isUnlit()) { if (drawMaterialKey.isUnlit()) {
builder.withUnlit(); builder.withUnlit();
} }
if (material) {
builder.withCullFaceMode(material->getCullFaceMode());
}
} }
return builder.build(); return builder.build();
@ -434,6 +437,9 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr
if (isUnlit) { if (isUnlit) {
builder.withUnlit(); builder.withUnlit();
} }
if (material) {
builder.withCullFaceMode(material->getCullFaceMode());
}
} }
_shapeKey = builder.build(); _shapeKey = builder.build();

View file

@ -1040,7 +1040,7 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch, bool forward) {
Transform meshToWorld(meshToWorldMatrix); Transform meshToWorld(meshToWorldMatrix);
batch.setModelTransform(meshToWorld); batch.setModelTransform(meshToWorld);
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true, forward); DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, forward, graphics::MaterialKey::CULL_NONE);
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) { for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
for (auto &partTriangleSet : meshTriangleSets) { for (auto &partTriangleSet : meshTriangleSets) {

View file

@ -259,46 +259,44 @@ void addPlumberPipeline(ShapePlumber& plumber,
gpu::ShaderPointer program = gpu::Shader::createProgram(programId); gpu::ShaderPointer program = gpu::Shader::createProgram(programId);
for (int i = 0; i < 8; i++) { for (int i = 0; i < 4; i++) {
bool isCulled = (i & 1); bool isBiased = (i & 1);
bool isBiased = (i & 2); bool isWireframed = (i & 2);
bool isWireframed = (i & 4); for (int cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_NONE; cullFaceMode < graphics::MaterialKey::CullFaceMode::NUM_CULL_FACE_MODES; cullFaceMode++) {
auto state = std::make_shared<gpu::State>();
key.isTranslucent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state);
auto state = std::make_shared<gpu::State>(); // Depth test depends on transparency
key.isTranslucent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state); state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);
state->setBlendFunction(key.isTranslucent(),
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
// Depth test depends on transparency ShapeKey::Builder builder(key);
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); builder.withCullFaceMode((graphics::MaterialKey::CullFaceMode)cullFaceMode);
state->setBlendFunction(key.isTranslucent(), state->setCullMode((gpu::State::CullMode)cullFaceMode);
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, if (isWireframed) {
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); builder.withWireframe();
state->setFillMode(gpu::State::FILL_LINE);
}
if (isBiased) {
builder.withDepthBias();
state->setDepthBias(1.0f);
state->setDepthBiasSlopeScale(1.0f);
}
ShapeKey::Builder builder(key); auto baseBatchSetter = (forceLightBatchSetter || key.isTranslucent()) ? &lightBatchSetter : &batchSetter;
if (!isCulled) { render::ShapePipeline::BatchSetter finalBatchSetter;
builder.withoutCullFace(); if (extraBatchSetter) {
finalBatchSetter = [baseBatchSetter, extraBatchSetter](const ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
baseBatchSetter(pipeline, batch, args);
extraBatchSetter(pipeline, batch, args);
};
} else {
finalBatchSetter = baseBatchSetter;
}
plumber.addPipeline(builder.build(), program, state, finalBatchSetter, itemSetter);
} }
state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE);
if (isWireframed) {
builder.withWireframe();
state->setFillMode(gpu::State::FILL_LINE);
}
if (isBiased) {
builder.withDepthBias();
state->setDepthBias(1.0f);
state->setDepthBiasSlopeScale(1.0f);
}
auto baseBatchSetter = (forceLightBatchSetter || key.isTranslucent()) ? &lightBatchSetter : &batchSetter;
render::ShapePipeline::BatchSetter finalBatchSetter;
if (extraBatchSetter) {
finalBatchSetter = [baseBatchSetter, extraBatchSetter](const ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
baseBatchSetter(pipeline, batch, args);
extraBatchSetter(pipeline, batch, args);
};
} else {
finalBatchSetter = baseBatchSetter;
}
plumber.addPipeline(builder.build(), program, state, finalBatchSetter, itemSetter);
} }
} }
@ -644,6 +642,12 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
wasSet = true; wasSet = true;
} }
break; break;
case graphics::Material::CULL_FACE_MODE:
if (!fallthrough) {
multiMaterial.setCullFaceMode(material->getCullFaceMode());
wasSet = true;
}
break;
default: default:
break; break;
} }
@ -685,6 +689,8 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
case graphics::Material::MATERIAL_PARAMS: case graphics::Material::MATERIAL_PARAMS:
// these are initialized to the correct default values in Schema() // these are initialized to the correct default values in Schema()
break; break;
case graphics::Material::CULL_FACE_MODE:
multiMaterial.setCullFaceMode(graphics::Material::DEFAULT_CULL_FACE_MODE);
case graphics::MaterialKey::ALBEDO_MAP_BIT: case graphics::MaterialKey::ALBEDO_MAP_BIT:
if (schemaKey.isAlbedoMap()) { if (schemaKey.isAlbedoMap()) {
drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture()); drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture());

View file

@ -15,6 +15,7 @@
#include <unordered_set> #include <unordered_set>
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <graphics/Material.h>
#include "Args.h" #include "Args.h"
@ -34,8 +35,9 @@ public:
DUAL_QUAT_SKINNED, DUAL_QUAT_SKINNED,
DEPTH_BIAS, DEPTH_BIAS,
WIREFRAME, WIREFRAME,
NO_CULL_FACE,
FADE, FADE,
CULL_FACE_NONE, // if neither of these are set, we're CULL_FACE_BACK
CULL_FACE_FRONT,
OWN_PIPELINE, OWN_PIPELINE,
INVALID, INVALID,
@ -81,9 +83,29 @@ public:
Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); return (*this); } Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); return (*this); }
Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); } Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); }
Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); }
Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); return (*this); }
Builder& withFade() { _flags.set(FADE); return (*this); } Builder& withFade() { _flags.set(FADE); return (*this); }
Builder& withoutCullFace() { return withCullFaceMode(graphics::MaterialKey::CullFaceMode::CULL_NONE); }
Builder& withCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) {
switch (cullFaceMode) {
case graphics::MaterialKey::CullFaceMode::CULL_NONE:
_flags.set(CULL_FACE_NONE);
_flags.reset(CULL_FACE_FRONT);
break;
case graphics::MaterialKey::CullFaceMode::CULL_FRONT:
_flags.reset(CULL_FACE_NONE);
_flags.set(CULL_FACE_FRONT);
break;
case graphics::MaterialKey::CullFaceMode::CULL_BACK:
_flags.reset(CULL_FACE_NONE);
_flags.reset(CULL_FACE_FRONT);
break;
default:
break;
}
return (*this);
}
Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); } Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); }
Builder& invalidate() { _flags.set(INVALID); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); }
@ -137,8 +159,27 @@ public:
Builder& withWireframe() { _flags.set(WIREFRAME); _mask.set(WIREFRAME); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); _mask.set(WIREFRAME); return (*this); }
Builder& withoutWireframe() { _flags.reset(WIREFRAME); _mask.set(WIREFRAME); return (*this); } Builder& withoutWireframe() { _flags.reset(WIREFRAME); _mask.set(WIREFRAME); return (*this); }
Builder& withCullFace() { _flags.reset(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } Builder& withCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) {
Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } switch (cullFaceMode) {
case graphics::MaterialKey::CullFaceMode::CULL_NONE:
_flags.set(CULL_FACE_NONE);
_flags.reset(CULL_FACE_FRONT);
break;
case graphics::MaterialKey::CullFaceMode::CULL_FRONT:
_flags.reset(CULL_FACE_NONE);
_flags.set(CULL_FACE_FRONT);
break;
case graphics::MaterialKey::CullFaceMode::CULL_BACK:
_flags.reset(CULL_FACE_NONE);
_flags.reset(CULL_FACE_FRONT);
break;
default:
break;
}
_mask.set(CULL_FACE_NONE);
_mask.set(CULL_FACE_FRONT);
return (*this);
}
Builder& withFade() { _flags.set(FADE); _mask.set(FADE); return (*this); } Builder& withFade() { _flags.set(FADE); _mask.set(FADE); return (*this); }
Builder& withoutFade() { _flags.reset(FADE); _mask.set(FADE); return (*this); } Builder& withoutFade() { _flags.reset(FADE); _mask.set(FADE); return (*this); }
@ -168,7 +209,7 @@ public:
bool isDualQuatSkinned() const { return _flags[DUAL_QUAT_SKINNED]; } bool isDualQuatSkinned() const { return _flags[DUAL_QUAT_SKINNED]; }
bool isDepthBiased() const { return _flags[DEPTH_BIAS]; } bool isDepthBiased() const { return _flags[DEPTH_BIAS]; }
bool isWireframe() const { return _flags[WIREFRAME]; } bool isWireframe() const { return _flags[WIREFRAME]; }
bool isCullFace() const { return !_flags[NO_CULL_FACE]; } bool isCullFace() const { return !_flags[CULL_FACE_NONE] && !_flags[CULL_FACE_FRONT]; }
bool isFaded() const { return _flags[FADE]; } bool isFaded() const { return _flags[FADE]; }
bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; } bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; }