mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 02:03:11 +02:00
Merge pull request #7028 from zzmp/fix/overlay
Add transparency and layering for overlays sam is doing it
This commit is contained in:
commit
e61636e8a7
46 changed files with 814 additions and 364 deletions
|
@ -105,7 +105,6 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
||||||
auto transform = _transform;
|
auto transform = _transform;
|
||||||
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false);
|
|
||||||
|
|
||||||
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
|
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
|
||||||
// we just draw a line...
|
// we just draw a line...
|
||||||
|
@ -278,6 +277,14 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder().withoutCullFace();
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
void Circle3DOverlay::setProperties(const QScriptValue &properties) {
|
void Circle3DOverlay::setProperties(const QScriptValue &properties) {
|
||||||
Planar3DOverlay::setProperties(properties);
|
Planar3DOverlay::setProperties(properties);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
Circle3DOverlay(const Circle3DOverlay* circle3DOverlay);
|
Circle3DOverlay(const Circle3DOverlay* circle3DOverlay);
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
virtual QScriptValue getProperty(const QString& property);
|
virtual QScriptValue getProperty(const QString& property);
|
||||||
|
|
||||||
|
|
|
@ -46,22 +46,17 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
||||||
Transform transform;
|
Transform transform;
|
||||||
transform.setTranslation(position);
|
transform.setTranslation(position);
|
||||||
transform.setRotation(rotation);
|
transform.setRotation(rotation);
|
||||||
if (_isSolid) {
|
|
||||||
// if (_borderSize > 0) {
|
|
||||||
// // Draw a cube at a larger size behind the main cube, creating
|
|
||||||
// // a border effect.
|
|
||||||
// // Disable writing to the depth mask so that the "border" cube will not
|
|
||||||
// // occlude the main cube. This means the border could be covered by
|
|
||||||
// // overlays that are further back and drawn later, but this is good
|
|
||||||
// // enough for the use-case.
|
|
||||||
// transform.setScale(dimensions * _borderSize);
|
|
||||||
// batch->setModelTransform(transform);
|
|
||||||
// DependencyManager::get<GeometryCache>()->renderSolidCube(*batch, 1.0f, glm::vec4(1.0f, 1.0f, 1.0f, alpha));
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
auto pipeline = args->_pipeline;
|
||||||
|
if (!pipeline) {
|
||||||
|
pipeline = geometryCache->getShapePipeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isSolid) {
|
||||||
transform.setScale(dimensions);
|
transform.setScale(dimensions);
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(*batch, cubeColor);
|
geometryCache->renderSolidCubeInstance(*batch, cubeColor, pipeline);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (getIsDashedLine()) {
|
if (getIsDashedLine()) {
|
||||||
|
@ -79,8 +74,6 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
||||||
glm::vec3 topLeftFar(-halfDimensions.x, halfDimensions.y, halfDimensions.z);
|
glm::vec3 topLeftFar(-halfDimensions.x, halfDimensions.y, halfDimensions.z);
|
||||||
glm::vec3 topRightFar(halfDimensions.x, halfDimensions.y, halfDimensions.z);
|
glm::vec3 topRightFar(halfDimensions.x, halfDimensions.y, halfDimensions.z);
|
||||||
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
|
||||||
|
|
||||||
geometryCache->renderDashedLine(*batch, bottomLeftNear, bottomRightNear, cubeColor);
|
geometryCache->renderDashedLine(*batch, bottomLeftNear, bottomRightNear, cubeColor);
|
||||||
geometryCache->renderDashedLine(*batch, bottomRightNear, bottomRightFar, cubeColor);
|
geometryCache->renderDashedLine(*batch, bottomRightNear, bottomRightFar, cubeColor);
|
||||||
geometryCache->renderDashedLine(*batch, bottomRightFar, bottomLeftFar, cubeColor);
|
geometryCache->renderDashedLine(*batch, bottomRightFar, bottomLeftFar, cubeColor);
|
||||||
|
@ -99,12 +92,20 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
||||||
} else {
|
} else {
|
||||||
transform.setScale(dimensions);
|
transform.setScale(dimensions);
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(*batch, cubeColor);
|
geometryCache->renderWireCubeInstance(*batch, cubeColor, pipeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Cube3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder();
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
Cube3DOverlay* Cube3DOverlay::createClone() const {
|
Cube3DOverlay* Cube3DOverlay::createClone() const {
|
||||||
return new Cube3DOverlay(this);
|
return new Cube3DOverlay(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
Cube3DOverlay(const Cube3DOverlay* cube3DOverlay);
|
Cube3DOverlay(const Cube3DOverlay* cube3DOverlay);
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
|
|
||||||
virtual Cube3DOverlay* createClone() const;
|
virtual Cube3DOverlay* createClone() const;
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,14 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Grid3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder();
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
void Grid3DOverlay::setProperties(const QScriptValue& properties) {
|
void Grid3DOverlay::setProperties(const QScriptValue& properties) {
|
||||||
Planar3DOverlay::setProperties(properties);
|
Planar3DOverlay::setProperties(properties);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
Grid3DOverlay(const Grid3DOverlay* grid3DOverlay);
|
Grid3DOverlay(const Grid3DOverlay* grid3DOverlay);
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
virtual QScriptValue getProperty(const QString& property);
|
virtual QScriptValue getProperty(const QString& property);
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,6 @@ void Image3DOverlay::render(RenderArgs* args) {
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(*batch, true, false, _emissive, true);
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(
|
DependencyManager::get<GeometryCache>()->renderQuad(
|
||||||
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||||
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)
|
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)
|
||||||
|
@ -104,6 +103,17 @@ void Image3DOverlay::render(RenderArgs* args) {
|
||||||
batch->setResourceTexture(0, args->_whiteTexture); // restore default white color after me
|
batch->setResourceTexture(0, args->_whiteTexture); // restore default white color after me
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Image3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
||||||
|
if (_emissive) {
|
||||||
|
builder.withEmissive();
|
||||||
|
}
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
void Image3DOverlay::setProperties(const QScriptValue &properties) {
|
void Image3DOverlay::setProperties(const QScriptValue &properties) {
|
||||||
Billboard3DOverlay::setProperties(properties);
|
Billboard3DOverlay::setProperties(properties);
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ public:
|
||||||
|
|
||||||
virtual void update(float deltatime);
|
virtual void update(float deltatime);
|
||||||
|
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void setURL(const QString& url);
|
void setURL(const QString& url);
|
||||||
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }
|
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }
|
||||||
|
|
|
@ -53,7 +53,6 @@ void Line3DOverlay::render(RenderArgs* args) {
|
||||||
auto batch = args->_batch;
|
auto batch = args->_batch;
|
||||||
if (batch) {
|
if (batch) {
|
||||||
batch->setModelTransform(_transform);
|
batch->setModelTransform(_transform);
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(*batch);
|
|
||||||
|
|
||||||
if (getIsDashedLine()) {
|
if (getIsDashedLine()) {
|
||||||
// TODO: add support for color to renderDashedLine()
|
// TODO: add support for color to renderDashedLine()
|
||||||
|
@ -64,6 +63,14 @@ void Line3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Line3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder();
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
void Line3DOverlay::setProperties(const QScriptValue& properties) {
|
void Line3DOverlay::setProperties(const QScriptValue& properties) {
|
||||||
Base3DOverlay::setProperties(properties);
|
Base3DOverlay::setProperties(properties);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
Line3DOverlay(const Line3DOverlay* line3DOverlay);
|
Line3DOverlay(const Line3DOverlay* line3DOverlay);
|
||||||
~Line3DOverlay();
|
~Line3DOverlay();
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
virtual AABox getBounds() const;
|
virtual AABox getBounds() const;
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
|
|
|
@ -44,6 +44,8 @@ public:
|
||||||
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||||
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||||
|
|
||||||
|
virtual const render::ShapeKey getShapeKey() { return render::ShapeKey::Builder::ownPipeline(); }
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
virtual QString getType() const = 0;
|
virtual QString getType() const = 0;
|
||||||
virtual bool is3D() const = 0;
|
virtual bool is3D() const = 0;
|
||||||
|
@ -119,6 +121,7 @@ namespace render {
|
||||||
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay);
|
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay);
|
||||||
template <> int payloadGetLayer(const Overlay::Pointer& overlay);
|
template <> int payloadGetLayer(const Overlay::Pointer& overlay);
|
||||||
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args);
|
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args);
|
||||||
|
template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,18 @@
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
|
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
|
||||||
|
auto builder = ItemKey::Builder().withTypeShape();
|
||||||
if (overlay->is3D() && !std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawOnHUD()) {
|
if (overlay->is3D() && !std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawOnHUD()) {
|
||||||
if (std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) {
|
if (std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) {
|
||||||
return ItemKey::Builder().withTypeShape().withLayered().build();
|
builder.withLayered();
|
||||||
} else {
|
}
|
||||||
return ItemKey::Builder::opaqueShape();
|
if (overlay->getAlpha() != 1.0f) {
|
||||||
|
builder.withTransparent();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return ItemKey::Builder().withTypeShape().withViewSpace().build();
|
builder.withViewSpace();
|
||||||
}
|
}
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) {
|
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) {
|
||||||
return overlay->getBounds();
|
return overlay->getBounds();
|
||||||
|
@ -80,4 +83,7 @@ namespace render {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay) {
|
||||||
|
return overlay->getShapeKey();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,14 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder();
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
void Rectangle3DOverlay::setProperties(const QScriptValue &properties) {
|
void Rectangle3DOverlay::setProperties(const QScriptValue &properties) {
|
||||||
Planar3DOverlay::setProperties(properties);
|
Planar3DOverlay::setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay);
|
Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay);
|
||||||
~Rectangle3DOverlay();
|
~Rectangle3DOverlay();
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
|
|
||||||
virtual Rectangle3DOverlay* createClone() const;
|
virtual Rectangle3DOverlay* createClone() const;
|
||||||
|
|
|
@ -42,14 +42,29 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
||||||
Transform transform = _transform;
|
Transform transform = _transform;
|
||||||
transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE);
|
transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE);
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
|
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
auto pipeline = args->_pipeline;
|
||||||
|
if (!pipeline) {
|
||||||
|
pipeline = geometryCache->getShapePipeline();
|
||||||
|
}
|
||||||
|
|
||||||
if (_isSolid) {
|
if (_isSolid) {
|
||||||
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(*batch, sphereColor);
|
geometryCache->renderSolidSphereInstance(*batch, sphereColor, pipeline);
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<GeometryCache>()->renderWireSphereInstance(*batch, sphereColor);
|
geometryCache->renderWireSphereInstance(*batch, sphereColor, pipeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder();
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
Sphere3DOverlay* Sphere3DOverlay::createClone() const {
|
Sphere3DOverlay* Sphere3DOverlay::createClone() const {
|
||||||
return new Sphere3DOverlay(this);
|
return new Sphere3DOverlay(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay);
|
Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay);
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
|
|
||||||
virtual Sphere3DOverlay* createClone() const;
|
virtual Sphere3DOverlay* createClone() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#include "Text3DOverlay.h"
|
#include "Text3DOverlay.h"
|
||||||
|
|
||||||
|
#include <TextureCache.h>
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <RenderDeferredTask.h>
|
#include <RenderDeferredTask.h>
|
||||||
|
@ -34,6 +36,7 @@ Text3DOverlay::Text3DOverlay() :
|
||||||
_bottomMargin(DEFAULT_MARGIN)
|
_bottomMargin(DEFAULT_MARGIN)
|
||||||
{
|
{
|
||||||
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||||
|
_alpha = _backgroundAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
||||||
|
@ -47,7 +50,8 @@ Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
||||||
_rightMargin(text3DOverlay->_rightMargin),
|
_rightMargin(text3DOverlay->_rightMargin),
|
||||||
_bottomMargin(text3DOverlay->_bottomMargin)
|
_bottomMargin(text3DOverlay->_bottomMargin)
|
||||||
{
|
{
|
||||||
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||||
|
_alpha = _backgroundAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
Text3DOverlay::~Text3DOverlay() {
|
Text3DOverlay::~Text3DOverlay() {
|
||||||
|
@ -100,7 +104,6 @@ void Text3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, true, false, true);
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, quadColor);
|
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, quadColor);
|
||||||
|
|
||||||
// Same font properties as textSize()
|
// Same font properties as textSize()
|
||||||
|
@ -120,7 +123,15 @@ void Text3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR,
|
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR,
|
||||||
_color.blue / MAX_COLOR, getAlpha() };
|
_color.blue / MAX_COLOR, getAlpha() };
|
||||||
_textRenderer->draw(batch, 0, 0, _text, textColor);
|
_textRenderer->draw(batch, 0, 0, _text, textColor, glm::vec2(-1.0f), getDrawInFront());
|
||||||
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Text3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder();
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
||||||
|
@ -145,6 +156,7 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
||||||
|
|
||||||
if (properties.property("backgroundAlpha").isValid()) {
|
if (properties.property("backgroundAlpha").isValid()) {
|
||||||
_backgroundAlpha = properties.property("backgroundAlpha").toVariant().toFloat();
|
_backgroundAlpha = properties.property("backgroundAlpha").toVariant().toFloat();
|
||||||
|
_alpha = _backgroundAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties.property("lineHeight").isValid()) {
|
if (properties.property("lineHeight").isValid()) {
|
||||||
|
|
|
@ -31,6 +31,8 @@ public:
|
||||||
|
|
||||||
virtual void update(float deltatime);
|
virtual void update(float deltatime);
|
||||||
|
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
const QString& getText() const { return _text; }
|
const QString& getText() const { return _text; }
|
||||||
float getLineHeight() const { return _lineHeight; }
|
float getLineHeight() const { return _lineHeight; }
|
||||||
|
@ -72,5 +74,4 @@ private:
|
||||||
float _bottomMargin;
|
float _bottomMargin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_Text3DOverlay_h
|
#endif // hifi_Text3DOverlay_h
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Centered local bounding box
|
// Centered local bounding box
|
||||||
AABox _localBoundingBox;
|
AABox _localBoundingBox{ vec3(0.0f), 1.0f };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -101,11 +101,18 @@ void Web3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, true, false, false, true);
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color);
|
DependencyManager::get<GeometryCache>()->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color);
|
||||||
batch.setResourceTexture(0, args->_whiteTexture); // restore default white color after me
|
batch.setResourceTexture(0, args->_whiteTexture); // restore default white color after me
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render::ShapeKey Web3DOverlay::getShapeKey() {
|
||||||
|
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
||||||
|
if (getAlpha() != 1.0f) {
|
||||||
|
builder.withTranslucent();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
void Web3DOverlay::setProperties(const QScriptValue &properties) {
|
void Web3DOverlay::setProperties(const QScriptValue &properties) {
|
||||||
Billboard3DOverlay::setProperties(properties);
|
Billboard3DOverlay::setProperties(properties);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
virtual ~Web3DOverlay();
|
virtual ~Web3DOverlay();
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
virtual const render::ShapeKey getShapeKey() override;
|
||||||
|
|
||||||
virtual void update(float deltatime);
|
virtual void update(float deltatime);
|
||||||
|
|
||||||
|
|
|
@ -511,9 +511,10 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferUnit) {
|
void DeferredLightingEffect::setupBatch(gpu::Batch& batch, int lightBufferUnit) {
|
||||||
|
PerformanceTimer perfTimer("DLE->setupBatch()");
|
||||||
auto globalLight = _allocatedLights[_globalLights.front()];
|
auto globalLight = _allocatedLights[_globalLights.front()];
|
||||||
args->_batch->setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());
|
batch.setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
|
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
void prepare(RenderArgs* args);
|
void prepare(RenderArgs* args);
|
||||||
void render(const render::RenderContextPointer& renderContext);
|
void render(const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
void setupTransparent(RenderArgs* args, int lightBufferUnit);
|
void setupBatch(gpu::Batch& batch, int lightBufferUnit);
|
||||||
|
|
||||||
// update global lighting
|
// update global lighting
|
||||||
void setAmbientLightMode(int preset);
|
void setAmbientLightMode(int preset);
|
||||||
|
|
|
@ -494,10 +494,22 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
|
||||||
return INSTANCED_SOLID_STREAM_FORMAT;
|
return INSTANCED_SOLID_STREAM_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render::ShapePipelinePointer GeometryCache::_simplePipeline;
|
||||||
|
|
||||||
GeometryCache::GeometryCache() :
|
GeometryCache::GeometryCache() :
|
||||||
_nextID(0)
|
_nextID(0)
|
||||||
{
|
{
|
||||||
buildShapes();
|
buildShapes();
|
||||||
|
GeometryCache::_simplePipeline =
|
||||||
|
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,
|
||||||
|
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||||
|
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
|
||||||
|
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GeometryCache::~GeometryCache() {
|
GeometryCache::~GeometryCache() {
|
||||||
|
@ -536,14 +548,6 @@ void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, siz
|
||||||
_shapes[shape].drawWireInstances(batch, count);
|
_shapes[shape].drawWireInstances(batch, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
|
|
||||||
renderShapeInstances(batch, Cube, count, colorBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
|
|
||||||
renderWireShapeInstances(batch, Cube, count, colorBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeometryCache::renderCube(gpu::Batch& batch) {
|
void GeometryCache::renderCube(gpu::Batch& batch) {
|
||||||
renderShape(batch, Cube);
|
renderShape(batch, Cube);
|
||||||
}
|
}
|
||||||
|
@ -552,10 +556,6 @@ void GeometryCache::renderWireCube(gpu::Batch& batch) {
|
||||||
renderWireShape(batch, Cube);
|
renderWireShape(batch, Cube);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer) {
|
|
||||||
renderShapeInstances(batch, Sphere, count, colorBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeometryCache::renderSphere(gpu::Batch& batch) {
|
void GeometryCache::renderSphere(gpu::Batch& batch) {
|
||||||
renderShape(batch, Sphere);
|
renderShape(batch, Sphere);
|
||||||
}
|
}
|
||||||
|
@ -756,7 +756,9 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
|
||||||
#endif // def WANT_DEBUG
|
#endif // def WANT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 2;
|
const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals
|
||||||
|
const int NUM_POS_COORDS = 2;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
details.isCreated = true;
|
details.isCreated = true;
|
||||||
details.vertices = points.size();
|
details.vertices = points.size();
|
||||||
details.vertexSize = FLOATS_PER_VERTEX;
|
details.vertexSize = FLOATS_PER_VERTEX;
|
||||||
|
@ -772,6 +774,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
|
@ -791,9 +794,13 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
|
||||||
int* colorData = new int[details.vertices];
|
int* colorData = new int[details.vertices];
|
||||||
int* colorDataAt = colorData;
|
int* colorDataAt = colorData;
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
|
||||||
foreach (const glm::vec2& point, points) {
|
foreach (const glm::vec2& point, points) {
|
||||||
*(vertex++) = point.x;
|
*(vertex++) = point.x;
|
||||||
*(vertex++) = point.y;
|
*(vertex++) = point.y;
|
||||||
|
*(vertex++) = NORMAL.x;
|
||||||
|
*(vertex++) = NORMAL.y;
|
||||||
|
*(vertex++) = NORMAL.z;
|
||||||
|
|
||||||
*(colorDataAt++) = compactColor;
|
*(colorDataAt++) = compactColor;
|
||||||
}
|
}
|
||||||
|
@ -817,7 +824,9 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
|
||||||
#endif // def WANT_DEBUG
|
#endif // def WANT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 3;
|
const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals
|
||||||
|
const int NUM_POS_COORDS = 3;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
details.isCreated = true;
|
details.isCreated = true;
|
||||||
details.vertices = points.size();
|
details.vertices = points.size();
|
||||||
details.vertexSize = FLOATS_PER_VERTEX;
|
details.vertexSize = FLOATS_PER_VERTEX;
|
||||||
|
@ -833,6 +842,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
|
@ -852,10 +862,14 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
|
||||||
int* colorData = new int[details.vertices];
|
int* colorData = new int[details.vertices];
|
||||||
int* colorDataAt = colorData;
|
int* colorDataAt = colorData;
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
|
||||||
foreach (const glm::vec3& point, points) {
|
foreach (const glm::vec3& point, points) {
|
||||||
*(vertex++) = point.x;
|
*(vertex++) = point.x;
|
||||||
*(vertex++) = point.y;
|
*(vertex++) = point.y;
|
||||||
*(vertex++) = point.z;
|
*(vertex++) = point.z;
|
||||||
|
*(vertex++) = NORMAL.x;
|
||||||
|
*(vertex++) = NORMAL.y;
|
||||||
|
*(vertex++) = NORMAL.z;
|
||||||
|
|
||||||
*(colorDataAt++) = compactColor;
|
*(colorDataAt++) = compactColor;
|
||||||
}
|
}
|
||||||
|
@ -880,7 +894,11 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
|
||||||
#endif // def WANT_DEBUG
|
#endif // def WANT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 5;
|
const int FLOATS_PER_VERTEX = 3 + 3 + 2; // vertices + normals + tex coords
|
||||||
|
const int NUM_POS_COORDS = 3;
|
||||||
|
const int NUM_NORMAL_COORDS = 3;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
|
const int VERTEX_TEX_OFFSET = VERTEX_NORMAL_OFFSET + NUM_NORMAL_COORDS * sizeof(float);
|
||||||
details.isCreated = true;
|
details.isCreated = true;
|
||||||
details.vertices = points.size();
|
details.vertices = points.size();
|
||||||
details.vertexSize = FLOATS_PER_VERTEX;
|
details.vertexSize = FLOATS_PER_VERTEX;
|
||||||
|
@ -896,7 +914,8 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), 3 * sizeof(float));
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEX_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
|
@ -918,12 +937,16 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
|
||||||
int* colorData = new int[details.vertices];
|
int* colorData = new int[details.vertices];
|
||||||
int* colorDataAt = colorData;
|
int* colorDataAt = colorData;
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < points.size(); i++) {
|
||||||
glm::vec3 point = points[i];
|
glm::vec3 point = points[i];
|
||||||
glm::vec2 texCoord = texCoords[i];
|
glm::vec2 texCoord = texCoords[i];
|
||||||
*(vertex++) = point.x;
|
*(vertex++) = point.x;
|
||||||
*(vertex++) = point.y;
|
*(vertex++) = point.y;
|
||||||
*(vertex++) = point.z;
|
*(vertex++) = point.z;
|
||||||
|
*(vertex++) = NORMAL.x;
|
||||||
|
*(vertex++) = NORMAL.y;
|
||||||
|
*(vertex++) = NORMAL.z;
|
||||||
*(vertex++) = texCoord.x;
|
*(vertex++) = texCoord.x;
|
||||||
*(vertex++) = texCoord.y;
|
*(vertex++) = texCoord.y;
|
||||||
|
|
||||||
|
@ -1073,8 +1096,10 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co
|
||||||
#endif // def WANT_DEBUG
|
#endif // def WANT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 2; // vertices
|
const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals
|
||||||
const int VERTICES = 4; // 1 quad = 4 vertices
|
const int VERTICES = 4; // 1 quad = 4 vertices
|
||||||
|
const int NUM_POS_COORDS = 2;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
|
|
||||||
if (!details.isCreated) {
|
if (!details.isCreated) {
|
||||||
|
|
||||||
|
@ -1093,17 +1118,19 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
||||||
|
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
|
||||||
float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {
|
float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {
|
||||||
minCorner.x, minCorner.y,
|
minCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
maxCorner.x, minCorner.y,
|
maxCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
minCorner.x, maxCorner.y,
|
minCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
maxCorner.x, maxCorner.y,
|
maxCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
};
|
};
|
||||||
|
|
||||||
const int NUM_COLOR_SCALARS_PER_QUAD = 4;
|
const int NUM_COLOR_SCALARS_PER_QUAD = 4;
|
||||||
|
@ -1158,10 +1185,12 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co
|
||||||
#endif // def WANT_DEBUG
|
#endif // def WANT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 2 * 2; // text coords & vertices
|
const int FLOATS_PER_VERTEX = 2 + 3 + 2; // vertices + normals + tex coords
|
||||||
const int VERTICES = 4; // 1 quad = 4 vertices
|
const int VERTICES = 4; // 1 quad = 4 vertices
|
||||||
const int NUM_POS_COORDS = 2;
|
const int NUM_POS_COORDS = 2;
|
||||||
const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float);
|
const int NUM_NORMAL_COORDS = 3;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
|
const int VERTEX_TEXCOORD_OFFSET = VERTEX_NORMAL_OFFSET + NUM_NORMAL_COORDS * sizeof(float);
|
||||||
|
|
||||||
if (!details.isCreated) {
|
if (!details.isCreated) {
|
||||||
|
|
||||||
|
@ -1181,7 +1210,9 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co
|
||||||
details.streamFormat = streamFormat;
|
details.streamFormat = streamFormat;
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
|
// zzmp: fix the normal across all renderQuad
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET);
|
details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
|
@ -1189,11 +1220,12 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co
|
||||||
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
||||||
|
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
|
||||||
float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {
|
float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {
|
||||||
minCorner.x, minCorner.y, texCoordMinCorner.x, texCoordMinCorner.y,
|
minCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMinCorner.x, texCoordMinCorner.y,
|
||||||
maxCorner.x, minCorner.y, texCoordMaxCorner.x, texCoordMinCorner.y,
|
maxCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMaxCorner.x, texCoordMinCorner.y,
|
||||||
minCorner.x, maxCorner.y, texCoordMinCorner.x, texCoordMaxCorner.y,
|
minCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMinCorner.x, texCoordMaxCorner.y,
|
||||||
maxCorner.x, maxCorner.y, texCoordMaxCorner.x, texCoordMaxCorner.y,
|
maxCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMaxCorner.x, texCoordMaxCorner.y,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1235,8 +1267,10 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co
|
||||||
#endif // def WANT_DEBUG
|
#endif // def WANT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 3; // vertices
|
const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals
|
||||||
const int VERTICES = 4; // 1 quad = 4 vertices
|
const int VERTICES = 4; // 1 quad = 4 vertices
|
||||||
|
const int NUM_POS_COORDS = 3;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
|
|
||||||
if (!details.isCreated) {
|
if (!details.isCreated) {
|
||||||
|
|
||||||
|
@ -1257,17 +1291,19 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
||||||
|
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
|
||||||
float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {
|
float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {
|
||||||
minCorner.x, minCorner.y, minCorner.z,
|
minCorner.x, minCorner.y, minCorner.z, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
maxCorner.x, minCorner.y, minCorner.z,
|
maxCorner.x, minCorner.y, minCorner.z, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
minCorner.x, maxCorner.y, maxCorner.z,
|
minCorner.x, maxCorner.y, maxCorner.z, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
maxCorner.x, maxCorner.y, maxCorner.z,
|
maxCorner.x, maxCorner.y, maxCorner.z, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
};
|
};
|
||||||
|
|
||||||
const int NUM_COLOR_SCALARS_PER_QUAD = 4;
|
const int NUM_COLOR_SCALARS_PER_QUAD = 4;
|
||||||
|
@ -1327,10 +1363,13 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons
|
||||||
#endif // def WANT_DEBUG
|
#endif // def WANT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 3 + 2; // 3d vertices + text coords
|
const int FLOATS_PER_VERTEX = 3 + 3 + 2; // vertices + normals + tex coords
|
||||||
const int VERTICES = 4; // 1 quad = 4 vertices
|
const int VERTICES = 4; // 1 quad = 4 vertices
|
||||||
const int NUM_POS_COORDS = 3;
|
const int NUM_POS_COORDS = 3;
|
||||||
const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float);
|
const int NUM_NORMAL_COORDS = 3;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
|
const int VERTEX_TEXCOORD_OFFSET = VERTEX_NORMAL_OFFSET + NUM_NORMAL_COORDS * sizeof(float);
|
||||||
|
|
||||||
|
|
||||||
if (!details.isCreated) {
|
if (!details.isCreated) {
|
||||||
|
|
||||||
|
@ -1349,6 +1388,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET);
|
details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
|
@ -1356,12 +1396,13 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons
|
||||||
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
||||||
|
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
|
||||||
float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {
|
float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {
|
||||||
bottomLeft.x, bottomLeft.y, bottomLeft.z, texCoordBottomLeft.x, texCoordBottomLeft.y,
|
bottomLeft.x, bottomLeft.y, bottomLeft.z, NORMAL.x, NORMAL.y, NORMAL.z, texCoordBottomLeft.x, texCoordBottomLeft.y,
|
||||||
bottomRight.x, bottomRight.y, bottomRight.z, texCoordBottomRight.x, texCoordBottomRight.y,
|
bottomRight.x, bottomRight.y, bottomRight.z, NORMAL.x, NORMAL.y, NORMAL.z, texCoordBottomRight.x, texCoordBottomRight.y,
|
||||||
topLeft.x, topLeft.y, topLeft.z, texCoordTopLeft.x, texCoordTopLeft.y,
|
topLeft.x, topLeft.y, topLeft.z, NORMAL.x, NORMAL.y, NORMAL.z, texCoordTopLeft.x, texCoordTopLeft.y,
|
||||||
topRight.x, topRight.y, topRight.z, texCoordTopRight.x, texCoordTopRight.y,
|
topRight.x, topRight.y, topRight.z, NORMAL.x, NORMAL.y, NORMAL.z, texCoordTopRight.x, texCoordTopRight.y,
|
||||||
};
|
};
|
||||||
|
|
||||||
const int NUM_COLOR_SCALARS_PER_QUAD = 4;
|
const int NUM_COLOR_SCALARS_PER_QUAD = 4;
|
||||||
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
||||||
|
@ -1414,7 +1455,9 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start,
|
||||||
glm::vec3 dashVector = segmentVector / SEGMENT_LENGTH * dash_length;
|
glm::vec3 dashVector = segmentVector / SEGMENT_LENGTH * dash_length;
|
||||||
glm::vec3 gapVector = segmentVector / SEGMENT_LENGTH * gap_length;
|
glm::vec3 gapVector = segmentVector / SEGMENT_LENGTH * gap_length;
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 3;
|
const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals
|
||||||
|
const int NUM_POS_COORDS = 3;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
details.vertices = (segmentCountFloor + 1) * 2;
|
details.vertices = (segmentCountFloor + 1) * 2;
|
||||||
details.vertexSize = FLOATS_PER_VERTEX;
|
details.vertexSize = FLOATS_PER_VERTEX;
|
||||||
details.isCreated = true;
|
details.isCreated = true;
|
||||||
|
@ -1430,6 +1473,7 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start,
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
|
@ -1441,10 +1485,14 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start,
|
||||||
float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
|
float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
|
||||||
float* vertex = vertexData;
|
float* vertex = vertexData;
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(1.0f, 0.0f, 0.0f);
|
||||||
glm::vec3 point = start;
|
glm::vec3 point = start;
|
||||||
*(vertex++) = point.x;
|
*(vertex++) = point.x;
|
||||||
*(vertex++) = point.y;
|
*(vertex++) = point.y;
|
||||||
*(vertex++) = point.z;
|
*(vertex++) = point.z;
|
||||||
|
*(vertex++) = NORMAL.x;
|
||||||
|
*(vertex++) = NORMAL.y;
|
||||||
|
*(vertex++) = NORMAL.z;
|
||||||
*(colorDataAt++) = compactColor;
|
*(colorDataAt++) = compactColor;
|
||||||
|
|
||||||
for (int i = 0; i < segmentCountFloor; i++) {
|
for (int i = 0; i < segmentCountFloor; i++) {
|
||||||
|
@ -1452,17 +1500,26 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start,
|
||||||
*(vertex++) = point.x;
|
*(vertex++) = point.x;
|
||||||
*(vertex++) = point.y;
|
*(vertex++) = point.y;
|
||||||
*(vertex++) = point.z;
|
*(vertex++) = point.z;
|
||||||
|
*(vertex++) = NORMAL.x;
|
||||||
|
*(vertex++) = NORMAL.y;
|
||||||
|
*(vertex++) = NORMAL.z;
|
||||||
*(colorDataAt++) = compactColor;
|
*(colorDataAt++) = compactColor;
|
||||||
|
|
||||||
point += gapVector;
|
point += gapVector;
|
||||||
*(vertex++) = point.x;
|
*(vertex++) = point.x;
|
||||||
*(vertex++) = point.y;
|
*(vertex++) = point.y;
|
||||||
*(vertex++) = point.z;
|
*(vertex++) = point.z;
|
||||||
|
*(vertex++) = NORMAL.x;
|
||||||
|
*(vertex++) = NORMAL.y;
|
||||||
|
*(vertex++) = NORMAL.z;
|
||||||
*(colorDataAt++) = compactColor;
|
*(colorDataAt++) = compactColor;
|
||||||
}
|
}
|
||||||
*(vertex++) = end.x;
|
*(vertex++) = end.x;
|
||||||
*(vertex++) = end.y;
|
*(vertex++) = end.y;
|
||||||
*(vertex++) = end.z;
|
*(vertex++) = end.z;
|
||||||
|
*(vertex++) = NORMAL.x;
|
||||||
|
*(vertex++) = NORMAL.y;
|
||||||
|
*(vertex++) = NORMAL.z;
|
||||||
*(colorDataAt++) = compactColor;
|
*(colorDataAt++) = compactColor;
|
||||||
|
|
||||||
details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
|
details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
|
||||||
|
@ -1569,7 +1626,9 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm
|
||||||
#endif // def WANT_DEBUG
|
#endif // def WANT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLOATS_PER_VERTEX = 3;
|
const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals
|
||||||
|
const int NUM_POS_COORDS = 3;
|
||||||
|
const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
const int vertices = 2;
|
const int vertices = 2;
|
||||||
if (!details.isCreated) {
|
if (!details.isCreated) {
|
||||||
|
|
||||||
|
@ -1588,13 +1647,16 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm
|
||||||
details.stream = stream;
|
details.stream = stream;
|
||||||
|
|
||||||
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);
|
||||||
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
|
|
||||||
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
||||||
|
|
||||||
|
const glm::vec3 NORMAL(1.0f, 0.0f, 0.0f);
|
||||||
float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { p1.x, p1.y, p1.z, p2.x, p2.y, p2.z };
|
float vertexBuffer[vertices * FLOATS_PER_VERTEX] = {
|
||||||
|
p1.x, p1.y, p1.z, NORMAL.x, NORMAL.y, NORMAL.z,
|
||||||
|
p2.x, p2.y, p2.z, NORMAL.x, NORMAL.y, NORMAL.z};
|
||||||
|
|
||||||
const int NUM_COLOR_SCALARS = 2;
|
const int NUM_COLOR_SCALARS = 2;
|
||||||
int colors[NUM_COLOR_SCALARS] = { compactColor1, compactColor2 };
|
int colors[NUM_COLOR_SCALARS] = { compactColor1, compactColor2 };
|
||||||
|
@ -1781,7 +1843,23 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) {
|
||||||
return a.getRaw() == b.getRaw();
|
return a.getRaw() == b.getRaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::PipelinePointer GeometryCache::getPipeline(SimpleProgramKey config) {
|
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 (!textured) {
|
||||||
|
batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP,
|
||||||
|
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||||
|
}
|
||||||
|
// Set a default normal map
|
||||||
|
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
|
||||||
|
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool emissive, bool depthBiased) {
|
||||||
|
SimpleProgramKey config{textured, culled, emissive, depthBiased};
|
||||||
|
|
||||||
|
// Compile the shaders
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
std::call_once(once, [&]() {
|
std::call_once(once, [&]() {
|
||||||
auto VS = gpu::Shader::createVertex(std::string(simple_vert));
|
auto VS = gpu::Shader::createVertex(std::string(simple_vert));
|
||||||
|
@ -1796,13 +1874,14 @@ gpu::PipelinePointer GeometryCache::getPipeline(SimpleProgramKey config) {
|
||||||
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
|
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
|
||||||
gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
|
gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If the pipeline already exists, return it
|
||||||
auto it = _simplePrograms.find(config);
|
auto it = _simplePrograms.find(config);
|
||||||
if (it != _simplePrograms.end()) {
|
if (it != _simplePrograms.end()) {
|
||||||
return it.value();
|
return it.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.isCulled()) {
|
||||||
state->setCullMode(gpu::State::CULL_BACK);
|
state->setCullMode(gpu::State::CULL_BACK);
|
||||||
|
@ -1815,33 +1894,15 @@ gpu::PipelinePointer GeometryCache::getPipeline(SimpleProgramKey config) {
|
||||||
state->setDepthBiasSlopeScale(1.0f);
|
state->setDepthBiasSlopeScale(1.0f);
|
||||||
}
|
}
|
||||||
state->setBlendFunction(false,
|
state->setBlendFunction(false,
|
||||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
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);
|
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||||
|
|
||||||
gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
|
gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
|
||||||
gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state);
|
gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state);
|
||||||
_simplePrograms.insert(config, pipeline);
|
_simplePrograms.insert(config, pipeline);
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::PipelinePointer GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
|
|
||||||
bool emissive, bool depthBias) {
|
|
||||||
SimpleProgramKey config{textured, culled, emissive, depthBias};
|
|
||||||
gpu::PipelinePointer pipeline = getPipeline(config);
|
|
||||||
batch.setPipeline(pipeline);
|
|
||||||
|
|
||||||
gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
|
|
||||||
|
|
||||||
if (!config.isTextured()) {
|
|
||||||
// If it is not textured, bind white texture and keep using textured pipeline
|
|
||||||
batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
|
||||||
}
|
|
||||||
|
|
||||||
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
|
|
||||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
|
||||||
return pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t toCompactColor(const glm::vec4& color) {
|
uint32_t toCompactColor(const glm::vec4& color) {
|
||||||
uint32_t compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
uint32_t compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
||||||
((int(color.y * 255.0f) & 0xFF) << 8) |
|
((int(color.y * 255.0f) & 0xFF) << 8) |
|
||||||
|
@ -1852,46 +1913,51 @@ uint32_t toCompactColor(const glm::vec4& color) {
|
||||||
|
|
||||||
static const size_t INSTANCE_COLOR_BUFFER = 0;
|
static const size_t INSTANCE_COLOR_BUFFER = 0;
|
||||||
|
|
||||||
template <typename F>
|
void renderInstances(const std::string& name, gpu::Batch& batch, const glm::vec4& color, bool isWire,
|
||||||
void renderInstances(const std::string& name, gpu::Batch& batch, const glm::vec4& color, F f) {
|
const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) {
|
||||||
|
// Add pipeline to name
|
||||||
|
std::string instanceName = name + std::to_string(std::hash<render::ShapePipelinePointer>()(pipeline));
|
||||||
|
|
||||||
|
// Add color to named buffer
|
||||||
{
|
{
|
||||||
gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(name, INSTANCE_COLOR_BUFFER);
|
gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(instanceName, INSTANCE_COLOR_BUFFER);
|
||||||
auto compactColor = toCompactColor(color);
|
auto compactColor = toCompactColor(color);
|
||||||
instanceColorBuffer->append(compactColor);
|
instanceColorBuffer->append(compactColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.setupNamedCalls(name, [f](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
// Add call to named buffer
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
batch.setupNamedCalls(instanceName, [isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||||
f(batch, data);
|
batch.setPipeline(pipeline->pipeline);
|
||||||
|
pipeline->prepare(batch);
|
||||||
|
|
||||||
|
if (isWire) {
|
||||||
|
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]);
|
||||||
|
} else {
|
||||||
|
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color) {
|
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
renderInstances(INSTANCE_NAME, batch, color, false, pipeline, GeometryCache::Sphere);
|
||||||
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, GeometryCache::Sphere, data.count(),
|
|
||||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color) {
|
void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
renderInstances(INSTANCE_NAME, batch, color, true, pipeline, GeometryCache::Sphere);
|
||||||
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, GeometryCache::Sphere, data.count(),
|
|
||||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable this in a debug build to cause 'box' entities to iterate through all the
|
// Enable this in a debug build to cause 'box' entities to iterate through all the
|
||||||
// available shape types, both solid and wireframes
|
// available shape types, both solid and wireframes
|
||||||
//#define DEBUG_SHAPES
|
//#define DEBUG_SHAPES
|
||||||
|
|
||||||
void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color) {
|
void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||||
|
|
||||||
#ifdef DEBUG_SHAPES
|
#ifdef DEBUG_SHAPES
|
||||||
static auto startTime = usecTimestampNow();
|
static auto startTime = usecTimestampNow();
|
||||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||||
|
|
||||||
auto usecs = usecTimestampNow();
|
auto usecs = usecTimestampNow();
|
||||||
usecs -= startTime;
|
usecs -= startTime;
|
||||||
|
@ -1916,26 +1982,17 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4&
|
||||||
|
|
||||||
// For the first half second for a given shape, show the wireframe, for the second half, show the solid.
|
// For the first half second for a given shape, show the wireframe, for the second half, show the solid.
|
||||||
if (fractionalSeconds > 0.5f) {
|
if (fractionalSeconds > 0.5f) {
|
||||||
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, shape, data.count(),
|
renderInstances(INSTANCE_NAME, batch, color, true, pipeline, shape);
|
||||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count(),
|
renderInstances(INSTANCE_NAME, batch, color, false, pipeline, shape);
|
||||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
renderInstances(INSTANCE_NAME, batch, color, false, pipeline, GeometryCache::Cube);
|
||||||
DependencyManager::get<GeometryCache>()->renderCubeInstances(batch, data.count(),
|
|
||||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
|
||||||
});
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color) {
|
void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
renderInstances(INSTANCE_NAME, batch, color, true, pipeline, GeometryCache::Cube);
|
||||||
DependencyManager::get<GeometryCache>()->renderWireCubeInstances(batch, data.count(),
|
|
||||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,45 +150,55 @@ public:
|
||||||
static const int UNKNOWN_ID;
|
static const int UNKNOWN_ID;
|
||||||
|
|
||||||
|
|
||||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
// Bind the pipeline and get the state to render static geometry
|
||||||
gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||||
bool emissive = false, bool depthBias = false);
|
bool emissive = false, bool depthBias = false);
|
||||||
|
// Get the pipeline to render static geometry
|
||||||
|
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true,
|
||||||
|
bool emissive = false, bool depthBias = false);
|
||||||
|
render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; }
|
||||||
|
|
||||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color);
|
// Static (instanced) geometry
|
||||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color) {
|
|
||||||
renderSolidSphereInstance(batch, glm::vec4(color, 1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color);
|
|
||||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color) {
|
|
||||||
renderWireSphereInstance(batch, glm::vec4(color, 1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color);
|
|
||||||
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color) {
|
|
||||||
renderSolidCubeInstance(batch, glm::vec4(color, 1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color);
|
|
||||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color) {
|
|
||||||
renderWireCubeInstance(batch, glm::vec4(color, 1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||||
|
|
||||||
|
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||||
|
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||||
|
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||||
|
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||||
|
renderSolidSphereInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||||
|
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||||
|
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||||
|
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||||
|
renderWireSphereInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||||
|
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||||
|
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||||
|
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||||
|
renderSolidCubeInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||||
|
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||||
|
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||||
|
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||||
|
renderWireCubeInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamic geometry
|
||||||
void renderShape(gpu::Batch& batch, Shape shape);
|
void renderShape(gpu::Batch& batch, Shape shape);
|
||||||
void renderWireShape(gpu::Batch& batch, Shape shape);
|
void renderWireShape(gpu::Batch& batch, Shape shape);
|
||||||
size_t getShapeTriangleCount(Shape shape);
|
size_t getShapeTriangleCount(Shape shape);
|
||||||
|
|
||||||
void renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
|
|
||||||
void renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
|
|
||||||
void renderCube(gpu::Batch& batch);
|
void renderCube(gpu::Batch& batch);
|
||||||
void renderWireCube(gpu::Batch& batch);
|
void renderWireCube(gpu::Batch& batch);
|
||||||
size_t getCubeTriangleCount();
|
size_t getCubeTriangleCount();
|
||||||
|
|
||||||
void renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
|
|
||||||
void renderWireSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer colorBuffer);
|
|
||||||
void renderSphere(gpu::Batch& batch);
|
void renderSphere(gpu::Batch& batch);
|
||||||
void renderWireSphere(gpu::Batch& batch);
|
void renderWireSphere(gpu::Batch& batch);
|
||||||
size_t getSphereTriangleCount();
|
size_t getSphereTriangleCount();
|
||||||
|
@ -364,11 +374,9 @@ private:
|
||||||
|
|
||||||
QHash<QUrl, QWeakPointer<NetworkGeometry> > _networkGeometry;
|
QHash<QUrl, QWeakPointer<NetworkGeometry> > _networkGeometry;
|
||||||
|
|
||||||
|
|
||||||
gpu::PipelinePointer getPipeline(SimpleProgramKey config);
|
|
||||||
|
|
||||||
gpu::ShaderPointer _simpleShader;
|
gpu::ShaderPointer _simpleShader;
|
||||||
gpu::ShaderPointer _emissiveShader;
|
gpu::ShaderPointer _emissiveShader;
|
||||||
|
static render::ShapePipelinePointer _simplePipeline;
|
||||||
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -225,8 +225,6 @@ void MeshPartPayload::render(RenderArgs* args) const {
|
||||||
|
|
||||||
gpu::Batch& batch = *(args->_batch);
|
gpu::Batch& batch = *(args->_batch);
|
||||||
|
|
||||||
ShapeKey key = getShapeKey();
|
|
||||||
|
|
||||||
auto locations = args->_pipeline->locations;
|
auto locations = args->_pipeline->locations;
|
||||||
assert(locations);
|
assert(locations);
|
||||||
|
|
||||||
|
@ -239,13 +237,6 @@ void MeshPartPayload::render(RenderArgs* args) const {
|
||||||
// apply material properties
|
// apply material properties
|
||||||
bindMaterial(batch, locations);
|
bindMaterial(batch, locations);
|
||||||
|
|
||||||
|
|
||||||
// TODO: We should be able to do that just in the renderTransparentJob
|
|
||||||
if (key.isTranslucent() && locations->lightBufferUnit >= 0) {
|
|
||||||
PerformanceTimer perfTimer("DLE->setupTransparent()");
|
|
||||||
|
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit);
|
|
||||||
}
|
|
||||||
if (args) {
|
if (args) {
|
||||||
args->_details._materialSwitches++;
|
args->_details._materialSwitches++;
|
||||||
}
|
}
|
||||||
|
@ -475,8 +466,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
|
||||||
|
|
||||||
gpu::Batch& batch = *(args->_batch);
|
gpu::Batch& batch = *(args->_batch);
|
||||||
|
|
||||||
ShapeKey key = getShapeKey();
|
if (!getShapeKey().isValid()) {
|
||||||
if (!key.isValid()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,13 +507,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
|
||||||
// apply material properties
|
// apply material properties
|
||||||
bindMaterial(batch, locations);
|
bindMaterial(batch, locations);
|
||||||
|
|
||||||
|
|
||||||
// TODO: We should be able to do that just in the renderTransparentJob
|
|
||||||
if (key.isTranslucent() && locations->lightBufferUnit >= 0) {
|
|
||||||
PerformanceTimer perfTimer("DLE->setupTransparent()");
|
|
||||||
|
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit);
|
|
||||||
}
|
|
||||||
if (args) {
|
if (args) {
|
||||||
args->_details._materialSwitches++;
|
args->_details._materialSwitches++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,8 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
|
||||||
addJob<DrawStatus>("DrawStatus", opaques, DrawStatus(statusIconMap));
|
addJob<DrawStatus>("DrawStatus", opaques, DrawStatus(statusIconMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
addJob<DrawOverlay3D>("DrawOverlay3D");
|
addJob<DrawOverlay3D>("DrawOverlay3DOpaque", ItemFilter::Builder::opaqueShape().withLayered());
|
||||||
|
addJob<DrawOverlay3D>("DrawOverlay3DTransparent", ItemFilter::Builder::transparentShape().withLayered());
|
||||||
|
|
||||||
addJob<HitEffect>("HitEffect");
|
addJob<HitEffect>("HitEffect");
|
||||||
|
|
||||||
|
@ -156,7 +157,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawOverlay3D::DrawOverlay3D() : _shapePlumber{ std::make_shared<ShapePlumber>() } {
|
DrawOverlay3D::DrawOverlay3D(ItemFilter filter) : _filter{ filter }, _shapePlumber{ std::make_shared<ShapePlumber>() } {
|
||||||
initOverlay3DPipelines(*_shapePlumber);
|
initOverlay3DPipelines(*_shapePlumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +167,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
|
||||||
|
|
||||||
// render backgrounds
|
// render backgrounds
|
||||||
auto& scene = sceneContext->_scene;
|
auto& scene = sceneContext->_scene;
|
||||||
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered());
|
auto& items = scene->getMasterBucket().at(_filter);
|
||||||
|
|
||||||
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
||||||
|
|
||||||
|
@ -179,7 +180,6 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
config->numItems = (int)inItems.size();
|
config->numItems = (int)inItems.size();
|
||||||
config->numDrawn = (int)inItems.size();
|
|
||||||
|
|
||||||
if (!inItems.empty()) {
|
if (!inItems.empty()) {
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
|
@ -87,14 +87,11 @@ public:
|
||||||
class DrawOverlay3DConfig : public render::Job::Config {
|
class DrawOverlay3DConfig : public render::Job::Config {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(int numItems READ getNumItems)
|
Q_PROPERTY(int numItems READ getNumItems)
|
||||||
Q_PROPERTY(int numDrawn READ getNumDrawn)
|
|
||||||
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
||||||
public:
|
public:
|
||||||
int getNumItems() { return numItems; }
|
int getNumItems() { return numItems; }
|
||||||
int getNumDrawn() { return numDrawn; }
|
|
||||||
|
|
||||||
int numItems{ 0 };
|
int numItems{ 0 };
|
||||||
int numDrawn{ 0 };
|
|
||||||
int maxDrawn{ -1 };
|
int maxDrawn{ -1 };
|
||||||
signals:
|
signals:
|
||||||
void dirty();
|
void dirty();
|
||||||
|
@ -105,12 +102,13 @@ public:
|
||||||
using Config = DrawOverlay3DConfig;
|
using Config = DrawOverlay3DConfig;
|
||||||
using JobModel = render::Job::Model<DrawOverlay3D, Config>;
|
using JobModel = render::Job::Model<DrawOverlay3D, Config>;
|
||||||
|
|
||||||
DrawOverlay3D();
|
DrawOverlay3D(render::ItemFilter filter);
|
||||||
|
|
||||||
void configure(const Config& config) { _maxDrawn = config.maxDrawn; }
|
void configure(const Config& config) { _maxDrawn = config.maxDrawn; }
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
render::ItemFilter _filter;
|
||||||
render::ShapePlumberPointer _shapePlumber;
|
render::ShapePlumberPointer _shapePlumber;
|
||||||
int _maxDrawn; // initialized by Config
|
int _maxDrawn; // initialized by Config
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <gpu/Context.h>
|
#include <gpu/Context.h>
|
||||||
#include <gpu/StandardShaderLib.h>
|
#include <gpu/StandardShaderLib.h>
|
||||||
|
|
||||||
|
#include "DeferredLightingEffect.h"
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "render/DrawTask.h"
|
#include "render/DrawTask.h"
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
#include "skin_model_normal_map_vert.h"
|
#include "skin_model_normal_map_vert.h"
|
||||||
|
|
||||||
#include "model_frag.h"
|
#include "model_frag.h"
|
||||||
|
#include "model_emissive_frag.h"
|
||||||
#include "model_shadow_frag.h"
|
#include "model_shadow_frag.h"
|
||||||
#include "model_normal_map_frag.h"
|
#include "model_normal_map_frag.h"
|
||||||
#include "model_normal_specular_map_frag.h"
|
#include "model_normal_specular_map_frag.h"
|
||||||
|
@ -35,9 +37,13 @@
|
||||||
#include "model_lightmap_normal_specular_map_frag.h"
|
#include "model_lightmap_normal_specular_map_frag.h"
|
||||||
#include "model_lightmap_specular_map_frag.h"
|
#include "model_lightmap_specular_map_frag.h"
|
||||||
#include "model_translucent_frag.h"
|
#include "model_translucent_frag.h"
|
||||||
|
#include "model_translucent_emissive_frag.h"
|
||||||
|
|
||||||
#include "overlay3D_vert.h"
|
#include "overlay3D_vert.h"
|
||||||
#include "overlay3D_frag.h"
|
#include "overlay3D_frag.h"
|
||||||
|
#include "overlay3D_translucent_frag.h"
|
||||||
|
#include "overlay3D_emissive_frag.h"
|
||||||
|
#include "overlay3D_translucent_emissive_frag.h"
|
||||||
|
|
||||||
#include "drawOpaqueStencil_frag.h"
|
#include "drawOpaqueStencil_frag.h"
|
||||||
|
|
||||||
|
@ -58,22 +64,85 @@ void initStencilPipeline(gpu::PipelinePointer& pipeline) {
|
||||||
pipeline = gpu::Pipeline::create(program, state);
|
pipeline = gpu::Pipeline::create(program, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initOverlay3DPipelines(ShapePlumber& plumber) {
|
gpu::BufferView getDefaultMaterialBuffer() {
|
||||||
auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert));
|
model::Material::Schema schema;
|
||||||
auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag));
|
schema._diffuse = vec3(1.0f);
|
||||||
auto program = gpu::Shader::createProgram(vs, ps);
|
schema._opacity = 1.0f;
|
||||||
|
schema._metallic = vec3(0.1f);
|
||||||
auto opaqueState = std::make_shared<gpu::State>();
|
schema._gloss = 10.0f;
|
||||||
opaqueState->setDepthTest(false);
|
return gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(model::Material::Schema), (const gpu::Byte*) &schema));
|
||||||
opaqueState->setBlendFunction(false);
|
|
||||||
|
|
||||||
plumber.addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
|
void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
|
||||||
if (pipeline.locations->normalFittingMapUnit > -1) {
|
// Set a default diffuse map
|
||||||
batch.setResourceTexture(pipeline.locations->normalFittingMapUnit,
|
batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP,
|
||||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||||
|
// Set a default normal map
|
||||||
|
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
|
||||||
|
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||||
|
// Set default coordinates
|
||||||
|
if (pipeline.locations->texcoordMatrices >= 0) {
|
||||||
|
static const glm::mat4 TEX_COORDS[2];
|
||||||
|
batch._glUniformMatrix4fv(pipeline.locations->texcoordMatrices, 2, false, (const float*)&TEX_COORDS);
|
||||||
|
}
|
||||||
|
// Set a default material
|
||||||
|
if (pipeline.locations->materialBufferUnit >= 0) {
|
||||||
|
static const gpu::BufferView OPAQUE_SCHEMA_BUFFER = getDefaultMaterialBuffer();
|
||||||
|
batch.setUniformBuffer(ShapePipeline::Slot::MATERIAL_GPU, OPAQUE_SCHEMA_BUFFER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
|
||||||
|
batchSetter(pipeline, batch);
|
||||||
|
// Set the light
|
||||||
|
if (pipeline.locations->lightBufferUnit >= 0) {
|
||||||
|
DependencyManager::get<DeferredLightingEffect>()->setupBatch(batch, pipeline.locations->lightBufferUnit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initOverlay3DPipelines(ShapePlumber& plumber) {
|
||||||
|
auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert));
|
||||||
|
auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag));
|
||||||
|
auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag));
|
||||||
|
auto pixelEmissive = gpu::Shader::createPixel(std::string(overlay3D_emissive_frag));
|
||||||
|
auto pixelTranslucentEmissive = gpu::Shader::createPixel(std::string(overlay3D_translucent_emissive_frag));
|
||||||
|
|
||||||
|
auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel);
|
||||||
|
auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent);
|
||||||
|
auto emissiveOpaqueProgram = gpu::Shader::createProgram(vertex, pixelEmissive);
|
||||||
|
auto emissiveTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentEmissive);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
bool isCulled = (i & 1);
|
||||||
|
bool isBiased = (i & 2);
|
||||||
|
bool isOpaque = (i & 4);
|
||||||
|
|
||||||
|
auto state = std::make_shared<gpu::State>();
|
||||||
|
state->setDepthTest(false);
|
||||||
|
state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE);
|
||||||
|
if (isBiased) {
|
||||||
|
state->setDepthBias(1.0f);
|
||||||
|
state->setDepthBiasSlopeScale(1.0f);
|
||||||
|
}
|
||||||
|
if (isOpaque) {
|
||||||
|
// Soft edges
|
||||||
|
state->setBlendFunction(true,
|
||||||
|
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||||
|
} else {
|
||||||
|
state->setBlendFunction(true,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapeKey::Filter::Builder builder;
|
||||||
|
isCulled ? builder.withCullFace() : builder.withoutCullFace();
|
||||||
|
isBiased ? builder.withDepthBias() : builder.withoutDepthBias();
|
||||||
|
isOpaque ? builder.withOpaque() : builder.withTranslucent();
|
||||||
|
|
||||||
|
auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram;
|
||||||
|
auto emissiveProgram = isOpaque ? emissiveOpaqueProgram : emissiveTranslucentProgram;
|
||||||
|
plumber.addPipeline(builder.withoutEmissive().build(), simpleProgram, state, &lightBatchSetter);
|
||||||
|
plumber.addPipeline(builder.withEmissive().build(), emissiveProgram, state, &batchSetter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,31 +151,43 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||||
using ShaderPointer = gpu::ShaderPointer;
|
using ShaderPointer = gpu::ShaderPointer;
|
||||||
|
|
||||||
auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) {
|
auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) {
|
||||||
auto state = std::make_shared<gpu::State>();
|
// These keyvalues' pipelines will be added by this lamdba in addition to the key passed
|
||||||
|
assert(!key.isWireFrame());
|
||||||
// Cull backface
|
assert(!key.isDepthBiased());
|
||||||
state->setCullMode(gpu::State::CULL_BACK);
|
assert(key.isCullFace());
|
||||||
|
|
||||||
// Z test depends on transparency
|
|
||||||
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);
|
|
||||||
|
|
||||||
// Blend if transparent
|
|
||||||
state->setBlendFunction(key.isTranslucent(),
|
|
||||||
// For transparency, keep the highlight intensity
|
|
||||||
gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
|
||||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
|
||||||
|
|
||||||
ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader);
|
ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader);
|
||||||
plumber.addPipeline(key, program, state, &pipelineBatchSetter);
|
|
||||||
|
|
||||||
// Add a wireframe version
|
for (int i = 0; i < 8; i++) {
|
||||||
if (!key.isWireFrame()) {
|
bool isCulled = (i & 1);
|
||||||
auto wireFrameKey = Key::Builder(key).withWireframe();
|
bool isBiased = (i & 2);
|
||||||
auto wireFrameState = std::make_shared<gpu::State>(state->getValues());
|
bool isWireframed = (i & 4);
|
||||||
|
|
||||||
wireFrameState->setFillMode(gpu::State::FILL_LINE);
|
ShapeKey::Builder builder(key);
|
||||||
|
auto state = std::make_shared<gpu::State>();
|
||||||
|
|
||||||
plumber.addPipeline(wireFrameKey, program, wireFrameState, &pipelineBatchSetter);
|
// Depth test depends on transparency
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!isCulled) {
|
||||||
|
builder.withoutCullFace();
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
plumber.addPipeline(builder.build(), program, state,
|
||||||
|
key.isTranslucent() ? &lightBatchSetter : &batchSetter);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,113 +203,99 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||||
|
|
||||||
// Pixel shaders
|
// Pixel shaders
|
||||||
auto modelPixel = gpu::Shader::createPixel(std::string(model_frag));
|
auto modelPixel = gpu::Shader::createPixel(std::string(model_frag));
|
||||||
|
auto modelEmissivePixel = gpu::Shader::createPixel(std::string(model_emissive_frag));
|
||||||
auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag));
|
auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag));
|
||||||
auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag));
|
auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag));
|
||||||
auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag));
|
auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag));
|
||||||
auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag));
|
auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag));
|
||||||
|
auto modelTranslucentEmissivePixel = gpu::Shader::createPixel(std::string(model_translucent_emissive_frag));
|
||||||
auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
|
auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
|
||||||
auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag));
|
auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag));
|
||||||
auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag));
|
auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag));
|
||||||
auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag));
|
auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag));
|
||||||
auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag));
|
auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag));
|
||||||
|
|
||||||
// Fill the pipelineLib
|
// TODO: Refactor this to use a filter
|
||||||
|
// Opaques
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder(),
|
Key::Builder(),
|
||||||
modelVertex, modelPixel);
|
modelVertex, modelPixel);
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withEmissive(),
|
||||||
|
modelVertex, modelEmissivePixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withTangents(),
|
Key::Builder().withTangents(),
|
||||||
modelNormalMapVertex, modelNormalMapPixel);
|
modelNormalMapVertex, modelNormalMapPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSpecular(),
|
Key::Builder().withSpecular(),
|
||||||
modelVertex, modelSpecularMapPixel);
|
modelVertex, modelSpecularMapPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withTangents().withSpecular(),
|
Key::Builder().withTangents().withSpecular(),
|
||||||
modelNormalMapVertex, modelNormalSpecularMapPixel);
|
modelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||||
|
// Translucents
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withTranslucent(),
|
Key::Builder().withTranslucent(),
|
||||||
modelVertex, modelTranslucentPixel);
|
modelVertex, modelTranslucentPixel);
|
||||||
// FIXME Ignore lightmap for translucents meshpart
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
|
Key::Builder().withTranslucent().withEmissive(),
|
||||||
|
modelVertex, modelTranslucentEmissivePixel);
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTranslucent().withTangents(),
|
||||||
|
modelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTranslucent().withSpecular(),
|
||||||
|
modelVertex, modelTranslucentPixel);
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTranslucent().withTangents().withSpecular(),
|
||||||
|
modelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
addPipeline(
|
||||||
|
// FIXME: Ignore lightmap for translucents meshpart
|
||||||
Key::Builder().withTranslucent().withLightmap(),
|
Key::Builder().withTranslucent().withLightmap(),
|
||||||
modelVertex, modelTranslucentPixel);
|
modelVertex, modelTranslucentPixel);
|
||||||
|
// Lightmapped
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withTangents().withTranslucent(),
|
|
||||||
modelNormalMapVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSpecular().withTranslucent(),
|
|
||||||
modelVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withTangents().withSpecular().withTranslucent(),
|
|
||||||
modelNormalMapVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withLightmap(),
|
Key::Builder().withLightmap(),
|
||||||
modelLightmapVertex, modelLightmapPixel);
|
modelLightmapVertex, modelLightmapPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withLightmap().withTangents(),
|
Key::Builder().withLightmap().withTangents(),
|
||||||
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);
|
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withLightmap().withSpecular(),
|
Key::Builder().withLightmap().withSpecular(),
|
||||||
modelLightmapVertex, modelLightmapSpecularMapPixel);
|
modelLightmapVertex, modelLightmapSpecularMapPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withLightmap().withTangents().withSpecular(),
|
Key::Builder().withLightmap().withTangents().withSpecular(),
|
||||||
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
|
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
|
||||||
|
// Skinned
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned(),
|
Key::Builder().withSkinned(),
|
||||||
skinModelVertex, modelPixel);
|
skinModelVertex, modelPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned().withTangents(),
|
Key::Builder().withSkinned().withTangents(),
|
||||||
skinModelNormalMapVertex, modelNormalMapPixel);
|
skinModelNormalMapVertex, modelNormalMapPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned().withSpecular(),
|
Key::Builder().withSkinned().withSpecular(),
|
||||||
skinModelVertex, modelSpecularMapPixel);
|
skinModelVertex, modelSpecularMapPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned().withTangents().withSpecular(),
|
Key::Builder().withSkinned().withTangents().withSpecular(),
|
||||||
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
|
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||||
|
// Skinned and Translucent
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned().withTranslucent(),
|
Key::Builder().withSkinned().withTranslucent(),
|
||||||
skinModelVertex, modelTranslucentPixel);
|
skinModelVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned().withTangents().withTranslucent(),
|
Key::Builder().withSkinned().withTranslucent().withTangents(),
|
||||||
skinModelNormalMapVertex, modelTranslucentPixel);
|
skinModelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned().withSpecular().withTranslucent(),
|
Key::Builder().withSkinned().withTranslucent().withSpecular(),
|
||||||
skinModelVertex, modelTranslucentPixel);
|
skinModelVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(),
|
Key::Builder().withSkinned().withTranslucent().withTangents().withSpecular(),
|
||||||
skinModelNormalMapVertex, modelTranslucentPixel);
|
skinModelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
// Depth-only
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withDepthOnly(),
|
Key::Builder().withDepthOnly(),
|
||||||
modelShadowVertex, modelShadowPixel);
|
modelShadowVertex, modelShadowPixel);
|
||||||
|
|
||||||
|
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withSkinned().withDepthOnly(),
|
Key::Builder().withSkinned().withDepthOnly(),
|
||||||
skinModelShadowVertex, modelShadowPixel);
|
skinModelShadowVertex, modelShadowPixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,12 +72,12 @@ float TextRenderer3D::getFontSize() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color,
|
void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color,
|
||||||
const glm::vec2& bounds) {
|
const glm::vec2& bounds, bool layered) {
|
||||||
// The font does all the OpenGL work
|
// The font does all the OpenGL work
|
||||||
if (_font) {
|
if (_font) {
|
||||||
// Cache color so that the pointer stays valid.
|
// Cache color so that the pointer stays valid.
|
||||||
_color = color;
|
_color = color;
|
||||||
_font->drawString(batch, x, y, str, &_color, _effectType, bounds);
|
_font->drawString(batch, x, y, str, &_color, _effectType, bounds, layered);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
float getFontSize() const; // Pixel size
|
float getFontSize() const; // Pixel size
|
||||||
|
|
||||||
void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color = glm::vec4(1.0f),
|
void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color = glm::vec4(1.0f),
|
||||||
const glm::vec2& bounds = glm::vec2(-1.0f));
|
const glm::vec2& bounds = glm::vec2(-1.0f), bool layered = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextRenderer3D(const char* family, float pointSize, int weight = -1, bool italic = false,
|
TextRenderer3D(const char* family, float pointSize, int weight = -1, bool italic = false,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<@include gpu/Config.slh@>
|
<@include gpu/Config.slh@>
|
||||||
<$VERSION_HEADER$>
|
<$VERSION_HEADER$>
|
||||||
// Generated on <$_SCRIBE_DATE$>
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
// model.vert
|
// model.slv
|
||||||
// vertex shader
|
// vertex shader
|
||||||
//
|
//
|
||||||
// Created by Andrzej Kapolka on 10/14/13.
|
// Created by Andrzej Kapolka on 10/14/13.
|
||||||
|
@ -17,19 +17,18 @@
|
||||||
<$declareStandardTransform()$>
|
<$declareStandardTransform()$>
|
||||||
|
|
||||||
const int MAX_TEXCOORDS = 2;
|
const int MAX_TEXCOORDS = 2;
|
||||||
|
|
||||||
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
|
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
|
||||||
|
|
||||||
|
out vec3 _color;
|
||||||
|
out float _alpha;
|
||||||
|
out vec2 _texCoord0;
|
||||||
out vec4 _position;
|
out vec4 _position;
|
||||||
out vec3 _normal;
|
out vec3 _normal;
|
||||||
out vec3 _color;
|
|
||||||
out vec2 _texCoord0;
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
// pass along the diffuse color in linear space
|
|
||||||
_color = colorToLinearRGB(inColor.xyz);
|
_color = colorToLinearRGB(inColor.xyz);
|
||||||
|
_alpha = inColor.w;
|
||||||
|
|
||||||
// and the texture coordinates
|
|
||||||
_texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st;
|
_texCoord0 = (texcoordMatrices[0] * vec4(inTexCoord0.st, 0.0, 1.0)).st;
|
||||||
|
|
||||||
// standard transform
|
// standard transform
|
||||||
|
|
38
libraries/render-utils/src/model_emissive.slf
Normal file
38
libraries/render-utils/src/model_emissive.slf
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// model_emissive.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 2/3/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
|
||||||
|
//
|
||||||
|
|
||||||
|
<@include DeferredBufferWrite.slh@>
|
||||||
|
<@include model/Material.slh@>
|
||||||
|
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
|
in vec2 _texCoord0;
|
||||||
|
in vec3 _normal;
|
||||||
|
in vec3 _color;
|
||||||
|
in float _alpha;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 texel = texture(diffuseMap, _texCoord0);
|
||||||
|
|
||||||
|
Material mat = getMaterial();
|
||||||
|
vec3 fragColor = getMaterialDiffuse(mat) * texel.rgb * _color;
|
||||||
|
|
||||||
|
packDeferredFragmentLightmap(
|
||||||
|
normalize(_normal),
|
||||||
|
texel.a,
|
||||||
|
vec3(1.0),
|
||||||
|
getMaterialSpecular(mat),
|
||||||
|
getMaterialShininess(mat),
|
||||||
|
fragColor);
|
||||||
|
}
|
|
@ -11,39 +11,14 @@
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
<@include model/Material.slh@>
|
<@include model/Material.slh@>
|
||||||
|
|
||||||
// Everything about global lighting
|
|
||||||
|
|
||||||
<@include DeferredLighting.slh@>
|
<@include DeferredLighting.slh@>
|
||||||
<@include gpu/Transform.slh@>
|
|
||||||
<$declareStandardCameraTransform()$>
|
|
||||||
|
|
||||||
|
|
||||||
// Everything about light
|
|
||||||
<@include model/Light.slh@>
|
<@include model/Light.slh@>
|
||||||
|
|
||||||
// The view Matrix
|
<@include gpu/Transform.slh@>
|
||||||
//uniform mat4 invViewMat;
|
<$declareStandardCameraTransform()$>
|
||||||
|
|
||||||
vec4 evalNormalColor(vec3 dir, float opacity) {
|
|
||||||
bool isX = (abs(dir.x) > 0.99);
|
|
||||||
bool isY = (abs(dir.y) > 0.99);
|
|
||||||
bool isZ = (abs(dir.z) > 0.99);
|
|
||||||
if (isX || isY || isZ) {
|
|
||||||
bool negX = (dir.x < -0.995);
|
|
||||||
bool negY = (dir.y < -0.995);
|
|
||||||
bool negZ = (dir.z < -0.995);
|
|
||||||
|
|
||||||
if (negX || negY || negZ) {
|
|
||||||
return vec4(float(isX), float(isY), float(isZ), 0.2);
|
|
||||||
} else {
|
|
||||||
return vec4(float(isX), float(isY), float(isZ), 1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec4(0.5 * dir + vec3(0.5), opacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 diffuse, vec3 specular, float gloss, float opacity) {
|
||||||
|
|
||||||
|
@ -60,42 +35,37 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 d
|
||||||
|
|
||||||
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
||||||
|
|
||||||
color += vec3(opacity * diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
|
color += vec3(diffuse * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
|
||||||
|
|
||||||
//return vec4(color, opacity);
|
|
||||||
return vec4(color, opacity);
|
return vec4(color, opacity);
|
||||||
//return vec4(diffuse.rgb, opacity);
|
|
||||||
//return evalNormalColor(fragEyeDir, opacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the diffuse texture
|
|
||||||
uniform sampler2D diffuseMap;
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
in vec4 _position;
|
|
||||||
in vec2 _texCoord0;
|
in vec2 _texCoord0;
|
||||||
|
in vec4 _position;
|
||||||
in vec3 _normal;
|
in vec3 _normal;
|
||||||
in vec3 _color;
|
in vec3 _color;
|
||||||
|
in float _alpha;
|
||||||
|
|
||||||
out vec4 _fragColor;
|
out vec4 _fragColor;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec3 fragPosition = _position.xyz;
|
|
||||||
|
|
||||||
// Fetch diffuse map
|
|
||||||
vec4 diffuse = texture(diffuseMap, _texCoord0);
|
vec4 diffuse = texture(diffuseMap, _texCoord0);
|
||||||
|
|
||||||
Material mat = getMaterial();
|
Material mat = getMaterial();
|
||||||
|
vec3 fragPosition = _position.xyz;
|
||||||
vec3 fragNormal = normalize(_normal);
|
vec3 fragNormal = normalize(_normal);
|
||||||
float fragOpacity = getMaterialOpacity(mat) * diffuse.a;
|
|
||||||
vec3 fragDiffuse = getMaterialDiffuse(mat) * diffuse.rgb * _color;
|
vec3 fragDiffuse = getMaterialDiffuse(mat) * diffuse.rgb * _color;
|
||||||
vec3 fragSpecular = getMaterialSpecular(mat);
|
vec3 fragSpecular = getMaterialSpecular(mat);
|
||||||
float fragGloss = getMaterialShininess(mat);
|
float fragGloss = getMaterialShininess(mat) / 128;
|
||||||
|
float fragOpacity = getMaterialOpacity(mat) * diffuse.a * _alpha;
|
||||||
|
|
||||||
_fragColor = evalGlobalColor(1.0,
|
_fragColor = evalGlobalColor(1.0,
|
||||||
fragPosition,
|
fragPosition,
|
||||||
fragNormal,
|
fragNormal,
|
||||||
fragDiffuse,
|
fragDiffuse,
|
||||||
fragSpecular,
|
fragSpecular,
|
||||||
fragGloss,
|
fragGloss,
|
||||||
fragOpacity);
|
fragOpacity);
|
||||||
}
|
}
|
||||||
|
|
33
libraries/render-utils/src/model_translucent_emissive.slf
Normal file
33
libraries/render-utils/src/model_translucent_emissive.slf
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// model_translucent_emissive.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 2/3/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
|
||||||
|
//
|
||||||
|
|
||||||
|
<@include model/Material.slh@>
|
||||||
|
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
|
in vec2 _texCoord0;
|
||||||
|
in vec3 _color;
|
||||||
|
in float _alpha;
|
||||||
|
|
||||||
|
out vec4 _fragColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 diffuse = texture(diffuseMap, _texCoord0);
|
||||||
|
|
||||||
|
Material mat = getMaterial();
|
||||||
|
vec3 fragColor = getMaterialDiffuse(mat) * diffuse.rgb * _color;
|
||||||
|
float fragOpacity = getMaterialOpacity(mat) * diffuse.a * _alpha;
|
||||||
|
|
||||||
|
_fragColor = vec4(fragColor, fragOpacity);
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<@include gpu/Config.slh@>
|
<@include gpu/Config.slh@>
|
||||||
<$VERSION_HEADER$>
|
<$VERSION_HEADER$>
|
||||||
// Generated on <$_SCRIBE_DATE$>
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
// model.frag
|
// overlay3D.slf
|
||||||
// fragment shader
|
// fragment shader
|
||||||
//
|
//
|
||||||
// Created by Sam Gateau on 6/16/15.
|
// Created by Sam Gateau on 6/16/15.
|
||||||
|
@ -11,20 +11,64 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
uniform sampler2D diffuseMap;
|
<@include DeferredLighting.slh@>
|
||||||
|
<@include model/Light.slh@>
|
||||||
|
|
||||||
in vec2 varTexcoord;
|
<@include gpu/Transform.slh@>
|
||||||
|
<$declareStandardCameraTransform()$>
|
||||||
|
|
||||||
in vec3 varEyeNormal;
|
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss, float opacity) {
|
||||||
|
|
||||||
in vec4 varColor;
|
// Need the light now
|
||||||
out vec4 outFragColor;
|
Light light = getLight();
|
||||||
|
TransformCamera cam = getTransformCamera();
|
||||||
|
vec3 fragNormal;
|
||||||
|
<$transformEyeToWorldDir(cam, normal, fragNormal)$>
|
||||||
|
vec3 fragEyeVectorView = normalize(-position);
|
||||||
|
vec3 fragEyeDir;
|
||||||
|
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
|
||||||
|
|
||||||
|
vec3 color = opacity * diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light);
|
||||||
|
|
||||||
|
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
||||||
|
|
||||||
|
color += vec3(diffuse * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
|
||||||
|
|
||||||
|
return vec4(color, opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform sampler2D originalTexture;
|
||||||
|
|
||||||
|
in vec2 _texCoord0;
|
||||||
|
in vec4 _position;
|
||||||
|
in vec3 _normal;
|
||||||
|
in vec3 _color;
|
||||||
|
in float _alpha;
|
||||||
|
|
||||||
|
out vec4 _fragColor;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 diffuse = texture(diffuseMap, varTexcoord.st);
|
vec4 diffuse = texture(originalTexture, _texCoord0);
|
||||||
if (diffuse.a < 0.5) {
|
|
||||||
|
vec3 fragPosition = _position.xyz;
|
||||||
|
vec3 fragNormal = normalize(_normal);
|
||||||
|
vec3 fragDiffuse = diffuse.rgb * _color;
|
||||||
|
vec3 fragSpecular = vec3(0.1);
|
||||||
|
float fragGloss = 10.0 / 128.0;
|
||||||
|
float fragOpacity = diffuse.a;
|
||||||
|
|
||||||
|
if (fragOpacity <= 0.1) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
outFragColor = vec4(varColor * diffuse);
|
|
||||||
|
vec4 color = evalGlobalColor(1.0,
|
||||||
|
fragPosition,
|
||||||
|
fragNormal,
|
||||||
|
fragDiffuse,
|
||||||
|
fragSpecular,
|
||||||
|
fragGloss,
|
||||||
|
fragOpacity);
|
||||||
|
|
||||||
|
// Apply standard tone mapping
|
||||||
|
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<$VERSION_HEADER$>
|
<$VERSION_HEADER$>
|
||||||
// Generated on <$_SCRIBE_DATE$>
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
// overlay3D.slv
|
// overlay3D.slv
|
||||||
|
// vertex shader
|
||||||
//
|
//
|
||||||
// Created by Sam Gateau on 6/16/15.
|
// Created by Sam Gateau on 6/16/15.
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
@ -15,25 +16,21 @@
|
||||||
<@include gpu/Transform.slh@>
|
<@include gpu/Transform.slh@>
|
||||||
<$declareStandardTransform()$>
|
<$declareStandardTransform()$>
|
||||||
|
|
||||||
out vec2 varTexcoord;
|
out vec3 _color;
|
||||||
|
out float _alpha;
|
||||||
// interpolated eye position
|
out vec2 _texCoord0;
|
||||||
out vec4 varEyePosition;
|
out vec4 _position;
|
||||||
|
out vec3 _normal;
|
||||||
// the interpolated normal
|
|
||||||
out vec3 varEyeNormal;
|
|
||||||
|
|
||||||
out vec4 varColor;
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
varTexcoord = inTexCoord0.xy;
|
_color = colorToLinearRGB(inColor.xyz);
|
||||||
|
_alpha = inColor.w;
|
||||||
|
|
||||||
// pass along the color
|
_texCoord0 = inTexCoord0.st;
|
||||||
varColor = colorToLinearRGBA(inColor);
|
|
||||||
|
|
||||||
// standard transform
|
// standard transform
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
TransformObject obj = getTransformObject();
|
TransformObject obj = getTransformObject();
|
||||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, varEyePosition, gl_Position)$>
|
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
|
||||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, varEyeNormal.xyz)$>
|
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
|
||||||
}
|
}
|
||||||
|
|
32
libraries/render-utils/src/overlay3D_emissive.slf
Normal file
32
libraries/render-utils/src/overlay3D_emissive.slf
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// overlay3D_emissive.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 2/2/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
|
||||||
|
//
|
||||||
|
|
||||||
|
uniform sampler2D originalTexture;
|
||||||
|
|
||||||
|
in vec2 _texCoord0;
|
||||||
|
in vec3 _color;
|
||||||
|
|
||||||
|
out vec4 _fragColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 diffuse = texture(originalTexture, _texCoord0);
|
||||||
|
|
||||||
|
if (diffuse.a <= 0.1) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
vec4 color = vec4(diffuse.rgb * _color, diffuse.a);
|
||||||
|
|
||||||
|
// Apply standard tone mapping
|
||||||
|
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
|
||||||
|
}
|
71
libraries/render-utils/src/overlay3D_translucent.slf
Normal file
71
libraries/render-utils/src/overlay3D_translucent.slf
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// overlay3D_translucent.slf
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 6/16/15.
|
||||||
|
// Copyright 2015 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
|
||||||
|
//
|
||||||
|
|
||||||
|
<@include DeferredLighting.slh@>
|
||||||
|
<@include model/Light.slh@>
|
||||||
|
|
||||||
|
<@include gpu/Transform.slh@>
|
||||||
|
<$declareStandardCameraTransform()$>
|
||||||
|
|
||||||
|
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss, float opacity) {
|
||||||
|
|
||||||
|
// Need the light now
|
||||||
|
Light light = getLight();
|
||||||
|
TransformCamera cam = getTransformCamera();
|
||||||
|
vec3 fragNormal;
|
||||||
|
<$transformEyeToWorldDir(cam, normal, fragNormal)$>
|
||||||
|
vec3 fragEyeVectorView = normalize(-position);
|
||||||
|
vec3 fragEyeDir;
|
||||||
|
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
|
||||||
|
|
||||||
|
vec3 color = opacity * diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light);
|
||||||
|
|
||||||
|
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
||||||
|
|
||||||
|
color += vec3(diffuse * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
|
||||||
|
|
||||||
|
return vec4(color, opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform sampler2D originalTexture;
|
||||||
|
|
||||||
|
in vec2 _texCoord0;
|
||||||
|
in vec4 _position;
|
||||||
|
in vec3 _normal;
|
||||||
|
in vec3 _color;
|
||||||
|
in float _alpha;
|
||||||
|
|
||||||
|
out vec4 _fragColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 diffuse = texture(originalTexture, _texCoord0);
|
||||||
|
|
||||||
|
vec3 fragPosition = _position.xyz;
|
||||||
|
vec3 fragNormal = normalize(_normal);
|
||||||
|
vec3 fragDiffuse = diffuse.rgb * _color;
|
||||||
|
vec3 fragSpecular = vec3(0.1);
|
||||||
|
float fragGloss = 10.0 / 128.0;
|
||||||
|
float fragOpacity = diffuse.a * _alpha;
|
||||||
|
|
||||||
|
vec4 color = evalGlobalColor(1.0,
|
||||||
|
fragPosition,
|
||||||
|
fragNormal,
|
||||||
|
fragDiffuse,
|
||||||
|
fragSpecular,
|
||||||
|
fragGloss,
|
||||||
|
fragOpacity);
|
||||||
|
|
||||||
|
// Apply standard tone mapping
|
||||||
|
_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// overlay3D_translucent_emissive.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 2/2/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
|
||||||
|
//
|
||||||
|
|
||||||
|
uniform sampler2D originalTexture;
|
||||||
|
|
||||||
|
in vec2 _texCoord0;
|
||||||
|
in vec3 _color;
|
||||||
|
in float _alpha;
|
||||||
|
|
||||||
|
out vec4 _fragColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 diffuse = texture(originalTexture, _texCoord0);
|
||||||
|
|
||||||
|
_fragColor = vec4(diffuse.rgb * _color, diffuse.a * _alpha);
|
||||||
|
}
|
|
@ -234,6 +234,10 @@ void Font::setupGPU() {
|
||||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
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);
|
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||||
_pipeline = gpu::Pipeline::create(program, state);
|
_pipeline = gpu::Pipeline::create(program, state);
|
||||||
|
|
||||||
|
auto layeredState = std::make_shared<gpu::State>(state->getValues());
|
||||||
|
layeredState->setDepthTest(false);
|
||||||
|
_layeredPipeline = gpu::Pipeline::create(program, layeredState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
|
@ -336,7 +340,7 @@ void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4* color,
|
void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4* color,
|
||||||
EffectType effectType, const glm::vec2& bounds) {
|
EffectType effectType, const glm::vec2& bounds, bool layered) {
|
||||||
if (str == "") {
|
if (str == "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +351,7 @@ void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, c
|
||||||
|
|
||||||
setupGPU();
|
setupGPU();
|
||||||
|
|
||||||
batch.setPipeline(_pipeline);
|
batch.setPipeline(layered ? _layeredPipeline : _pipeline);
|
||||||
batch.setResourceTexture(_fontLoc, _texture);
|
batch.setResourceTexture(_fontLoc, _texture);
|
||||||
batch._glUniform1i(_outlineLoc, (effectType == OUTLINE_EFFECT));
|
batch._glUniform1i(_outlineLoc, (effectType == OUTLINE_EFFECT));
|
||||||
batch._glUniform4fv(_colorLoc, 1, (const float*)color);
|
batch._glUniform4fv(_colorLoc, 1, (const float*)color);
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
// Render string to batch
|
// Render string to batch
|
||||||
void drawString(gpu::Batch& batch, float x, float y, const QString& str,
|
void drawString(gpu::Batch& batch, float x, float y, const QString& str,
|
||||||
const glm::vec4* color, EffectType effectType,
|
const glm::vec4* color, EffectType effectType,
|
||||||
const glm::vec2& bound);
|
const glm::vec2& bound, bool layered = false);
|
||||||
|
|
||||||
static Font* load(QIODevice& fontFile);
|
static Font* load(QIODevice& fontFile);
|
||||||
static Font* load(const QString& family);
|
static Font* load(const QString& family);
|
||||||
|
@ -61,6 +61,7 @@ private:
|
||||||
|
|
||||||
// gpu structures
|
// gpu structures
|
||||||
gpu::PipelinePointer _pipeline;
|
gpu::PipelinePointer _pipeline;
|
||||||
|
gpu::PipelinePointer _layeredPipeline;
|
||||||
gpu::TexturePointer _texture;
|
gpu::TexturePointer _texture;
|
||||||
gpu::Stream::FormatPointer _format;
|
gpu::Stream::FormatPointer _format;
|
||||||
gpu::BufferPointer _verticesBuffer;
|
gpu::BufferPointer _verticesBuffer;
|
||||||
|
|
|
@ -143,6 +143,7 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons
|
||||||
if (args->_pipeline) {
|
if (args->_pipeline) {
|
||||||
item.render(args);
|
item.render(args);
|
||||||
}
|
}
|
||||||
|
args->_pipeline = nullptr;
|
||||||
} else if (key.hasOwnPipeline()) {
|
} else if (key.hasOwnPipeline()) {
|
||||||
item.render(args);
|
item.render(args);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
|
void ShapePipeline::prepare(gpu::Batch& batch) {
|
||||||
|
if (batchSetter) {
|
||||||
|
batchSetter(*this, batch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ShapeKey::Filter::Builder::Builder() {
|
ShapeKey::Filter::Builder::Builder() {
|
||||||
_mask.set(OWN_PIPELINE);
|
_mask.set(OWN_PIPELINE);
|
||||||
_mask.set(INVALID);
|
_mask.set(INVALID);
|
||||||
|
@ -90,13 +96,13 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke
|
||||||
PipelinePointer shapePipeline(pipelineIterator->second);
|
PipelinePointer shapePipeline(pipelineIterator->second);
|
||||||
auto& batch = args->_batch;
|
auto& batch = args->_batch;
|
||||||
|
|
||||||
|
// Setup the one pipeline (to rule them all)
|
||||||
|
batch->setPipeline(shapePipeline->pipeline);
|
||||||
|
|
||||||
// Run the pipeline's BatchSetter on the passed in batch
|
// Run the pipeline's BatchSetter on the passed in batch
|
||||||
if (shapePipeline->batchSetter) {
|
if (shapePipeline->batchSetter) {
|
||||||
shapePipeline->batchSetter(*shapePipeline, *batch);
|
shapePipeline->batchSetter(*shapePipeline, *batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the one pipeline (to rule them all)
|
|
||||||
batch->setPipeline(shapePipeline->pipeline);
|
|
||||||
|
|
||||||
return shapePipeline;
|
return shapePipeline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,9 @@ public:
|
||||||
SKINNED,
|
SKINNED,
|
||||||
STEREO,
|
STEREO,
|
||||||
DEPTH_ONLY,
|
DEPTH_ONLY,
|
||||||
|
DEPTH_BIAS,
|
||||||
WIREFRAME,
|
WIREFRAME,
|
||||||
|
NO_CULL_FACE,
|
||||||
|
|
||||||
OWN_PIPELINE,
|
OWN_PIPELINE,
|
||||||
INVALID,
|
INVALID,
|
||||||
|
@ -39,7 +41,7 @@ public:
|
||||||
|
|
||||||
Flags _flags;
|
Flags _flags;
|
||||||
|
|
||||||
ShapeKey() : _flags{0} {}
|
ShapeKey() : _flags{ 0 } {}
|
||||||
ShapeKey(const Flags& flags) : _flags{flags} {}
|
ShapeKey(const Flags& flags) : _flags{flags} {}
|
||||||
|
|
||||||
class Builder {
|
class Builder {
|
||||||
|
@ -57,7 +59,9 @@ public:
|
||||||
Builder& withSkinned() { _flags.set(SKINNED); return (*this); }
|
Builder& withSkinned() { _flags.set(SKINNED); return (*this); }
|
||||||
Builder& withStereo() { _flags.set(STEREO); return (*this); }
|
Builder& withStereo() { _flags.set(STEREO); return (*this); }
|
||||||
Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); }
|
Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); 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& 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); }
|
||||||
|
@ -107,9 +111,15 @@ public:
|
||||||
Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); }
|
Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); }
|
||||||
Builder& withoutDepthOnly() { _flags.reset(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); }
|
Builder& withoutDepthOnly() { _flags.reset(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); }
|
||||||
|
|
||||||
|
Builder& withDepthBias() { _flags.set(DEPTH_BIAS); _mask.set(DEPTH_BIAS); return (*this); }
|
||||||
|
Builder& withoutDepthBias() { _flags.reset(DEPTH_BIAS); _mask.set(DEPTH_BIAS); return (*this); }
|
||||||
|
|
||||||
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& withoutCullFace() { _flags.set(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Filter;
|
friend class Filter;
|
||||||
Flags _flags{0};
|
Flags _flags{0};
|
||||||
|
@ -130,7 +140,9 @@ public:
|
||||||
bool isSkinned() const { return _flags[SKINNED]; }
|
bool isSkinned() const { return _flags[SKINNED]; }
|
||||||
bool isStereo() const { return _flags[STEREO]; }
|
bool isStereo() const { return _flags[STEREO]; }
|
||||||
bool isDepthOnly() const { return _flags[DEPTH_ONLY]; }
|
bool isDepthOnly() const { return _flags[DEPTH_ONLY]; }
|
||||||
|
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 hasOwnPipeline() const { return _flags[OWN_PIPELINE]; }
|
bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; }
|
||||||
bool isValid() const { return !_flags[INVALID]; }
|
bool isValid() const { return !_flags[INVALID]; }
|
||||||
|
@ -150,21 +162,23 @@ public:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QDebug operator<<(QDebug debug, const ShapeKey& renderKey) {
|
inline QDebug operator<<(QDebug debug, const ShapeKey& key) {
|
||||||
if (renderKey.isValid()) {
|
if (key.isValid()) {
|
||||||
if (renderKey.hasOwnPipeline()) {
|
if (key.hasOwnPipeline()) {
|
||||||
debug << "[ShapeKey: OWN_PIPELINE]";
|
debug << "[ShapeKey: OWN_PIPELINE]";
|
||||||
} else {
|
} else {
|
||||||
debug << "[ShapeKey:"
|
debug << "[ShapeKey:"
|
||||||
<< "hasLightmap:" << renderKey.hasLightmap()
|
<< "hasLightmap:" << key.hasLightmap()
|
||||||
<< "hasTangents:" << renderKey.hasTangents()
|
<< "hasTangents:" << key.hasTangents()
|
||||||
<< "hasSpecular:" << renderKey.hasSpecular()
|
<< "hasSpecular:" << key.hasSpecular()
|
||||||
<< "hasEmissive:" << renderKey.hasEmissive()
|
<< "hasEmissive:" << key.hasEmissive()
|
||||||
<< "isTranslucent:" << renderKey.isTranslucent()
|
<< "isTranslucent:" << key.isTranslucent()
|
||||||
<< "isSkinned:" << renderKey.isSkinned()
|
<< "isSkinned:" << key.isSkinned()
|
||||||
<< "isStereo:" << renderKey.isStereo()
|
<< "isStereo:" << key.isStereo()
|
||||||
<< "isDepthOnly:" << renderKey.isDepthOnly()
|
<< "isDepthOnly:" << key.isDepthOnly()
|
||||||
<< "isWireFrame:" << renderKey.isWireFrame()
|
<< "isDepthBiased:" << key.isDepthBiased()
|
||||||
|
<< "isWireFrame:" << key.isWireFrame()
|
||||||
|
<< "isCullFace:" << key.isCullFace()
|
||||||
<< "]";
|
<< "]";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -209,6 +223,10 @@ public:
|
||||||
ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter) :
|
ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter) :
|
||||||
pipeline(pipeline), locations(locations), batchSetter(batchSetter) {}
|
pipeline(pipeline), locations(locations), batchSetter(batchSetter) {}
|
||||||
|
|
||||||
|
// Normally, a pipeline is accessed thorugh pickPipeline. If it needs to be set manually,
|
||||||
|
// after calling setPipeline this method should be called to prepare the pipeline with default buffers.
|
||||||
|
void prepare(gpu::Batch& batch);
|
||||||
|
|
||||||
gpu::PipelinePointer pipeline;
|
gpu::PipelinePointer pipeline;
|
||||||
std::shared_ptr<Locations> locations;
|
std::shared_ptr<Locations> locations;
|
||||||
|
|
||||||
|
|
|
@ -239,6 +239,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto pipeline = geometryCache->getSimplePipeline();
|
||||||
for (auto& transform : transforms) {
|
for (auto& transform : transforms) {
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||||
|
|
Loading…
Reference in a new issue