diff --git a/interface/resources/qml/windows/Decoration.qml b/interface/resources/qml/windows/Decoration.qml index 843ae25596..f8fd9f4e6c 100644 --- a/interface/resources/qml/windows/Decoration.qml +++ b/interface/resources/qml/windows/Decoration.qml @@ -1,5 +1,5 @@ // -// DefaultFrame.qml +// Decoration.qml // // Created by Bradley Austin Davis on 12 Jan 2016 // Copyright 2016 High Fidelity, Inc. diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index ef8ea95704..9b2482e73a 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -24,6 +24,36 @@ class QScriptEngine; #include +/**jsdoc + * The HMD API provides access to the HMD used in VR display mode. + * + * @namespace HMD + * @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise + * {@link Vec3(0)|Vec3.ZERO}. Read-only. + * @property {Quat} orientation - The orientation of the HMD if currently in VR display mode, otherwise + * {@link Quat(0)|Quat.IDENTITY}. Read-only. + * @property {boolean} active - true if the display mode is HMD, otherwise false. Read-only. + * @property {boolean} mounted - true if currently in VR display mode and the HMD is being worn, otherwise + * false. Read-only. + * + * @property {number} playerHeight - The real-world height of the user. Read-only. Currently always returns a + * value of 1.755. + * @property {number} eyeHeight - The real-world height of the user's eyes. Read-only. Currently always returns a + * value of 1.655. + * @property {number} ipd - The inter-pupillary distance (distance between eyes) of the user, used for rendering. Defaults to + * the human average of 0.064 unless set by the HMD. Read-only. + * @property {number} ipdScale=1.0 - A scale factor applied to the ipd property value. + * + * @property {boolean} showTablet - true if the tablet is being displayed, false otherwise. + * Read-only. + * @property {boolean} tabletContextualMode - true if the tablet has been opened in contextual mode, otherwise + * false. In contextual mode, the tablet has been opened at a specific world position and orientation rather + * than at a position and orientation relative to the user. Read-only. + * @property {Uuid} tabletID - The UUID of the tablet body model overlay. + * @property {Uuid} tabletScreenID - The UUID of the tablet's screen overlay. + * @property {Uuid} homeButtonID - The UUID of the tablet's "home" button overlay. + * @property {Uuid} homeButtonHighlightID - The UUID of the tablet's "home" button highlight overlay. + */ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency { Q_OBJECT Q_PROPERTY(glm::vec3 position READ getPosition) @@ -37,26 +67,217 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID) public: + + /**jsdoc + * Calculate the intersection of a ray with the HUD overlay. + * @function HMD.calculateRayUICollisionPoint + * @param {Vec3} position - The origin of the ray. + * @param {Vec3} direction - The direction of the ray. + * @returns {Vec3} The point of intersection with the HUD overlay if it intersects, otherwise {@link Vec3(0)|Vec3.ZERO}. + * @example Draw a square on the HUD overlay in the direction you're looking. + * var hudIntersection = HMD.calculateRayUICollisionPoint(MyAvatar.getHeadPosition(), + * Quat.getForward(MyAvatar.headOrientation)); + * var hudPoint = HMD.overlayFromWorldPoint(hudIntersection); + * + * var DIMENSIONS = { x: 50, y: 50 }; + * var square = Overlays.addOverlay("rectangle", { + * x: hudPoint.x - DIMENSIONS.x / 2, + * y: hudPoint.y - DIMENSIONS.y / 2, + * width: DIMENSIONS.x, + * height: DIMENSIONS.y, + * color: { red: 255, green: 0, blue: 0 } + * }); + * + * Script.scriptEnding.connect(function () { + * Overlays.deleteOverlay(square); + * }); + */ Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const; + + /**jsdoc + * Get the 2D HUD overlay coordinates of a 3D point on the HUD overlay. + * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. + * @function HMD.overlayFromWorldPoint + * @param {Vec3} position - The point on the HUD overlay in world coordinates. + * @returns {Vec2} The point on the HUD overlay in HUD coordinates. + * @example Draw a square on the HUD overlay in the direction you're looking. + * var hudIntersection = HMD.calculateRayUICollisionPoint(MyAvatar.getHeadPosition(), + * Quat.getForward(MyAvatar.headOrientation)); + * var hudPoint = HMD.overlayFromWorldPoint(hudIntersection); + * + * var DIMENSIONS = { x: 50, y: 50 }; + * var square = Overlays.addOverlay("rectangle", { + * x: hudPoint.x - DIMENSIONS.x / 2, + * y: hudPoint.y - DIMENSIONS.y / 2, + * width: DIMENSIONS.x, + * height: DIMENSIONS.y, + * color: { red: 255, green: 0, blue: 0 } + * }); + * + * Script.scriptEnding.connect(function () { + * Overlays.deleteOverlay(square); + * }); + */ Q_INVOKABLE glm::vec2 overlayFromWorldPoint(const glm::vec3& position) const; + + /**jsdoc + * Get the 3D world coordinates of a 2D point on the HUD overlay. + * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. + * @function HMD.worldPointFromOverlay + * @param {Vec2} coordinates - The point on the HUD overlay in HUD coordinates. + * @returns {Vec3} The point on the HUD overlay in world coordinates. + */ Q_INVOKABLE glm::vec3 worldPointFromOverlay(const glm::vec2& overlay) const; + + /**jsdoc + * Get the 2D point on the HUD overlay represented by given spherical coordinates. + * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. + * Spherical coordinates are polar coordinates in radians with { x: 0, y: 0 } being the center of the HUD + * overlay. + * @function HMD.sphericalToOverlay + * @param {Vec2} sphericalPos - The point on the HUD overlay in spherical coordinates. + * @returns {Vec2} The point on the HUD overlay in HUD coordinates. + */ Q_INVOKABLE glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const; + + /**jsdoc + * Get the spherical coordinates of a 2D point on the HUD overlay. + * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. + * Spherical coordinates are polar coordinates in radians with { x: 0, y: 0 } being the center of the HUD + * overlay. + * @function HMD.overlayToSpherical + * @param {Vec2} overlayPos - The point on the HUD overlay in HUD coordinates. + * @returns {Vec2} The point on the HUD overlay in spherical coordinates. + */ Q_INVOKABLE glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; + + /**jsdoc + * Recenter the HMD HUD to the current HMD position and orientation. + * @function HMD.centerUI + */ + Q_INVOKABLE void centerUI(); + + + /**jsdoc + * Get the name of the HMD audio input device. + * @function HMD.preferredAudioInput + * @returns {string} The name of the HMD audio input device if in HMD mode, otherwise an empty string. + */ Q_INVOKABLE QString preferredAudioInput() const; + + /**jsdoc + * Get the name of the HMD audio output device. + * @function HMD.preferredAudioOutput + * @returns {string} The name of the HMD audio output device if in HMD mode, otherwise an empty string. + */ Q_INVOKABLE QString preferredAudioOutput() const; + + /**jsdoc + * Check whether there is an HMD available. + * @function HMD.isHMDAvailable + * @param {string} [name=""] - The name of the HMD to check for, e.g., "Oculus Rift". The name is the same as + * may be displayed in Interface's "Display" menu. If no name is specified then any HMD matches. + * @returns {boolean} true if an HMD of the specified name is available, otherwise + * false. + * @example Report on HMD availability. + * print("Is any HMD available: " + HMD.isHMDAvailable()); + * print("Is an Oculus Rift HMD available: " + HMD.isHMDAvailable("Oculus Rift")); + * print("Is a Vive HMD available: " + HMD.isHMDAvailable("OpenVR (Vive)")); + */ Q_INVOKABLE bool isHMDAvailable(const QString& name = ""); + + /**jsdoc + * Check whether there is an HMD head controller available. + * @function HMD.isHeadControllerAvailable + * @param {string} [name=""] - The name of the HMD head controller to check for, e.g., "Oculus". If no name is + * specified then any HMD head controller matches. + * @returns {boolean} true if an HMD head controller of the specified name is available, + * otherwise false. + * @example Report HMD head controller availability. + * print("Is any HMD head controller available: " + HMD.isHeadControllerAvailable()); + * print("Is an Oculus head controller available: " + HMD.isHeadControllerAvailable("Oculus")); + * print("Is a Vive head controller available: " + HMD.isHeadControllerAvailable("OpenVR")); + */ Q_INVOKABLE bool isHeadControllerAvailable(const QString& name = ""); + + /**jsdoc + * Check whether there are HMD hand controllers available. + * @function HMD.isHandControllerAvailable + * @param {string} [name=""] - The name of the HMD hand controller to check for, e.g., "Oculus". If no name is + * specified then any HMD hand controller matches. + * @returns {boolean} true if an HMD hand controller of the specified name is available, + * otherwise false. + * @example Report HMD hand controller availability. + * print("Are any HMD hand controllers available: " + HMD.isHandControllerAvailable()); + * print("Are Oculus hand controllers available: " + HMD.isHandControllerAvailable("Oculus")); + * print("Are Vive hand controllers available: " + HMD.isHandControllerAvailable("OpenVR")); + */ Q_INVOKABLE bool isHandControllerAvailable(const QString& name = ""); + + /**jsdoc + * Check whether there are specific HMD controllers available. + * @function HMD.isSubdeviceContainingNameAvailable + * @param {string} name - The name of the HMD controller to check for, e.g., "OculusTouch". + * @returns {boolean} true if an HMD controller with a name containing the specified name is + * available, otherwise false. + * @example Report if particular Oculus controllers are available. + * print("Is an Oculus Touch controller available: " + HMD.isSubdeviceContainingNameAvailable("Touch")); + * print("Is an Oculus Remote controller available: " + HMD.isSubdeviceContainingNameAvailable("Remote")); + */ Q_INVOKABLE bool isSubdeviceContainingNameAvailable(const QString& name); + /**jsdoc + * Signal that models of the HMD hand controllers being used should be displayed. The models are displayed at their actual, + * real-world locations. + * @function HMD.requestShowHandControllers + * @example Show your hand controllers for 10 seconds. + * HMD.requestShowHandControllers(); + * Script.setTimeout(function () { + * HMD.requestHideHandControllers(); + * }, 10000); + */ Q_INVOKABLE void requestShowHandControllers(); + + /**jsdoc + * Signal that it is no longer necessary to display models of the HMD hand controllers being used. If no other scripts + * want the models displayed then they are no longer displayed. + * @function HMD.requestHideHandControllers + */ Q_INVOKABLE void requestHideHandControllers(); + + /**jsdoc + * Check whether any script wants models of the HMD hand controllers displayed. Requests are made and canceled using + * {@link HMD.requestShowHandControllers|requestShowHandControllers} and + * {@link HMD.requestHideHandControllers|requestHideHandControllers}. + * @function HMD.shouldShowHandControllers + * @returns {boolean} true if any script is requesting that HMD hand controller models be displayed. + */ Q_INVOKABLE bool shouldShowHandControllers() const; + + /**jsdoc + * Causes the borders in HUD windows to be enlarged when the laser intersects them in HMD mode. By default, borders are not + * enlarged. + * @function HMD.activateHMDHandMouse + */ Q_INVOKABLE void activateHMDHandMouse(); + + /**jsdoc + * Causes the border in HUD windows to no longer be enlarged when the laser intersects them in HMD mode. By default, + * borders are not enlarged. + * @function HMD.deactivateHMDHandMouse + */ Q_INVOKABLE void deactivateHMDHandMouse(); + + /**jsdoc + * Suppress the activation of the HMD-provided keyboard, if any. Successful calls should be balanced with a call to + * {@link HMD.unspressKeyboard|unspressKeyboard} within a reasonable amount of time. + * @function HMD.suppressKeyboard + * @returns {boolean} true if the current HMD provides a keyboard and it was successfully suppressed (e.g., it + * isn't being displayed), otherwise false. + */ /// Suppress the activation of any on-screen keyboard so that a script operation will /// not be interrupted by a keyboard popup /// Returns false if there is already an active keyboard displayed. @@ -65,21 +286,68 @@ public: /// call to unsuppressKeyboard() within a reasonable amount of time Q_INVOKABLE bool suppressKeyboard(); + /**jsdoc + * Unsuppress the activation of the HMD-provided keyboard, if any. + * @function HMD.unsuppressKeyboard + */ /// Enable the keyboard following a suppressKeyboard call Q_INVOKABLE void unsuppressKeyboard(); + /**jsdoc + * Check whether the HMD-provided keyboard, if any, is visible. + * @function HMD.isKeyboardVisible + * @returns {boolean} true if the current HMD provides a keyboard and it is visible, otherwise + * false. + */ /// Query the display plugin to determine the current VR keyboard visibility Q_INVOKABLE bool isKeyboardVisible(); - // rotate the overlay UI sphere so that it is centered about the the current HMD position and orientation - Q_INVOKABLE void centerUI(); - + /**jsdoc + * Closes the tablet if it is open. + * @function HMD.closeTablet + */ Q_INVOKABLE void closeTablet(); + /**jsdoc + * Opens the tablet if the tablet is used in the current display mode and it isn't already showing, and sets the tablet to + * contextual mode if requested. In contextual mode, the page displayed on the tablet is wholly controlled by script (i.e., + * the user cannot navigate to another). + * @function HMD.openTablet + * @param {boolean} [contextualMode=false] - If true then the tablet is opened at a specific position and + * orientation already set by the script, otherwise it opens at a position and orientation relative to the user. For + * contextual mode, set the world or local position and orientation of the HMD.tabletID overlay. + */ Q_INVOKABLE void openTablet(bool contextualMode = false); signals: + /**jsdoc + * Triggered when a request to show or hide models of the HMD hand controllers is made using + * {@link HMD.requestShowHandControllers|requestShowHandControllers} or + * {@link HMD.requestHideHandControllers|requestHideHandControllers}. + * @function HMD.shouldShowHandControllersChanged + * @returns {Signal} + * @example Report when showing of hand controllers changes. + * function onShouldShowHandControllersChanged() { + * print("Should show hand controllers: " + HMD.shouldShowHandControllers()); + * } + * HMD.shouldShowHandControllersChanged.connect(onShouldShowHandControllersChanged); + * + * HMD.requestShowHandControllers(); + * Script.setTimeout(function () { + * HMD.requestHideHandControllers(); + * }, 10000); + */ bool shouldShowHandControllersChanged(); + + /**jsdoc + * Triggered when the HMD.mounted property value changes. + * @function HMD.mountedChanged + * @returns {Signal} + * @example Report when there's a change in the HMD being worn. + * HMD.mountedChanged.connect(function () { + * print("Mounted changed. HMD is mounted: " + HMD.mounted); + * }); + */ void mountedChanged(); public: diff --git a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h index f260fa959f..392fa7e2a2 100644 --- a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h +++ b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h @@ -12,6 +12,7 @@ #include +// These properties have JSDoc documentation in HMDScriptingInterface.h. class AbstractHMDScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(bool active READ isHMDMode) @@ -30,7 +31,27 @@ public: bool isHMDMode() const; signals: + /**jsdoc + * Triggered when the HMD.ipdScale property value changes. + * @function HMD.IPDScaleChanged + * @returns {Signal} + */ void IPDScaleChanged(); + + /**jsdoc + * Triggered when Interface's display mode changes and when the user puts on or takes off their HMD. + * @function HMD.displayModeChanged + * @param {boolean} isHMDMode - true if the display mode is HMD, otherwise false. This is the + * same value as provided by HMD.active. + * @returns {Signal} + * @example Report when the display mode changes. + * HMD.displayModeChanged.connect(function (isHMDMode) { + * print("Display mode changed"); + * print("isHMD = " + isHMDMode); + * print("HMD.active = " + HMD.active); + * print("HMD.mounted = " + HMD.mounted); + * }); + */ void displayModeChanged(bool isHMDMode); private: diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index feb88bed4b..1d34837a58 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -18,6 +18,9 @@ #include "render-utils/simple_vert.h" #include "render-utils/simple_frag.h" +#include "render-utils/simple_transparent_frag.h" +#include "render-utils/forward_simple_frag.h" +#include "render-utils/forward_simple_transparent_frag.h" #include "RenderPipelines.h" @@ -35,13 +38,23 @@ static const float SPHERE_ENTITY_SCALE = 0.5f; ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { _procedural._vertexSource = simple_vert::getSource(); - _procedural._fragmentSource = simple_frag::getSource(); + // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering + _procedural._opaquefragmentSource = simple_frag::getSource(); + // FIXME: Transparent procedural entities only seem to work if they use the opaque pipelines + //_procedural._transparentfragmentSource = simple_transparent_frag::getSource(); + _procedural._transparentfragmentSource = simple_frag::getSource(); _procedural._opaqueState->setCullMode(gpu::State::CULL_NONE); _procedural._opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL); PrepareStencil::testMaskDrawShape(*_procedural._opaqueState); _procedural._opaqueState->setBlendFunction(false, 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); + _procedural._transparentState->setCullMode(gpu::State::CULL_BACK); + _procedural._transparentState->setDepthTest(true, true, gpu::LESS_EQUAL); + PrepareStencil::testMask(*_procedural._transparentState); + _procedural._transparentState->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); } bool ShapeEntityRenderer::needsRenderUpdate() const { @@ -218,9 +231,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { if (mat) { outColor = glm::vec4(mat->getAlbedo(), mat->getOpacity()); if (_procedural.isReady()) { - _procedural.prepare(batch, _position, _dimensions, _orientation); outColor = _procedural.getColor(outColor); outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; + _procedural.prepare(batch, _position, _dimensions, _orientation, outColor); proceduralRender = true; } } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 8b916a875f..f78168b05d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -477,18 +477,19 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {boolean} visible=true - Whether or not the entity is rendered. If true then the entity is rendered. * @property {boolean} canCastShadows=true - Whether or not the entity casts shadows. Currently applicable only to * {@link Entities.EntityType|Model} and {@link Entities.EntityType|Shape} entities. Shadows are cast if inside a - * {@link Entities.EntityType|Zone} entity with castShadows enabled in its {@link Entities.EntityProperties-Zone|keyLight} property. + * {@link Entities.EntityType|Zone} entity with castShadows enabled in its + * {@link Entities.EntityProperties-Zone|keyLight} property. * * @property {Vec3} position=0,0,0 - The position of the entity. * @property {Quat} rotation=0,0,0,1 - The orientation of the entity with respect to world coordinates. * @property {Vec3} registrationPoint=0.5,0.5,0.5 - The point in the entity that is set to the entity's position and is rotated - * about, {@link Vec3|Vec3.ZERO} – {@link Vec3|Vec3.ONE}. A value of {@link Vec3|Vec3.ZERO} is the entity's - * minimum x, y, z corner; a value of {@link Vec3|Vec3.ONE} is the entity's maximum x, y, z corner. + * about, {@link Vec3(0)|Vec3.ZERO} – {@link Vec3(0)|Vec3.ONE}. A value of {@link Vec3(0)|Vec3.ZERO} is the entity's + * minimum x, y, z corner; a value of {@link Vec3(0)|Vec3.ONE} is the entity's maximum x, y, z corner. * * @property {Vec3} naturalPosition=0,0,0 - The center of the entity's unscaled mesh model if it has one, otherwise - * {@link Vec3|Vec3.ZERO}. Read-only. + * {@link Vec3(0)|Vec3.ZERO}. Read-only. * @property {Vec3} naturalDimensions - The dimensions of the entity's unscaled mesh model if it has one, otherwise - * {@link Vec3|Vec3.ONE}. Read-only. + * {@link Vec3(0)|Vec3.ONE}. Read-only. * * @property {Vec3} velocity=0,0,0 - The linear velocity of the entity in m/s with respect to world coordinates. * @property {number} damping=0.39347 - How much to slow down the linear velocity of an entity over time, 0.0 @@ -505,13 +506,13 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Vec3} gravity=0,0,0 - The acceleration due to gravity in m/s2 that the entity should move with, in * world coordinates. Set to { x: 0, y: -9.8, z: 0 } to simulate Earth's gravity. Gravity is applied to an * entity's motion only if its dynamic property is true. If changing an entity's - * gravity from {@link Vec3|Vec3.ZERO}, you need to give it a small velocity in order to kick off - * physics simulation. + * gravity from {@link Vec3(0)|Vec3.ZERO}, you need to give it a small velocity in order to kick + * off physics simulation. * The gravity value is applied in addition to the acceleration value. * @property {Vec3} acceleration=0,0,0 - A general acceleration in m/s2 that the entity should move with, in world * coordinates. The acceleration is applied to an entity's motion only if its dynamic property is - * true. If changing an entity's acceleration from {@link Vec3|Vec3.ZERO}, you need to give it a - * small velocity in order to kick off physics simulation. + * true. If changing an entity's acceleration from {@link Vec3(0)|Vec3.ZERO}, you need to give it + * a small velocity in order to kick off physics simulation. * The acceleration value is applied in addition to the gravity value. * @property {number} restitution=0.5 - The "bounciness" of an entity when it collides, 0.0 – * 0.99. The higher the value, the more bouncy. diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 4c2a2a47b4..74e7ddb677 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -694,7 +694,7 @@ public slots: * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity. * @param {Vec3} voxelCoords - The voxel coordinates. May be fractional and outside the entity's bounding box. * @returns {Vec3} The world coordinates of the voxelCoords if the entityID is a - * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. + * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. * @example Create a PolyVox cube with the 0,0,0 voxel replaced by a sphere. * // Cube PolyVox with 0,0,0 voxel missing. * var polyVox = Entities.addEntity({ @@ -729,7 +729,7 @@ public slots: * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity. * @param {Vec3} worldCoords - The world coordinates. May be outside the entity's bounding box. * @returns {Vec3} The voxel coordinates of the worldCoords if the entityID is a - * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. The value may be fractional. + * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. The value may be fractional. */ // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords); @@ -741,7 +741,7 @@ public slots: * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity. * @param {Vec3} voxelCoords - The voxel coordinates. May be fractional and outside the entity's bounding box. * @returns {Vec3} The local coordinates of the voxelCoords if the entityID is a - * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. + * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. * @example Get the world dimensions of a voxel in a PolyVox entity. * var polyVox = Entities.addEntity({ * type: "PolyVox", @@ -763,7 +763,7 @@ public slots: * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity. * @param {Vec3} localCoords - The local coordinates. May be outside the entity's bounding box. * @returns {Vec3} The voxel coordinates of the worldCoords if the entityID is a - * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. The value may be fractional. + * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. The value may be fractional. */ // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords); diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index d8b72c8838..c155d5bd7f 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -219,7 +219,29 @@ bool Procedural::isReady() const { return true; } -void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation) { +std::string Procedural::replaceProceduralBlock(const std::string& fragmentSource) { + std::string fragmentShaderSource = fragmentSource; + size_t replaceIndex = fragmentShaderSource.find(PROCEDURAL_COMMON_BLOCK); + if (replaceIndex != std::string::npos) { + fragmentShaderSource.replace(replaceIndex, PROCEDURAL_COMMON_BLOCK.size(), ProceduralCommon_frag::getSource()); + } + + replaceIndex = fragmentShaderSource.find(PROCEDURAL_VERSION); + if (replaceIndex != std::string::npos) { + if (_data.version == 1) { + fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V1 1"); + } else if (_data.version == 2) { + fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V2 1"); + } + } + replaceIndex = fragmentShaderSource.find(PROCEDURAL_BLOCK); + if (replaceIndex != std::string::npos) { + fragmentShaderSource.replace(replaceIndex, PROCEDURAL_BLOCK.size(), _shaderSource.toLocal8Bit().data()); + } + return fragmentShaderSource; +} + +void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const glm::vec4& color) { _entityDimensions = size; _entityPosition = position; _entityOrientation = glm::mat3_cast(orientation); @@ -242,58 +264,48 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm } // Build the fragment shader - std::string fragmentShaderSource = _fragmentSource; - size_t replaceIndex = fragmentShaderSource.find(PROCEDURAL_COMMON_BLOCK); - if (replaceIndex != std::string::npos) { - fragmentShaderSource.replace(replaceIndex, PROCEDURAL_COMMON_BLOCK.size(), ProceduralCommon_frag::getSource()); - } - - replaceIndex = fragmentShaderSource.find(PROCEDURAL_VERSION); - if (replaceIndex != std::string::npos) { - if (_data.version == 1) { - fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V1 1"); - } else if (_data.version == 2) { - fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V2 1"); - } - } - replaceIndex = fragmentShaderSource.find(PROCEDURAL_BLOCK); - if (replaceIndex != std::string::npos) { - fragmentShaderSource.replace(replaceIndex, PROCEDURAL_BLOCK.size(), _shaderSource.toLocal8Bit().data()); - } + std::string opaqueShaderSource = replaceProceduralBlock(_opaquefragmentSource); + std::string transparentShaderSource = replaceProceduralBlock(_transparentfragmentSource); // Leave this here for debugging // qCDebug(procedural) << "FragmentShader:\n" << fragmentShaderSource.c_str(); - _fragmentShader = gpu::Shader::createPixel(fragmentShaderSource); - _shader = gpu::Shader::createProgram(_vertexShader, _fragmentShader); + _opaqueFragmentShader = gpu::Shader::createPixel(opaqueShaderSource); + _opaqueShader = gpu::Shader::createProgram(_vertexShader, _opaqueFragmentShader); + _transparentFragmentShader = gpu::Shader::createPixel(transparentShaderSource); + _transparentShader = gpu::Shader::createProgram(_vertexShader, _transparentFragmentShader); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("iChannel0"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("iChannel1"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("iChannel2"), 2)); slotBindings.insert(gpu::Shader::Binding(std::string("iChannel3"), 3)); - gpu::Shader::makeProgram(*_shader, slotBindings); + gpu::Shader::makeProgram(*_opaqueShader, slotBindings); + gpu::Shader::makeProgram(*_transparentShader, slotBindings); - _opaquePipeline = gpu::Pipeline::create(_shader, _opaqueState); - _transparentPipeline = gpu::Pipeline::create(_shader, _transparentState); + _opaquePipeline = gpu::Pipeline::create(_opaqueShader, _opaqueState); + _transparentPipeline = gpu::Pipeline::create(_transparentShader, _transparentState); for (size_t i = 0; i < NUM_STANDARD_UNIFORMS; ++i) { const std::string& name = STANDARD_UNIFORM_NAMES[i]; - _standardUniformSlots[i] = _shader->getUniforms().findLocation(name); + _standardOpaqueUniformSlots[i] = _opaqueShader->getUniforms().findLocation(name); + _standardTransparentUniformSlots[i] = _transparentShader->getUniforms().findLocation(name); } _start = usecTimestampNow(); _frameCount = 0; } - batch.setPipeline(isFading() ? _transparentPipeline : _opaquePipeline); + bool transparent = color.a < 1.0f; + batch.setPipeline(transparent ? _transparentPipeline : _opaquePipeline); - if (_shaderDirty || _uniformsDirty) { - setupUniforms(); + if (_shaderDirty || _uniformsDirty || _prevTransparent != transparent) { + setupUniforms(transparent); } - if (_shaderDirty || _uniformsDirty || _channelsDirty) { - setupChannels(_shaderDirty || _uniformsDirty); + if (_shaderDirty || _uniformsDirty || _channelsDirty || _prevTransparent != transparent) { + setupChannels(_shaderDirty || _uniformsDirty, transparent); } + _prevTransparent = transparent; _shaderDirty = _uniformsDirty = _channelsDirty = false; for (auto lambda : _uniforms) { @@ -319,12 +331,12 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm } } -void Procedural::setupUniforms() { +void Procedural::setupUniforms(bool transparent) { _uniforms.clear(); // Set any userdata specified uniforms foreach(QString key, _data.uniforms.keys()) { std::string uniformName = key.toLocal8Bit().data(); - int32_t slot = _shader->getUniforms().findLocation(uniformName); + int32_t slot = (transparent ? _transparentShader : _opaqueShader)->getUniforms().findLocation(uniformName); if (gpu::Shader::INVALID_LOCATION == slot) { continue; } @@ -385,15 +397,17 @@ void Procedural::setupUniforms() { } } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[TIME]) { + auto uniformSlots = transparent ? _standardTransparentUniformSlots : _standardOpaqueUniformSlots; + + if (gpu::Shader::INVALID_LOCATION != uniformSlots[TIME]) { _uniforms.push_back([=](gpu::Batch& batch) { // Minimize floating point error by doing an integer division to milliseconds, before the floating point division to seconds float time = (float)((usecTimestampNow() - _start) / USECS_PER_MSEC) / MSECS_PER_SECOND; - batch._glUniform(_standardUniformSlots[TIME], time); + batch._glUniform(uniformSlots[TIME], time); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[DATE]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[DATE]) { _uniforms.push_back([=](gpu::Batch& batch) { QDateTime now = QDateTime::currentDateTimeUtc(); QDate date = now.date(); @@ -406,40 +420,41 @@ void Procedural::setupUniforms() { v.z = date.day(); float fractSeconds = (time.msec() / 1000.0f); v.w = (time.hour() * 3600) + (time.minute() * 60) + time.second() + fractSeconds; - batch._glUniform(_standardUniformSlots[DATE], v); + batch._glUniform(uniformSlots[DATE], v); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[FRAME_COUNT]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[FRAME_COUNT]) { _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[FRAME_COUNT], ++_frameCount); + batch._glUniform(uniformSlots[FRAME_COUNT], ++_frameCount); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[SCALE]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[SCALE]) { // FIXME move into the 'set once' section, since this doesn't change over time _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[SCALE], _entityDimensions); + batch._glUniform(uniformSlots[SCALE], _entityDimensions); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[ORIENTATION]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[ORIENTATION]) { // FIXME move into the 'set once' section, since this doesn't change over time _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[ORIENTATION], _entityOrientation); + batch._glUniform(uniformSlots[ORIENTATION], _entityOrientation); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[POSITION]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[POSITION]) { // FIXME move into the 'set once' section, since this doesn't change over time _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[POSITION], _entityPosition); + batch._glUniform(uniformSlots[POSITION], _entityPosition); }); } } -void Procedural::setupChannels(bool shouldCreate) { - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[CHANNEL_RESOLUTION]) { +void Procedural::setupChannels(bool shouldCreate, bool transparent) { + auto uniformSlots = transparent ? _standardTransparentUniformSlots : _standardOpaqueUniformSlots; + if (gpu::Shader::INVALID_LOCATION != uniformSlots[CHANNEL_RESOLUTION]) { if (!shouldCreate) { // Instead of modifying the last element, just remove and recreate it. _uniforms.pop_back(); @@ -451,7 +466,7 @@ void Procedural::setupChannels(bool shouldCreate) { channelSizes[i] = vec3(_channels[i]->getWidth(), _channels[i]->getHeight(), 1.0); } } - batch._glUniform3fv(_standardUniformSlots[CHANNEL_RESOLUTION], MAX_PROCEDURAL_TEXTURE_CHANNELS, &channelSizes[0].x); + batch._glUniform3fv(uniformSlots[CHANNEL_RESOLUTION], MAX_PROCEDURAL_TEXTURE_CHANNELS, &channelSizes[0].x); }); } } diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 9c29a681f0..1d3b0b3b5a 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -55,8 +55,8 @@ public: bool isReady() const; bool isEnabled() const { return _enabled; } - void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation); - const gpu::ShaderPointer& getShader() const { return _shader; } + void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const glm::vec4& color = glm::vec4(1)); + const gpu::ShaderPointer& getOpaqueShader() const { return _opaqueShader; } glm::vec4 getColor(const glm::vec4& entityColor); quint64 getFadeStartTime() const { return _fadeStartTime; } @@ -65,7 +65,8 @@ public: void setDoesFade(bool doesFade) { _doesFade = doesFade; } std::string _vertexSource; - std::string _fragmentSource; + std::string _opaquefragmentSource; + std::string _transparentfragmentSource; gpu::StatePointer _opaqueState { std::make_shared() }; gpu::StatePointer _transparentState { std::make_shared() }; @@ -101,13 +102,16 @@ protected: // Rendering objects UniformLambdas _uniforms; - int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS]; + int32_t _standardOpaqueUniformSlots[NUM_STANDARD_UNIFORMS]; + int32_t _standardTransparentUniformSlots[NUM_STANDARD_UNIFORMS]; NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS]; gpu::PipelinePointer _opaquePipeline; gpu::PipelinePointer _transparentPipeline; gpu::ShaderPointer _vertexShader; - gpu::ShaderPointer _fragmentShader; - gpu::ShaderPointer _shader; + gpu::ShaderPointer _opaqueFragmentShader; + gpu::ShaderPointer _transparentFragmentShader; + gpu::ShaderPointer _opaqueShader; + gpu::ShaderPointer _transparentShader; // Entity metadata glm::vec3 _entityDimensions; @@ -116,13 +120,16 @@ protected: private: // This should only be called from the render thread, as it shares data with Procedural::prepare - void setupUniforms(); - void setupChannels(bool shouldCreate); + void setupUniforms(bool transparent); + void setupChannels(bool shouldCreate, bool transparent); + + std::string replaceProceduralBlock(const std::string& fragmentSource); mutable quint64 _fadeStartTime { 0 }; mutable bool _hasStartedFade { false }; mutable bool _isFading { false }; bool _doesFade { true }; + bool _prevTransparent { false }; }; #endif diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 43633e47ad..0c6501928b 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -20,7 +20,7 @@ ProceduralSkybox::ProceduralSkybox() : graphics::Skybox() { _procedural._vertexSource = skybox_vert::getSource(); - _procedural._fragmentSource = skybox_frag::getSource(); + _procedural._opaquefragmentSource = skybox_frag::getSource(); // Adjust the pipeline state for background using the stencil test _procedural.setDoesFade(false); // Must match PrepareStencil::STENCIL_BACKGROUND @@ -61,8 +61,8 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, auto& procedural = skybox._procedural; procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat()); - auto textureSlot = procedural.getShader()->getTextures().findLocation("cubeMap"); - auto bufferSlot = procedural.getShader()->getUniformBuffers().findLocation("skyboxBuffer"); + auto textureSlot = procedural.getOpaqueShader()->getTextures().findLocation("cubeMap"); + auto bufferSlot = procedural.getOpaqueShader()->getUniformBuffers().findLocation("skyboxBuffer"); skybox.prepare(batch, textureSlot, bufferSlot); batch.draw(gpu::TRIANGLE_STRIP, 4); } diff --git a/libraries/render-utils/src/DefaultMaterials.slh b/libraries/render-utils/src/DefaultMaterials.slh new file mode 100644 index 0000000000..afb3dc2b28 --- /dev/null +++ b/libraries/render-utils/src/DefaultMaterials.slh @@ -0,0 +1,23 @@ + +<@if not DEFAULT_MATERIAL_SLH@> +<@def DEFAULT_MATERIAL_SLH@> + +const float DEFAULT_ROUGHNESS = 0.9; +const float DEFAULT_SHININESS = 10.0; +const float DEFAULT_METALLIC = 0.0; +const vec3 DEFAULT_SPECULAR = vec3(0.1); +const vec3 DEFAULT_EMISSIVE = vec3(0.0); +const float DEFAULT_OCCLUSION = 1.0; +const float DEFAULT_SCATTERING = 0.0; +const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE; + +<@endif@> diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 2f6bfaeb61..49db49af2a 100644 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -26,14 +26,7 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold)); } -const float DEFAULT_ROUGHNESS = 0.9; -const float DEFAULT_SHININESS = 10.0; -const float DEFAULT_METALLIC = 0.0; -const vec3 DEFAULT_SPECULAR = vec3(0.1); -const vec3 DEFAULT_EMISSIVE = vec3(0.0); -const float DEFAULT_OCCLUSION = 1.0; -const float DEFAULT_SCATTERING = 0.0; -const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE; +<@include DefaultMaterials.slh@> void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) { if (alpha != 1.0) { diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 3fd18a0eaf..ecfa9881a3 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -40,6 +40,7 @@ #include "simple_vert.h" #include "simple_textured_frag.h" +#include "simple_transparent_textured_frag.h" #include "simple_textured_unlit_frag.h" #include "simple_fade_vert.h" #include "simple_textured_fade_frag.h" @@ -49,6 +50,19 @@ #include "glowLine_vert.h" #include "glowLine_frag.h" +#include "forward_simple_textured_frag.h" +#include "forward_simple_textured_transparent_frag.h" +#include "forward_simple_textured_unlit_frag.h" + +#include "DeferredLightingEffect.h" + +#if defined(USE_GLES) +static bool DISABLE_DEFERRED = true; +#else +static const QString RENDER_FORWARD{ "HIFI_RENDER_FORWARD" }; +static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD); +#endif + #include "grid_frag.h" //#define WANT_DEBUG @@ -679,6 +693,7 @@ gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() { QHash GeometryCache::_simplePrograms; gpu::ShaderPointer GeometryCache::_simpleShader; +gpu::ShaderPointer GeometryCache::_transparentShader; gpu::ShaderPointer GeometryCache::_unlitShader; gpu::ShaderPointer GeometryCache::_simpleFadeShader; gpu::ShaderPointer GeometryCache::_unlitFadeShader; @@ -774,8 +789,12 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool bool unlit, bool depthBias) { return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true), nullptr, - [](const render::ShapePipeline& , gpu::Batch& batch, render::Args*) { + [](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); + DependencyManager::get()->setupKeyLightBatch(args, batch, + pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("keyLightBuffer"), + pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("lightAmbientBuffer"), + pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("skyboxMap")); } ); } @@ -798,7 +817,7 @@ render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline; } -render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { +render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline; } @@ -843,7 +862,7 @@ void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, siz _shapes[shape].drawWireInstances(batch, count); } -void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, +void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, gpu::BufferPointer fadeBuffer1, gpu::BufferPointer fadeBuffer2, gpu::BufferPointer fadeBuffer3) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT); @@ -2003,7 +2022,7 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const auto program = gpu::Shader::createProgram(VS, PS); state->setCullMode(gpu::State::CULL_NONE); state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setBlendFunction(true, + 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); @@ -2231,29 +2250,41 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp static std::once_flag once; std::call_once(once, [&]() { auto VS = simple_vert::getShader(); - auto PS = simple_textured_frag::getShader(); - auto PSUnlit = simple_textured_unlit_frag::getShader(); + auto PS = DISABLE_DEFERRED ? forward_simple_textured_frag::getShader() : simple_textured_frag::getShader(); + // Use the forward pipeline for both here, otherwise transparents will be unlit + auto PSTransparent = DISABLE_DEFERRED ? forward_simple_textured_transparent_frag::getShader() : forward_simple_textured_transparent_frag::getShader(); + auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit_frag::getShader() : simple_textured_unlit_frag::getShader(); _simpleShader = gpu::Shader::createProgram(VS, PS); + _transparentShader = gpu::Shader::createProgram(VS, PSTransparent); _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), render::ShapePipeline::Slot::LIGHTING_MODEL)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), render::ShapePipeline::Slot::KEY_LIGHT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), render::ShapePipeline::Slot::MAP::LIGHT_AMBIENT)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); + gpu::Shader::makeProgram(*_transparentShader, slotBindings); gpu::Shader::makeProgram(*_unlitShader, slotBindings); }); } else { static std::once_flag once; std::call_once(once, [&]() { auto VS = simple_fade_vert::getShader(); - auto PS = simple_textured_fade_frag::getShader(); - auto PSUnlit = simple_textured_unlit_fade_frag::getShader(); + auto PS = DISABLE_DEFERRED ? forward_simple_textured_frag::getShader() : simple_textured_fade_frag::getShader(); + auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit_frag::getShader() : simple_textured_unlit_fade_frag::getShader(); _simpleFadeShader = gpu::Shader::createProgram(VS, PS); _unlitFadeShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), render::ShapePipeline::Slot::LIGHTING_MODEL)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), render::ShapePipeline::Slot::KEY_LIGHT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), render::ShapePipeline::Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), render::ShapePipeline::Slot::MAP::FADE_MASK)); gpu::Shader::makeProgram(*_simpleFadeShader, slotBindings); gpu::Shader::makeProgram(*_unlitFadeShader, slotBindings); @@ -2282,7 +2313,8 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp PrepareStencil::testMaskDrawShapeNoAA(*state); } - gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : (config.isFading() ? _simpleFadeShader : _simpleShader); + gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : + (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader)); gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state); _simplePrograms.insert(config, pipeline); return pipeline; @@ -2363,11 +2395,11 @@ void renderFadeInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& c pipeline->prepare(batch, args); if (isWire) { - DependencyManager::get()->renderWireFadeShapeInstances(batch, shape, data.count(), + DependencyManager::get()->renderWireFadeShapeInstances(batch, shape, data.count(), buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]); } else { - DependencyManager::get()->renderFadeShapeInstances(batch, shape, data.count(), + DependencyManager::get()->renderFadeShapeInstances(batch, shape, data.count(), buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]); } }); @@ -2383,15 +2415,15 @@ void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, renderInstances(args, batch, color, true, pipeline, shape); } -void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, - int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, +void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, + int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, const render::ShapePipelinePointer& pipeline) { assert(pipeline != nullptr); renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, false, pipeline, shape); } -void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, - int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, +void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, + int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, const render::ShapePipelinePointer& pipeline) { assert(pipeline != nullptr); renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, true, pipeline, shape); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index e0ba99b09e..fcbf5ee128 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -471,6 +471,7 @@ private: QHash _registeredGridBuffers; static gpu::ShaderPointer _simpleShader; + static gpu::ShaderPointer _transparentShader; static gpu::ShaderPointer _unlitShader; static gpu::ShaderPointer _simpleFadeShader; static gpu::ShaderPointer _unlitFadeShader; @@ -478,8 +479,6 @@ private: static render::ShapePipelinePointer _simpleTransparentPipeline; static render::ShapePipelinePointer _simpleOpaqueFadePipeline; static render::ShapePipelinePointer _simpleTransparentFadePipeline; - static render::ShapePipelinePointer _simpleOpaqueOverlayPipeline; - static render::ShapePipelinePointer _simpleTransparentOverlayPipeline; static render::ShapePipelinePointer _simpleWirePipeline; gpu::PipelinePointer _glowLinePipeline; diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index 008f29da01..b2377d1904 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -111,15 +111,11 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie } <@endif@> - if (!(isObscuranceEnabled() > 0.0)) { - obscurance = 1.0; - } + obscurance = mix(1.0, obscurance, isObscuranceEnabled()); float lightEnergy = obscurance * getLightAmbientIntensity(ambient); - if (isAlbedoEnabled() > 0.0) { - diffuse *= albedo; - } + diffuse *= mix(vec3(1), albedo, isAlbedoEnabled()); lightEnergy *= isAmbientEnabled(); diffuse *= lightEnergy * isDiffuseEnabled(); diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index 2280d12465..3f615f11db 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -13,11 +13,19 @@ <@func declareLightingModel()@> +#ifndef PRECISIONQ +#ifdef GL_ES +#define PRECISIONQ highp +#else +#define PRECISIONQ +#endif +#endif + struct LightingModel { - vec4 _UnlitEmissiveLightmapBackground; - vec4 _ScatteringDiffuseSpecularAlbedo; - vec4 _AmbientDirectionalPointSpot; - vec4 _ShowContourObscuranceWireframe; + PRECISIONQ vec4 _UnlitEmissiveLightmapBackground; + PRECISIONQ vec4 _ScatteringDiffuseSpecularAlbedo; + PRECISIONQ vec4 _AmbientDirectionalPointSpot; + PRECISIONQ vec4 _ShowContourObscuranceWireframe; }; uniform lightingModelBuffer{ @@ -256,9 +264,7 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) { vec4 shading = evalPBRShading(metallic, fresnel, surface); diffuse = vec3(shading.w); - if (isAlbedoEnabled() > 0.0) { - diffuse *= albedo; - } + diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); specular = shading.xyz; } diff --git a/libraries/render-utils/src/Shadows_shared.slh b/libraries/render-utils/src/Shadows_shared.slh index 0d49fc037e..bc8063e018 100644 --- a/libraries/render-utils/src/Shadows_shared.slh +++ b/libraries/render-utils/src/Shadows_shared.slh @@ -1,10 +1,8 @@ // glsl / C++ compatible source as interface for Shadows #ifdef __cplusplus # define MAT4 glm::mat4 -# define VEC3 glm::vec3 #else # define MAT4 mat4 -# define VEC3 vec3 #endif #define SHADOW_CASCADE_MAX_COUNT 4 diff --git a/libraries/render-utils/src/forward_simple.slf b/libraries/render-utils/src/forward_simple.slf new file mode 100644 index 0000000000..ac2aa63697 --- /dev/null +++ b/libraries/render-utils/src/forward_simple.slf @@ -0,0 +1,83 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// forward_simple.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 DefaultMaterials.slh@> + +<@include ForwardGlobalLight.slh@> +<$declareEvalSkyboxGlobalColor()$> + +// the interpolated normal +in vec3 _normal; +in vec3 _modelNormal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _position; +in vec4 _eyePosition; + +layout(location = 0) out vec4 _fragColor0; + +//PROCEDURAL_COMMON_BLOCK + +#line 1001 +//PROCEDURAL_BLOCK + +#line 2030 +void main(void) { + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; + vec3 specular = DEFAULT_SPECULAR; + float shininess = DEFAULT_SHININESS; + float emissiveAmount = 0.0; + +#ifdef PROCEDURAL + +#ifdef PROCEDURAL_V1 + specular = getProceduralColor().rgb; + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + //specular = pow(specular, vec3(2.2)); + emissiveAmount = 1.0; +#else + emissiveAmount = getProceduralColors(diffuse, specular, shininess); +#endif + +#endif + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _eyePosition.xyz; + + if (emissiveAmount > 0.0) { + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normal, + diffuse, + specular, + DEFAULT_METALLIC, + max(0.0, 1.0 - shininess / 128.0)), + 1.0); + } else { + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normal, + diffuse, + DEFAULT_FRESNEL, + length(specular), + max(0.0, 1.0 - shininess / 128.0)), + 1.0); + } +} diff --git a/libraries/render-utils/src/forward_simple_textured.slf b/libraries/render-utils/src/forward_simple_textured.slf new file mode 100644 index 0000000000..c88482c208 --- /dev/null +++ b/libraries/render-utils/src/forward_simple_textured.slf @@ -0,0 +1,51 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// forward_simple_textured.slf +// fragment shader +// +// Created by Clément Brisset on 5/29/15. +// Copyright 2014 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 DefaultMaterials.slh@> + +<@include ForwardGlobalLight.slh@> +<$declareEvalSkyboxGlobalColor()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _eyePosition; + +layout(location = 0) out vec4 _fragColor0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a * texel.a; + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _eyePosition.xyz; + + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normal), + _color.rgb * texel.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_ROUGHNESS), + 1.0); +} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_textured_transparent.slf b/libraries/render-utils/src/forward_simple_textured_transparent.slf new file mode 100644 index 0000000000..a8f23907d3 --- /dev/null +++ b/libraries/render-utils/src/forward_simple_textured_transparent.slf @@ -0,0 +1,52 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// forward_simple_textured_transparent.slf +// fragment shader +// +// Created by Clément Brisset on 5/29/15. +// Copyright 2014 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 DefaultMaterials.slh@> + +<@include ForwardGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _eyePosition; + +layout(location = 0) out vec4 _fragColor0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a * texel.a; + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _eyePosition.xyz; + + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normal), + _color.rgb * texel.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_ROUGHNESS, colorAlpha), + colorAlpha); +} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_textured_unlit.slf b/libraries/render-utils/src/forward_simple_textured_unlit.slf new file mode 100644 index 0000000000..0cc241b75e --- /dev/null +++ b/libraries/render-utils/src/forward_simple_textured_unlit.slf @@ -0,0 +1,31 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_textured_unlit.frag +// fragment shader +// +// Created by Clément Brisset on 5/29/15. +// Copyright 2014 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 LightingModel.slh@> +<@include gpu/Color.slh@> + +layout(location = 0) out vec4 _fragColor0; + +// the albedo texture +uniform sampler2D originalTexture; + +in vec4 _color; +in vec2 _texCoord0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0.st); + float colorAlpha = _color.a * texel.a; + + _fragColor0 = vec4(_color.rgb * texel.rgb * isUnlitEnabled(), colorAlpha); +} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_transparent.slf b/libraries/render-utils/src/forward_simple_transparent.slf new file mode 100644 index 0000000000..551e10282a --- /dev/null +++ b/libraries/render-utils/src/forward_simple_transparent.slf @@ -0,0 +1,84 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// forward_simple_transparent.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 DefaultMaterials.slh@> + +<@include ForwardGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +// the interpolated normal +in vec3 _normal; +in vec3 _modelNormal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _eyePosition; + +layout(location = 0) out vec4 _fragColor0; + +//PROCEDURAL_COMMON_BLOCK + +#line 1001 +//PROCEDURAL_BLOCK + +#line 2030 +void main(void) { + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; + vec3 specular = DEFAULT_SPECULAR; + float shininess = DEFAULT_SHININESS; + float emissiveAmount = 0.0; + +#ifdef PROCEDURAL + +#ifdef PROCEDURAL_V1 + specular = getProceduralColor().rgb; + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + //specular = pow(specular, vec3(2.2)); + emissiveAmount = 1.0; +#else + emissiveAmount = getProceduralColors(diffuse, specular, shininess); +#endif + +#endif + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _eyePosition.xyz; + + if (emissiveAmount > 0.0) { + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normal, + specular, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_ROUGHNESS, _color.a), + _color.a); + } else { + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normal, + diffuse, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_ROUGHNESS, _color.a), + _color.a); + } +} diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 7b32541c63..1c2ad9a413 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -13,7 +13,6 @@ // <@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> // the interpolated normal in vec3 _normal; @@ -29,9 +28,8 @@ in vec4 _position; #line 2030 void main(void) { - Material material = getMaterial(); - vec3 normal = normalize(_normal.xyz); - vec3 diffuse = _color.rgb; + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; vec3 specular = DEFAULT_SPECULAR; float shininess = DEFAULT_SHININESS; float emissiveAmount = 0.0; @@ -43,49 +41,30 @@ void main(void) { // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline //specular = pow(specular, vec3(2.2)); emissiveAmount = 1.0; -#else +#else emissiveAmount = getProceduralColors(diffuse, specular, shininess); #endif #endif - const float ALPHA_THRESHOLD = 0.999; - if (_color.a < ALPHA_THRESHOLD) { - if (emissiveAmount > 0.0) { - packDeferredFragmentTranslucent( - normal, - _color.a, - specular, - DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragmentTranslucent( - normal, - _color.a, - diffuse, - DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); - } + if (emissiveAmount > 0.0) { + packDeferredFragmentLightmap( + normal, + 1.0, + diffuse, + max(0.0, 1.0 - shininess / 128.0), + DEFAULT_METALLIC, + specular, + vec3(clamp(emissiveAmount, 0.0, 1.0))); } else { - if (emissiveAmount > 0.0) { - packDeferredFragmentLightmap( - normal, - 1.0, - diffuse, - max(0.0, 1.0 - shininess / 128.0), - DEFAULT_METALLIC, - specular, - vec3(clamp(emissiveAmount, 0.0, 1.0))); - } else { - packDeferredFragment( - normal, - 1.0, - diffuse, - max(0.0, 1.0 - shininess / 128.0), - length(specular), - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); - } + packDeferredFragment( + normal, + 1.0, + diffuse, + max(0.0, 1.0 - shininess / 128.0), + length(specular), + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); } } diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 0ce6505a65..f63ccb61a6 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -23,6 +23,7 @@ out vec3 _modelNormal; out vec4 _color; out vec2 _texCoord0; out vec4 _position; +out vec4 _eyePosition; void main(void) { _color = color_sRGBAToLinear(inColor); @@ -33,6 +34,6 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _eyePosition, gl_Position)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf index ce9251b9a5..1c74612ff0 100644 --- a/libraries/render-utils/src/simple_fade.slf +++ b/libraries/render-utils/src/simple_fade.slf @@ -13,7 +13,6 @@ // <@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> <@include Fade.slh@> <$declareFadeFragmentInstanced()$> @@ -39,7 +38,6 @@ void main(void) { <$fetchFadeObjectParamsInstanced(fadeParams)$> applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); - Material material = getMaterial(); vec3 normal = normalize(_normal.xyz); vec3 diffuse = _color.rgb; vec3 specular = DEFAULT_SPECULAR; diff --git a/libraries/render-utils/src/simple_fade.slv b/libraries/render-utils/src/simple_fade.slv index 85946045ac..6dbe40485a 100644 --- a/libraries/render-utils/src/simple_fade.slv +++ b/libraries/render-utils/src/simple_fade.slv @@ -26,6 +26,7 @@ out vec3 _modelNormal; out vec4 _color; out vec2 _texCoord0; out vec4 _position; +out vec4 _eyePosition; out vec4 _worldPosition; void main(void) { @@ -37,7 +38,7 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _eyePosition, gl_Position)$> <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> <$passThroughFadeObjectParams()$> diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 4fd734aad5..bb50c9d158 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -12,9 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> // the albedo texture uniform sampler2D originalTexture; @@ -26,29 +24,14 @@ in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - float colorAlpha = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - colorAlpha = -_color.a; - } - const float ALPHA_THRESHOLD = 0.999; - if (colorAlpha * texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - normalize(_normal), - colorAlpha * texel.a, - _color.rgb * texel.rgb, - DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragment( - normalize(_normal), - 1.0, - _color.rgb * texel.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); - } + packDeferredFragment( + normalize(_normal), + 1.0, + _color.rgb * texel.rgb, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index d378e7a5c1..e5ecd94852 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -14,7 +14,6 @@ <@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> <@include Fade.slh@> diff --git a/libraries/render-utils/src/simple_transparent.slf b/libraries/render-utils/src/simple_transparent.slf new file mode 100644 index 0000000000..65ffe0504a --- /dev/null +++ b/libraries/render-utils/src/simple_transparent.slf @@ -0,0 +1,65 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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@> + +// the interpolated normal +in vec3 _normal; +in vec3 _modelNormal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _position; + +//PROCEDURAL_COMMON_BLOCK + +#line 1001 +//PROCEDURAL_BLOCK + +#line 2030 +void main(void) { + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; + vec3 specular = DEFAULT_SPECULAR; + float shininess = DEFAULT_SHININESS; + float emissiveAmount = 0.0; + +#ifdef PROCEDURAL + +#ifdef PROCEDURAL_V1 + specular = getProceduralColor().rgb; + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + //specular = pow(specular, vec3(2.2)); + emissiveAmount = 1.0; +#else + emissiveAmount = getProceduralColors(diffuse, specular, shininess); +#endif + +#endif + + if (emissiveAmount > 0.0) { + packDeferredFragmentTranslucent( + normal, + _color.a, + specular, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } else { + packDeferredFragmentTranslucent( + normal, + _color.a, + diffuse, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } +} diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index c6b0d83914..7c7168ec0f 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -12,51 +12,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Color.slh@> - <@include DeferredBufferWrite.slh@> -<@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> // the albedo texture uniform sampler2D originalTexture; // the interpolated normal -in vec4 _position; in vec3 _normal; in vec4 _color; in vec2 _texCoord0; void main(void) { - vec4 texel = texture(originalTexture, _texCoord0.st); - float opacity = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - opacity = -_color.a; - } - opacity *= texel.a; - vec3 albedo = _color.rgb * texel.rgb; + vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a * texel.a; - vec3 fragPosition = _position.xyz; - vec3 fragNormal = normalize(_normal); - - TransformCamera cam = getTransformCamera(); - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - 1.0, - fragPosition, - fragNormal, - albedo, + packDeferredFragmentTranslucent( + normalize(_normal), + colorAlpha, + _color.rgb * texel.rgb, DEFAULT_FRESNEL, - 0.0, - vec3(0.0f), - DEFAULT_ROUGHNESS, - opacity), - opacity); - + DEFAULT_ROUGHNESS); } \ No newline at end of file diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index 1f73f14b2b..e4da94ccd5 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -24,11 +24,12 @@ exports.handlers = { '../../libraries/animation/src', '../../libraries/avatars/src', '../../libraries/controllers/src/controllers/', - '../../libraries/graphics-scripting/src/graphics-scripting/', + '../../libraries/display-plugins/src/display-plugins/', '../../libraries/entities/src', + '../../libraries/graphics-scripting/src/graphics-scripting/', '../../libraries/model-networking/src/model-networking/', - '../../libraries/octree/src', '../../libraries/networking/src', + '../../libraries/octree/src', '../../libraries/physics/src', '../../libraries/pointers/src', '../../libraries/script-engine/src',