mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 03:08:00 +02:00
Merging with upstream
This commit is contained in:
commit
982664dac5
28 changed files with 500 additions and 80 deletions
|
@ -386,8 +386,11 @@ bool AudioMixer::prepareMixForListeningNode(Node* node) {
|
||||||
// loop through all other nodes that have sufficient audio to mix
|
// loop through all other nodes that have sufficient audio to mix
|
||||||
|
|
||||||
DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& otherNode){
|
DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& otherNode){
|
||||||
// make sure that we have audio data for this other node and that it isn't being ignored by our listening node
|
// make sure that we have audio data for this other node
|
||||||
if (otherNode->getLinkedData() && !node->isIgnoringNodeWithID(otherNode->getUUID())) {
|
// and that it isn't being ignored by our listening node
|
||||||
|
// and that it isn't ignoring our listening node
|
||||||
|
if (otherNode->getLinkedData()
|
||||||
|
&& !node->isIgnoringNodeWithID(otherNode->getUUID()) && !otherNode->isIgnoringNodeWithID(node->getUUID())) {
|
||||||
AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData();
|
AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData();
|
||||||
|
|
||||||
// enumerate the ARBs attached to the otherNode and add all that should be added to mix
|
// enumerate the ARBs attached to the otherNode and add all that should be added to mix
|
||||||
|
|
|
@ -230,9 +230,11 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
[&](const SharedNodePointer& otherNode)->bool {
|
[&](const SharedNodePointer& otherNode)->bool {
|
||||||
// make sure we have data for this avatar, that it isn't the same node,
|
// make sure we have data for this avatar, that it isn't the same node,
|
||||||
// and isn't an avatar that the viewing node has ignored
|
// and isn't an avatar that the viewing node has ignored
|
||||||
|
// or that has ignored the viewing node
|
||||||
if (!otherNode->getLinkedData()
|
if (!otherNode->getLinkedData()
|
||||||
|| otherNode->getUUID() == node->getUUID()
|
|| otherNode->getUUID() == node->getUUID()
|
||||||
|| node->isIgnoringNodeWithID(otherNode->getUUID())) {
|
|| node->isIgnoringNodeWithID(otherNode->getUUID())
|
||||||
|
|| otherNode->isIgnoringNodeWithID(node->getUUID())) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -109,7 +109,14 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
|
||||||
// set the sending sock addr and node interest set on this node
|
// set the sending sock addr and node interest set on this node
|
||||||
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
|
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
|
||||||
nodeData->setSendingSockAddr(message->getSenderSockAddr());
|
nodeData->setSendingSockAddr(message->getSenderSockAddr());
|
||||||
nodeData->setNodeInterestSet(nodeConnection.interestList.toSet());
|
|
||||||
|
// guard against patched agents asking to hear about other agents
|
||||||
|
auto safeInterestSet = nodeConnection.interestList.toSet();
|
||||||
|
if (nodeConnection.nodeType == NodeType::Agent) {
|
||||||
|
safeInterestSet.remove(NodeType::Agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeData->setNodeInterestSet(safeInterestSet);
|
||||||
nodeData->setPlaceName(nodeConnection.placeName);
|
nodeData->setPlaceName(nodeConnection.placeName);
|
||||||
|
|
||||||
// signal that we just connected a node so the DomainServer can get it a list
|
// signal that we just connected a node so the DomainServer can get it a list
|
||||||
|
|
|
@ -843,7 +843,14 @@ void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> mess
|
||||||
|
|
||||||
// update the NodeInterestSet in case there have been any changes
|
// update the NodeInterestSet in case there have been any changes
|
||||||
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(sendingNode->getLinkedData());
|
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(sendingNode->getLinkedData());
|
||||||
nodeData->setNodeInterestSet(nodeRequestData.interestList.toSet());
|
|
||||||
|
// guard against patched agents asking to hear about other agents
|
||||||
|
auto safeInterestSet = nodeRequestData.interestList.toSet();
|
||||||
|
if (sendingNode->getType() == NodeType::Agent) {
|
||||||
|
safeInterestSet.remove(NodeType::Agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeData->setNodeInterestSet(safeInterestSet);
|
||||||
|
|
||||||
// update the connecting hostname in case it has changed
|
// update the connecting hostname in case it has changed
|
||||||
nodeData->setPlaceName(nodeRequestData.placeName);
|
nodeData->setPlaceName(nodeRequestData.placeName);
|
||||||
|
@ -950,7 +957,8 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
if (nodeData->isAuthenticated()) {
|
if (nodeData->isAuthenticated()) {
|
||||||
// if this authenticated node has any interest types, send back those nodes as well
|
// if this authenticated node has any interest types, send back those nodes as well
|
||||||
limitedNodeList->eachNode([&](const SharedNodePointer& otherNode){
|
limitedNodeList->eachNode([&](const SharedNodePointer& otherNode){
|
||||||
if (otherNode->getUUID() != node->getUUID() && nodeInterestSet.contains(otherNode->getType())) {
|
if (otherNode->getUUID() != node->getUUID()
|
||||||
|
&& nodeInterestSet.contains(otherNode->getType())) {
|
||||||
|
|
||||||
// since we're about to add a node to the packet we start a segment
|
// since we're about to add a node to the packet we start a segment
|
||||||
domainListPackets->startSegment();
|
domainListPackets->startSegment();
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 84 KiB |
|
@ -37,7 +37,17 @@ static int cameraModeId = qRegisterMetaType<CameraMode>();
|
||||||
|
|
||||||
class Camera : public QObject {
|
class Camera : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @namespace Camera
|
||||||
|
* @property position {Vec3} The position of the camera.
|
||||||
|
* @property orientation {Quat} The orientation of the camera.
|
||||||
|
* @property mode {string} The current camera mode.
|
||||||
|
* @property cameraEntity {EntityID} The position and rotation properties of
|
||||||
|
* the entity specified by this ID are then used as the camera's position and
|
||||||
|
* orientation. Only works when <code>mode</code> is "entity".
|
||||||
|
* @property frustum {Object} The frustum of the camera.
|
||||||
|
*/
|
||||||
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
|
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
|
||||||
Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
|
Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
|
||||||
Q_PROPERTY(QString mode READ getModeString WRITE setModeString)
|
Q_PROPERTY(QString mode READ getModeString WRITE setModeString)
|
||||||
|
@ -47,13 +57,13 @@ class Camera : public QObject {
|
||||||
public:
|
public:
|
||||||
Camera();
|
Camera();
|
||||||
|
|
||||||
void initialize(); // instantly put the camera at the ideal position and orientation.
|
void initialize(); // instantly put the camera at the ideal position and orientation.
|
||||||
|
|
||||||
void update( float deltaTime );
|
void update( float deltaTime );
|
||||||
|
|
||||||
CameraMode getMode() const { return _mode; }
|
CameraMode getMode() const { return _mode; }
|
||||||
void setMode(CameraMode m);
|
void setMode(CameraMode m);
|
||||||
|
|
||||||
void loadViewFrustum(ViewFrustum& frustum) const;
|
void loadViewFrustum(ViewFrustum& frustum) const;
|
||||||
ViewFrustum toViewFrustum() const;
|
ViewFrustum toViewFrustum() const;
|
||||||
|
|
||||||
|
@ -80,20 +90,44 @@ public slots:
|
||||||
QUuid getCameraEntity() const;
|
QUuid getCameraEntity() const;
|
||||||
void setCameraEntity(QUuid entityID);
|
void setCameraEntity(QUuid entityID);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Compute a {PickRay} based on the current camera configuration and the position x,y on the screen.
|
||||||
|
* @function Camera.computePickRay
|
||||||
|
* @param {float} x X-coordinate on screen.
|
||||||
|
* @param {float} y Y-coordinate on screen.
|
||||||
|
* @return {PickRay} The computed {PickRay}.
|
||||||
|
*/
|
||||||
PickRay computePickRay(float x, float y);
|
PickRay computePickRay(float x, float y);
|
||||||
|
|
||||||
// These only work on independent cameras
|
/**jsdoc
|
||||||
/// one time change to what the camera is looking at
|
* Set the camera to look at position <code>position</code>. Only works while in <code>independent</code>.
|
||||||
void lookAt(const glm::vec3& value);
|
* camera mode.
|
||||||
|
* @function Camera.lookAt
|
||||||
|
* @param {Vec3} Position Position to look at.
|
||||||
|
*/
|
||||||
|
void lookAt(const glm::vec3& position);
|
||||||
|
|
||||||
/// fix what the camera is looking at, and keep the camera looking at this even if position changes
|
/**jsdoc
|
||||||
void keepLookingAt(const glm::vec3& value);
|
* Set the camera to continue looking at position <code>position</code>.
|
||||||
|
* Only works while in `independent` camera mode.
|
||||||
|
* @function Camera.keepLookingAt
|
||||||
|
* @param {Vec3} position Position to keep looking at.
|
||||||
|
*/
|
||||||
|
void keepLookingAt(const glm::vec3& position);
|
||||||
|
|
||||||
/// stops the keep looking at feature, doesn't change what's being looked at, but will stop camera from
|
/**jsdoc
|
||||||
/// continuing to update it's orientation to keep looking at the item
|
* Stops the camera from continually looking at a position that was set with
|
||||||
|
* `keepLookingAt`
|
||||||
|
* @function Camera.stopLookingAt
|
||||||
|
*/
|
||||||
void stopLooking() { _isKeepLookingAt = false; }
|
void stopLooking() { _isKeepLookingAt = false; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
/**jsdoc
|
||||||
|
* Triggered when camera mode has changed.
|
||||||
|
* @function Camera.modeUpdated
|
||||||
|
* @return {Signal}
|
||||||
|
*/
|
||||||
void modeUpdated(const QString& newMode);
|
void modeUpdated(const QString& newMode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @namespace Clipboard
|
||||||
|
*/
|
||||||
class ClipboardScriptingInterface : public QObject {
|
class ClipboardScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -21,13 +24,47 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void readyToImport();
|
void readyToImport();
|
||||||
|
|
||||||
public slots:
|
public:
|
||||||
glm::vec3 getContentsDimensions(); /// returns the overall dimensions of everything on the blipboard
|
/**jsdoc
|
||||||
float getClipboardContentsLargestDimension(); /// returns the largest dimension of everything on the clipboard
|
* @function Clipboard.getContentsDimensions
|
||||||
bool importEntities(const QString& filename);
|
* @return {Vec3} The extents of the contents held in the clipboard.
|
||||||
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs);
|
*/
|
||||||
bool exportEntities(const QString& filename, float x, float y, float z, float s);
|
Q_INVOKABLE glm::vec3 getContentsDimensions();
|
||||||
QVector<EntityItemID> pasteEntities(glm::vec3 position);
|
|
||||||
|
/**jsdoc
|
||||||
|
* Compute largest dimension of the extents of the contents held in the clipboard
|
||||||
|
* @function Clipboard.getClipboardContentsLargestDimension
|
||||||
|
* @return {float} The largest dimension computed.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE float getClipboardContentsLargestDimension();
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Import entities from a .json file containing entity data into the clipboard.
|
||||||
|
* You can generate * a .json file using {Clipboard.exportEntities}.
|
||||||
|
* @function Clipboard.importEntities
|
||||||
|
* @param {string} filename Filename of file to import.
|
||||||
|
* @return {bool} True if the import was succesful, otherwise false.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE bool importEntities(const QString& filename);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Export the entities listed in `entityIDs` to the file `filename`
|
||||||
|
* @function Clipboard.exportEntities
|
||||||
|
* @param {string} filename Path to the file to export entities to.
|
||||||
|
* @param {EntityID[]} entityIDs IDs of entities to export.
|
||||||
|
* @return {bool} True if the export was succesful, otherwise false.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs);
|
||||||
|
Q_INVOKABLE bool exportEntities(const QString& filename, float x, float y, float z, float s);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Paste the contents of the clipboard into the world.
|
||||||
|
* @function Clipboard.pasteEntities
|
||||||
|
* @param {Vec3} position Position to paste clipboard at.
|
||||||
|
* @return {EntityID[]} Array of entity IDs for the new entities that were
|
||||||
|
* created as a result of the paste operation.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE QVector<EntityItemID> pasteEntities(glm::vec3 position);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ClipboardScriptingInterface_h
|
#endif // hifi_ClipboardScriptingInterface_h
|
||||||
|
|
|
@ -56,6 +56,9 @@ QScriptValue RayToEntityIntersectionResultToScriptValue(QScriptEngine* engine, c
|
||||||
void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, RayToEntityIntersectionResult& results);
|
void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, RayToEntityIntersectionResult& results);
|
||||||
|
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @namespace Entities
|
||||||
|
*/
|
||||||
/// handles scripting of Entity commands from JS passed to assigned clients
|
/// handles scripting of Entity commands from JS passed to assigned clients
|
||||||
class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency {
|
class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -87,40 +90,90 @@ public:
|
||||||
ActivityTracking getActivityTracking() const { return _activityTracking; }
|
ActivityTracking getActivityTracking() const { return _activityTracking; }
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
// returns true if the DomainServer will allow this Node/Avatar to make changes
|
/**jsdoc
|
||||||
|
* Returns `true` if the DomainServer will allow this Node/Avatar to make changes
|
||||||
|
*
|
||||||
|
* @function Entities.canAdjustLocks
|
||||||
|
* @return {bool} `true` if the client can adjust locks, `false` if not.
|
||||||
|
*/
|
||||||
Q_INVOKABLE bool canAdjustLocks();
|
Q_INVOKABLE bool canAdjustLocks();
|
||||||
|
|
||||||
// returns true if the DomainServer will allow this Node/Avatar to rez new entities
|
/**jsdoc
|
||||||
|
* @function Entities.canRez
|
||||||
|
* @return {bool} `true` if the DomainServer will allow this Node/Avatar to rez new entities
|
||||||
|
*/
|
||||||
Q_INVOKABLE bool canRez();
|
Q_INVOKABLE bool canRez();
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @function Entities.canRezTmp
|
||||||
|
* @return {bool} `true` if the DomainServer will allow this Node/Avatar to rez new temporary entities
|
||||||
|
*/
|
||||||
Q_INVOKABLE bool canRezTmp();
|
Q_INVOKABLE bool canRezTmp();
|
||||||
|
|
||||||
/// adds a model with the specific properties
|
/**jsdoc
|
||||||
|
* Add a new entity with the specified properties. If `clientOnly` is true, the entity will
|
||||||
|
* not be sent to the server and will only be visible/accessible on the local client.
|
||||||
|
*
|
||||||
|
* @function Entities.addEntity
|
||||||
|
* @param {EntityItemProperties} properties Properties of the entity to create.
|
||||||
|
* @param {bool} [clientOnly=false] Whether the entity should only exist locally or not.
|
||||||
|
* @return {EntityID} The entity ID of the newly created entity. The ID will be a null
|
||||||
|
* UUID (`{00000000-0000-0000-0000-000000000000}`) if the entity could not be created.
|
||||||
|
*/
|
||||||
Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, bool clientOnly = false);
|
Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, bool clientOnly = false);
|
||||||
|
|
||||||
/// temporary method until addEntity can be used from QJSEngine
|
/// temporary method until addEntity can be used from QJSEngine
|
||||||
|
/// Deliberately not adding jsdoc, only used internally.
|
||||||
Q_INVOKABLE QUuid addModelEntity(const QString& name, const QString& modelUrl, const QString& shapeType, bool dynamic,
|
Q_INVOKABLE QUuid addModelEntity(const QString& name, const QString& modelUrl, const QString& shapeType, bool dynamic,
|
||||||
const glm::vec3& position, const glm::vec3& gravity);
|
const glm::vec3& position, const glm::vec3& gravity);
|
||||||
|
|
||||||
/// gets the current model properties for a specific model
|
/**jsdoc
|
||||||
/// this function will not find return results in script engine contexts which don't have access to models
|
* Return the properties for the specified {EntityID}.
|
||||||
|
* not be sent to the server and will only be visible/accessible on the local client.
|
||||||
|
* @param {EntityItemProperties} properties Properties of the entity to create.
|
||||||
|
* @param {EntityPropertyFlags} [desiredProperties=[]] Array containing the names of the properties you
|
||||||
|
* would like to get. If the array is empty, all properties will be returned.
|
||||||
|
* @return {EntityItemProperties} The entity properties for the specified entity.
|
||||||
|
*/
|
||||||
Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID);
|
Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID);
|
||||||
Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties);
|
Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties);
|
||||||
|
|
||||||
/// edits a model updating only the included properties, will return the identified EntityItemID in case of
|
/**jsdoc
|
||||||
/// successful edit, if the input entityID is for an unknown model this function will have no effect
|
* Updates an entity with the specified properties.
|
||||||
|
*
|
||||||
|
* @function Entities.editEntity
|
||||||
|
* @return {EntityID} The EntityID of the entity if the edit was successful, otherwise the null {EntityID}.
|
||||||
|
*/
|
||||||
Q_INVOKABLE QUuid editEntity(QUuid entityID, const EntityItemProperties& properties);
|
Q_INVOKABLE QUuid editEntity(QUuid entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
/// deletes a model
|
/**jsdoc
|
||||||
|
* Deletes an entity.
|
||||||
|
*
|
||||||
|
* @function Entities.deleteEntity
|
||||||
|
* @param {EntityID} entityID The ID of the entity to delete.
|
||||||
|
*/
|
||||||
Q_INVOKABLE void deleteEntity(QUuid entityID);
|
Q_INVOKABLE void deleteEntity(QUuid entityID);
|
||||||
|
|
||||||
/// Allows a script to call a method on an entity's script. The method will execute in the entity script
|
/// Allows a script to call a method on an entity's script. The method will execute in the entity script
|
||||||
/// engine. If the entity does not have an entity script or the method does not exist, this call will have
|
/// engine. If the entity does not have an entity script or the method does not exist, this call will have
|
||||||
/// no effect.
|
/// no effect.
|
||||||
|
/**jsdoc
|
||||||
|
* Call a method on an entity. If it is running an entity script (specified by the `script` property)
|
||||||
|
* and it exposes a property with the specified name `method`, it will be called
|
||||||
|
* using `params` as the list of arguments.
|
||||||
|
*
|
||||||
|
* @function Entities.callEntityMethod
|
||||||
|
* @param {EntityID} entityID The ID of the entity to call the method on.
|
||||||
|
* @param {string} method The name of the method to call.
|
||||||
|
* @param {string[]} params The list of parameters to call the specified method with.
|
||||||
|
*/
|
||||||
Q_INVOKABLE void callEntityMethod(QUuid entityID, const QString& method, const QStringList& params = QStringList());
|
Q_INVOKABLE void callEntityMethod(QUuid entityID, const QString& method, const QStringList& params = QStringList());
|
||||||
|
|
||||||
/// finds the closest model to the center point, within the radius
|
/// finds the closest model to the center point, within the radius
|
||||||
/// will return a EntityItemID.isKnownID = false if no models are in the radius
|
/// will return a EntityItemID.isKnownID = false if no models are in the radius
|
||||||
/// this function will not find any models in script engine contexts which don't have access to models
|
/// this function will not find any models in script engine contexts which don't have access to models
|
||||||
|
/**jsdoc
|
||||||
|
*/
|
||||||
Q_INVOKABLE QUuid findClosestEntity(const glm::vec3& center, float radius) const;
|
Q_INVOKABLE QUuid findClosestEntity(const glm::vec3& center, float radius) const;
|
||||||
|
|
||||||
/// finds models within the search sphere specified by the center point and radius
|
/// finds models within the search sphere specified by the center point and radius
|
||||||
|
|
|
@ -50,7 +50,8 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) {
|
||||||
valid = true;
|
valid = true;
|
||||||
override = false;
|
override = false;
|
||||||
|
|
||||||
QGLWidget* glWidget = new QGLWidget();
|
QGLWidget* glWidget = new QGLWidget(getDefaultGLFormat());
|
||||||
|
|
||||||
valid = glWidget->isValid();
|
valid = glWidget->isValid();
|
||||||
// Inform user if no OpenGL support
|
// Inform user if no OpenGL support
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
|
|
|
@ -307,11 +307,20 @@ void GLBackend::render(const Batch& batch) {
|
||||||
renderPassTransfer(batch);
|
renderPassTransfer(batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
if (_stereo._enable) {
|
||||||
|
glEnable(GL_CLIP_DISTANCE0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(_stereo._enable ? "Render Stereo" : "Render");
|
PROFILE_RANGE(_stereo._enable ? "Render Stereo" : "Render");
|
||||||
renderPassDraw(batch);
|
renderPassDraw(batch);
|
||||||
}
|
}
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
if (_stereo._enable) {
|
||||||
|
glDisable(GL_CLIP_DISTANCE0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// Restore the saved stereo state for the next batch
|
// Restore the saved stereo state for the next batch
|
||||||
_stereo._enable = savedStereo;
|
_stereo._enable = savedStereo;
|
||||||
}
|
}
|
||||||
|
@ -326,13 +335,24 @@ void GLBackend::syncCache() {
|
||||||
glEnable(GL_LINE_SMOOTH);
|
glEnable(GL_LINE_SMOOTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||||
void GLBackend::setupStereoSide(int side) {
|
void GLBackend::setupStereoSide(int side) {
|
||||||
ivec4 vp = _transform._viewport;
|
ivec4 vp = _transform._viewport;
|
||||||
vp.z /= 2;
|
vp.z /= 2;
|
||||||
glViewport(vp.x + side * vp.z, vp.y, vp.z, vp.w);
|
glViewport(vp.x + side * vp.z, vp.y, vp.z, vp.w);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||||
|
glVertexAttribI1i(14, side);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
_transform.bindCurrentCamera(side);
|
_transform.bindCurrentCamera(side);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
|
||||||
void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) {
|
||||||
resetStages();
|
resetStages();
|
||||||
|
@ -385,8 +405,11 @@ void GLBackend::do_popProfileRange(const Batch& batch, size_t paramOffset) {
|
||||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||||
|
|
||||||
// As long as we don;t use several versions of shaders we can avoid this more complex code path
|
// As long as we don;t use several versions of shaders we can avoid this more complex code path
|
||||||
// #define GET_UNIFORM_LOCATION(shaderUniformLoc) _pipeline._programShader->getUniformLocation(shaderUniformLoc, isStereo());
|
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||||
|
#define GET_UNIFORM_LOCATION(shaderUniformLoc) _pipeline._programShader->getUniformLocation(shaderUniformLoc, (GLShader::Version) isStereo())
|
||||||
|
#else
|
||||||
#define GET_UNIFORM_LOCATION(shaderUniformLoc) shaderUniformLoc
|
#define GET_UNIFORM_LOCATION(shaderUniformLoc) shaderUniformLoc
|
||||||
|
#endif
|
||||||
|
|
||||||
void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) {
|
||||||
if (_pipeline._program == 0) {
|
if (_pipeline._program == 0) {
|
||||||
|
|
|
@ -29,6 +29,29 @@
|
||||||
|
|
||||||
#include "GLShared.h"
|
#include "GLShared.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Different versions for the stereo drawcall
|
||||||
|
// Current preferred is "instanced" which draw the shape twice but instanced and rely on clipping plane to draw left/right side only
|
||||||
|
//#define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
|
||||||
|
//#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER
|
||||||
|
#define GPU_STEREO_TECHNIQUE_INSTANCED
|
||||||
|
|
||||||
|
|
||||||
|
// Let these be configured by the one define picked above
|
||||||
|
#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
|
||||||
|
#define GPU_STEREO_DRAWCALL_DOUBLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER
|
||||||
|
#define GPU_STEREO_DRAWCALL_DOUBLED
|
||||||
|
#define GPU_STEREO_CAMERA_BUFFER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_TECHNIQUE_INSTANCED
|
||||||
|
#define GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
#define GPU_STEREO_CAMERA_BUFFER
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace gpu { namespace gl {
|
namespace gpu { namespace gl {
|
||||||
|
|
||||||
class GLBackend : public Backend, public std::enable_shared_from_this<GLBackend> {
|
class GLBackend : public Backend, public std::enable_shared_from_this<GLBackend> {
|
||||||
|
@ -204,7 +227,10 @@ protected:
|
||||||
|
|
||||||
void renderPassTransfer(const Batch& batch);
|
void renderPassTransfer(const Batch& batch);
|
||||||
void renderPassDraw(const Batch& batch);
|
void renderPassDraw(const Batch& batch);
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||||
void setupStereoSide(int side);
|
void setupStereoSide(int side);
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void initInput() final;
|
virtual void initInput() final;
|
||||||
virtual void killInput() final;
|
virtual void killInput() final;
|
||||||
|
@ -262,7 +288,19 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransformStageState {
|
struct TransformStageState {
|
||||||
|
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||||
|
struct Cameras {
|
||||||
|
TransformCamera _cams[2];
|
||||||
|
|
||||||
|
Cameras() {};
|
||||||
|
Cameras(const TransformCamera& cam) { memcpy(_cams, &cam, sizeof(TransformCamera)); };
|
||||||
|
Cameras(const TransformCamera& camL, const TransformCamera& camR) { memcpy(_cams, &camL, sizeof(TransformCamera)); memcpy(_cams + 1, &camR, sizeof(TransformCamera)); };
|
||||||
|
};
|
||||||
|
|
||||||
|
using CameraBufferElement = Cameras;
|
||||||
|
#else
|
||||||
using CameraBufferElement = TransformCamera;
|
using CameraBufferElement = TransformCamera;
|
||||||
|
#endif
|
||||||
using TransformCameras = std::vector<CameraBufferElement>;
|
using TransformCameras = std::vector<CameraBufferElement>;
|
||||||
|
|
||||||
TransformCamera _camera;
|
TransformCamera _camera;
|
||||||
|
|
|
@ -187,7 +187,11 @@ void GLBackend::updateInput() {
|
||||||
glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
||||||
glVertexAttribBinding(slot + locNum, attrib._channel);
|
glVertexAttribBinding(slot + locNum, attrib._channel);
|
||||||
}
|
}
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glVertexBindingDivisor(attrib._channel, attrib._frequency * (isStereo() ? 2 : 1));
|
||||||
|
#else
|
||||||
glVertexBindingDivisor(attrib._channel, attrib._frequency);
|
glVertexBindingDivisor(attrib._channel, attrib._frequency);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
@ -306,7 +310,11 @@ void GLBackend::updateInput() {
|
||||||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride,
|
glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride,
|
||||||
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1));
|
||||||
|
#else
|
||||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support properly the IAttrib version
|
// TODO: Support properly the IAttrib version
|
||||||
|
|
|
@ -48,7 +48,13 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
|
||||||
|
|
||||||
// check the program cache
|
// check the program cache
|
||||||
// pick the program version
|
// pick the program version
|
||||||
|
// check the program cache
|
||||||
|
// pick the program version
|
||||||
|
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||||
|
GLuint glprogram = pipelineObject->_program->getProgram((GLShader::Version) isStereo());
|
||||||
|
#else
|
||||||
GLuint glprogram = pipelineObject->_program->getProgram();
|
GLuint glprogram = pipelineObject->_program->getProgram();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (_pipeline._program != glprogram) {
|
if (_pipeline._program != glprogram) {
|
||||||
_pipeline._program = glprogram;
|
_pipeline._program = glprogram;
|
||||||
|
|
|
@ -31,10 +31,25 @@ void GLBackend::do_setProjectionTransform(const Batch& batch, size_t paramOffset
|
||||||
void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) {
|
||||||
memcpy(&_transform._viewport, batch.readData(batch._params[paramOffset]._uint), sizeof(Vec4i));
|
memcpy(&_transform._viewport, batch.readData(batch._params[paramOffset]._uint), sizeof(Vec4i));
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
{
|
||||||
|
ivec4& vp = _transform._viewport;
|
||||||
|
glViewport(vp.x, vp.y, vp.z, vp.w);
|
||||||
|
|
||||||
|
// Where we assign the GL viewport
|
||||||
|
if (_stereo._enable) {
|
||||||
|
vp.z /= 2;
|
||||||
|
if (_stereo._pass) {
|
||||||
|
vp.x += vp.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!_inRenderTransferPass && !isStereo()) {
|
if (!_inRenderTransferPass && !isStereo()) {
|
||||||
ivec4& vp = _transform._viewport;
|
ivec4& vp = _transform._viewport;
|
||||||
glViewport(vp.x, vp.y, vp.z, vp.w);
|
glViewport(vp.x, vp.y, vp.z, vp.w);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// The Viewport is tagged invalid because the CameraTransformUBO is not up to date and will need update on next drawcall
|
// The Viewport is tagged invalid because the CameraTransformUBO is not up to date and will need update on next drawcall
|
||||||
_transform._invalidViewport = true;
|
_transform._invalidViewport = true;
|
||||||
|
@ -100,13 +115,21 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
|
||||||
if (_invalidView || _invalidProj || _invalidViewport) {
|
if (_invalidView || _invalidProj || _invalidViewport) {
|
||||||
size_t offset = _cameraUboSize * _cameras.size();
|
size_t offset = _cameraUboSize * _cameras.size();
|
||||||
_cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset));
|
_cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset));
|
||||||
if (stereo._enable) {
|
|
||||||
_cameras.push_back((_camera.getEyeCamera(0, stereo, _view)));
|
|
||||||
_cameras.push_back((_camera.getEyeCamera(1, stereo, _view)));
|
|
||||||
} else {
|
|
||||||
_cameras.push_back((_camera.recomputeDerived(_view)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (stereo._enable) {
|
||||||
|
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||||
|
_cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view)));
|
||||||
|
#else
|
||||||
|
_cameras.push_back((_camera.getEyeCamera(0, stereo, _view)));
|
||||||
|
_cameras.push_back((_camera.getEyeCamera(1, stereo, _view)));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||||
|
_cameras.push_back(CameraBufferElement(_camera.recomputeDerived(_view)));
|
||||||
|
#else
|
||||||
|
_cameras.push_back((_camera.recomputeDerived(_view)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flags are clean
|
// Flags are clean
|
||||||
|
@ -122,9 +145,13 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset != INVALID_OFFSET) {
|
if (offset != INVALID_OFFSET) {
|
||||||
|
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||||
|
bindCurrentCamera(0);
|
||||||
|
#else
|
||||||
if (!stereo._enable) {
|
if (!stereo._enable) {
|
||||||
bindCurrentCamera(0);
|
bindCurrentCamera(0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
@ -148,7 +175,11 @@ void GLBackend::updateTransform(const Batch& batch) {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer);
|
||||||
glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0,
|
glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0,
|
||||||
_transform._drawCallInfoOffsets[batch._currentNamedCall]);
|
_transform._drawCallInfoOffsets[batch._currentNamedCall]);
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1));
|
||||||
|
#else
|
||||||
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1);
|
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
|
@ -54,9 +54,24 @@ static const std::array<std::string, NUM_SHADER_DOMAINS> DOMAIN_DEFINES { {
|
||||||
"#define GPU_GEOMETRY_SHADER",
|
"#define GPU_GEOMETRY_SHADER",
|
||||||
} };
|
} };
|
||||||
|
|
||||||
|
// Stereo specific defines
|
||||||
|
static const std::string stereoVersion {
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
"#define GPU_TRANSFORM_IS_STEREO\n#define GPU_TRANSFORM_STEREO_CAMERA\n#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN"
|
||||||
|
#endif
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_DOUBLED
|
||||||
|
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||||
|
"#define GPU_TRANSFORM_IS_STEREO\n#define GPU_TRANSFORM_STEREO_CAMERA\n#define GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED"
|
||||||
|
#else
|
||||||
|
"#define GPU_TRANSFORM_IS_STEREO"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
// Versions specific of the shader
|
// Versions specific of the shader
|
||||||
static const std::array<std::string, GLShader::NumVersions> VERSION_DEFINES { {
|
static const std::array<std::string, GLShader::NumVersions> VERSION_DEFINES { {
|
||||||
""
|
"",
|
||||||
|
stereoVersion
|
||||||
} };
|
} };
|
||||||
|
|
||||||
GLShader* compileBackendShader(GLBackend& backend, const Shader& shader) {
|
GLShader* compileBackendShader(GLBackend& backend, const Shader& shader) {
|
||||||
|
@ -181,7 +196,8 @@ bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::Bin
|
||||||
// Define the public slots only from the default version
|
// Define the public slots only from the default version
|
||||||
if (version == 0) {
|
if (version == 0) {
|
||||||
shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs);
|
shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs);
|
||||||
} else {
|
} // else
|
||||||
|
{
|
||||||
GLShader::UniformMapping mapping;
|
GLShader::UniformMapping mapping;
|
||||||
for (auto srcUniform : shader.getUniforms()) {
|
for (auto srcUniform : shader.getUniforms()) {
|
||||||
mapping[srcUniform._location] = uniforms.findLocation(srcUniform._name);
|
mapping[srcUniform._location] = uniforms.findLocation(srcUniform._name);
|
||||||
|
|
|
@ -19,6 +19,8 @@ public:
|
||||||
|
|
||||||
enum Version {
|
enum Version {
|
||||||
Mono = 0,
|
Mono = 0,
|
||||||
|
Stereo,
|
||||||
|
|
||||||
NumVersions
|
NumVersions
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,8 +42,8 @@ public:
|
||||||
|
|
||||||
GLint getUniformLocation(GLint srcLoc, Version version = Mono) {
|
GLint getUniformLocation(GLint srcLoc, Version version = Mono) {
|
||||||
// THIS will be used in the future PR as we grow the number of versions
|
// THIS will be used in the future PR as we grow the number of versions
|
||||||
// return _uniformMappings[version][srcLoc];
|
return _uniformMappings[version][srcLoc];
|
||||||
return srcLoc;
|
// return srcLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::weak_ptr<GLBackend> _backend;
|
const std::weak_ptr<GLBackend> _backend;
|
||||||
|
|
|
@ -25,11 +25,14 @@ void GL41Backend::do_draw(const Batch& batch, size_t paramOffset) {
|
||||||
uint32 startVertex = batch._params[paramOffset + 0]._uint;
|
uint32 startVertex = batch._params[paramOffset + 0]._uint;
|
||||||
|
|
||||||
if (isStereo()) {
|
if (isStereo()) {
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
|
||||||
|
#else
|
||||||
setupStereoSide(0);
|
setupStereoSide(0);
|
||||||
glDrawArrays(mode, startVertex, numVertices);
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
setupStereoSide(1);
|
setupStereoSide(1);
|
||||||
glDrawArrays(mode, startVertex, numVertices);
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
#endif
|
||||||
_stats._DSNumTriangles += 2 * numVertices / 3;
|
_stats._DSNumTriangles += 2 * numVertices / 3;
|
||||||
_stats._DSNumDrawcalls += 2;
|
_stats._DSNumDrawcalls += 2;
|
||||||
|
|
||||||
|
@ -55,11 +58,14 @@ void GL41Backend::do_drawIndexed(const Batch& batch, size_t paramOffset) {
|
||||||
GLvoid* indexBufferByteOffset = reinterpret_cast<GLvoid*>(startIndex * typeByteSize + _input._indexBufferOffset);
|
GLvoid* indexBufferByteOffset = reinterpret_cast<GLvoid*>(startIndex * typeByteSize + _input._indexBufferOffset);
|
||||||
|
|
||||||
if (isStereo()) {
|
if (isStereo()) {
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2);
|
||||||
|
#else
|
||||||
setupStereoSide(0);
|
setupStereoSide(0);
|
||||||
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||||
setupStereoSide(1);
|
setupStereoSide(1);
|
||||||
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||||
|
#endif
|
||||||
_stats._DSNumTriangles += 2 * numIndices / 3;
|
_stats._DSNumTriangles += 2 * numIndices / 3;
|
||||||
_stats._DSNumDrawcalls += 2;
|
_stats._DSNumDrawcalls += 2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,11 +89,14 @@ void GL41Backend::do_drawInstanced(const Batch& batch, size_t paramOffset) {
|
||||||
if (isStereo()) {
|
if (isStereo()) {
|
||||||
GLint trueNumInstances = 2 * numInstances;
|
GLint trueNumInstances = 2 * numInstances;
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, trueNumInstances);
|
||||||
|
#else
|
||||||
setupStereoSide(0);
|
setupStereoSide(0);
|
||||||
glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances);
|
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||||
setupStereoSide(1);
|
setupStereoSide(1);
|
||||||
glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances);
|
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||||
|
#endif
|
||||||
_stats._DSNumTriangles += (trueNumInstances * numVertices) / 3;
|
_stats._DSNumTriangles += (trueNumInstances * numVertices) / 3;
|
||||||
_stats._DSNumDrawcalls += trueNumInstances;
|
_stats._DSNumDrawcalls += trueNumInstances;
|
||||||
} else {
|
} else {
|
||||||
|
@ -124,10 +133,14 @@ void GL41Backend::do_drawIndexedInstanced(const Batch& batch, size_t paramOffset
|
||||||
if (isStereo()) {
|
if (isStereo()) {
|
||||||
GLint trueNumInstances = 2 * numInstances;
|
GLint trueNumInstances = 2 * numInstances;
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance);
|
||||||
|
#else
|
||||||
setupStereoSide(0);
|
setupStereoSide(0);
|
||||||
glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||||
setupStereoSide(1);
|
setupStereoSide(1);
|
||||||
glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||||
|
#endif
|
||||||
|
|
||||||
_stats._DSNumTriangles += (trueNumInstances * numIndices) / 3;
|
_stats._DSNumTriangles += (trueNumInstances * numIndices) / 3;
|
||||||
_stats._DSNumDrawcalls += trueNumInstances;
|
_stats._DSNumDrawcalls += trueNumInstances;
|
||||||
|
|
|
@ -25,10 +25,14 @@ void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) {
|
||||||
uint32 startVertex = batch._params[paramOffset + 0]._uint;
|
uint32 startVertex = batch._params[paramOffset + 0]._uint;
|
||||||
|
|
||||||
if (isStereo()) {
|
if (isStereo()) {
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
|
||||||
|
#else
|
||||||
setupStereoSide(0);
|
setupStereoSide(0);
|
||||||
glDrawArrays(mode, startVertex, numVertices);
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
setupStereoSide(1);
|
setupStereoSide(1);
|
||||||
glDrawArrays(mode, startVertex, numVertices);
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
#endif
|
||||||
|
|
||||||
_stats._DSNumTriangles += 2 * numVertices / 3;
|
_stats._DSNumTriangles += 2 * numVertices / 3;
|
||||||
_stats._DSNumDrawcalls += 2;
|
_stats._DSNumDrawcalls += 2;
|
||||||
|
@ -55,11 +59,14 @@ void GL45Backend::do_drawIndexed(const Batch& batch, size_t paramOffset) {
|
||||||
GLvoid* indexBufferByteOffset = reinterpret_cast<GLvoid*>(startIndex * typeByteSize + _input._indexBufferOffset);
|
GLvoid* indexBufferByteOffset = reinterpret_cast<GLvoid*>(startIndex * typeByteSize + _input._indexBufferOffset);
|
||||||
|
|
||||||
if (isStereo()) {
|
if (isStereo()) {
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2);
|
||||||
|
#else
|
||||||
setupStereoSide(0);
|
setupStereoSide(0);
|
||||||
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||||
setupStereoSide(1);
|
setupStereoSide(1);
|
||||||
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||||
|
#endif
|
||||||
_stats._DSNumTriangles += 2 * numIndices / 3;
|
_stats._DSNumTriangles += 2 * numIndices / 3;
|
||||||
_stats._DSNumDrawcalls += 2;
|
_stats._DSNumDrawcalls += 2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,10 +90,14 @@ void GL45Backend::do_drawInstanced(const Batch& batch, size_t paramOffset) {
|
||||||
if (isStereo()) {
|
if (isStereo()) {
|
||||||
GLint trueNumInstances = 2 * numInstances;
|
GLint trueNumInstances = 2 * numInstances;
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, trueNumInstances);
|
||||||
|
#else
|
||||||
setupStereoSide(0);
|
setupStereoSide(0);
|
||||||
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||||
setupStereoSide(1);
|
setupStereoSide(1);
|
||||||
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||||
|
#endif
|
||||||
|
|
||||||
_stats._DSNumTriangles += (trueNumInstances * numVertices) / 3;
|
_stats._DSNumTriangles += (trueNumInstances * numVertices) / 3;
|
||||||
_stats._DSNumDrawcalls += trueNumInstances;
|
_stats._DSNumDrawcalls += trueNumInstances;
|
||||||
|
@ -112,10 +123,15 @@ void GL45Backend::do_drawIndexedInstanced(const Batch& batch, size_t paramOffset
|
||||||
|
|
||||||
if (isStereo()) {
|
if (isStereo()) {
|
||||||
GLint trueNumInstances = 2 * numInstances;
|
GLint trueNumInstances = 2 * numInstances;
|
||||||
|
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance);
|
||||||
|
#else
|
||||||
setupStereoSide(0);
|
setupStereoSide(0);
|
||||||
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||||
setupStereoSide(1);
|
setupStereoSide(1);
|
||||||
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||||
|
#endif
|
||||||
_stats._DSNumTriangles += (trueNumInstances * numIndices) / 3;
|
_stats._DSNumTriangles += (trueNumInstances * numIndices) / 3;
|
||||||
_stats._DSNumDrawcalls += trueNumInstances;
|
_stats._DSNumDrawcalls += trueNumInstances;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -22,29 +22,84 @@ struct TransformCamera {
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std140) uniform transformCameraBuffer {
|
layout(std140) uniform transformCameraBuffer {
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||||
|
TransformCamera _camera[2];
|
||||||
|
#else
|
||||||
TransformCamera _camera;
|
TransformCamera _camera;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
TransformCamera _camera;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef GPU_VERTEX_SHADER
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED
|
||||||
|
layout(location=14) in int _inStereoSide;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
flat out int _stereoSide;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GPU_PIXEL_SHADER
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||||
|
flat in int _stereoSide;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
TransformCamera getTransformCamera() {
|
TransformCamera getTransformCamera() {
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||||
|
#ifdef GPU_VERTEX_SHADER
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED
|
||||||
|
_stereoSide = _inStereoSide;
|
||||||
|
#endif
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED
|
||||||
|
_stereoSide = gl_InstanceID % 2;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return _camera[_stereoSide];
|
||||||
|
#else
|
||||||
|
return _camera;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
return _camera;
|
return _camera;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 getEyeWorldPos() {
|
vec3 getEyeWorldPos() {
|
||||||
return _camera._viewInverse[3].xyz;
|
return getTransformCamera()._viewInverse[3].xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool cam_isStereo() {
|
bool cam_isStereo() {
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
return getTransformCamera()._stereoInfo.x > 0.0;
|
||||||
|
#else
|
||||||
return _camera._stereoInfo.x > 0.0;
|
return _camera._stereoInfo.x > 0.0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float cam_getStereoSide() {
|
float cam_getStereoSide() {
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||||
|
return getTransformCamera()._stereoInfo.y;
|
||||||
|
#else
|
||||||
return _camera._stereoInfo.y;
|
return _camera._stereoInfo.y;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
return _camera._stereoInfo.y;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
||||||
<@func declareStandardObjectTransform()@>
|
<@func declareStandardObjectTransform()@>
|
||||||
struct TransformObject {
|
struct TransformObject {
|
||||||
mat4 _model;
|
mat4 _model;
|
||||||
|
@ -92,6 +147,25 @@ TransformObject getTransformObject() {
|
||||||
<$viewport$> = <$cameraTransform$>._viewport;
|
<$viewport$> = <$cameraTransform$>._viewport;
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
<@func transformStereoClipsSpace(cameraTransform, clipPos)@>
|
||||||
|
{
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN
|
||||||
|
vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));
|
||||||
|
vec2 eyeOffsetScale = vec2(-0.5, +0.5);
|
||||||
|
uint eyeIndex = _stereoSide;
|
||||||
|
gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]);
|
||||||
|
float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w;
|
||||||
|
<$clipPos$>.x = newClipPosX;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
||||||
<@func transformModelToEyeWorldAlignedPos(cameraTransform, objectTransform, modelPos, eyeWorldAlignedPos)@>
|
<@func transformModelToEyeWorldAlignedPos(cameraTransform, objectTransform, modelPos, eyeWorldAlignedPos)@>
|
||||||
<!// Bring the model pos in the world aligned space centered on the eye axis !>
|
<!// Bring the model pos in the world aligned space centered on the eye axis !>
|
||||||
{ // _transformModelToEyeWorldAlignedPos
|
{ // _transformModelToEyeWorldAlignedPos
|
||||||
|
@ -108,6 +182,8 @@ TransformObject getTransformObject() {
|
||||||
<$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$>
|
<$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$>
|
||||||
|
|
||||||
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
||||||
|
|
||||||
|
<$transformStereoClipsSpace($cameraTransform$, $clipPos$)$>
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
@ -117,6 +193,8 @@ TransformObject getTransformObject() {
|
||||||
<$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$>
|
<$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$>
|
||||||
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
||||||
<$eyePos$> = vec4((<$cameraTransform$>._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);
|
<$eyePos$> = vec4((<$cameraTransform$>._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);
|
||||||
|
|
||||||
|
<$transformStereoClipsSpace($cameraTransform$, $clipPos$)$>
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
@ -143,11 +221,10 @@ TransformObject getTransformObject() {
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
<@func transformModelToWorldDir(cameraTransform, objectTransform, modelDir, worldDir)@>
|
<@func transformModelToWorldDir(cameraTransform, objectTransform, modelDir, worldDir)@>
|
||||||
{ // transformModelToEyeDir
|
{ // transformModelToEyeDir
|
||||||
vec3 mr0 = <$objectTransform$>._modelInverse[0].xyz;
|
vec3 mr0 = <$objectTransform$>._modelInverse[0].xyz;
|
||||||
vec3 mr1 = <$objectTransform$>._modelInverse[1].xyz;
|
vec3 mr1 = <$objectTransform$>._modelInverse[1].xyz;
|
||||||
vec3 mr2 = <$objectTransform$>._modelInverse[2].xyz;
|
vec3 mr2 = <$objectTransform$>._modelInverse[2].xyz;
|
||||||
|
|
||||||
<$worldDir$> = vec3(dot(mr0, <$modelDir$>), dot(mr1, <$modelDir$>), dot(mr2, <$modelDir$>));
|
<$worldDir$> = vec3(dot(mr0, <$modelDir$>), dot(mr1, <$modelDir$>), dot(mr2, <$modelDir$>));
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
@ -181,6 +258,8 @@ TransformObject getTransformObject() {
|
||||||
<@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@>
|
<@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@>
|
||||||
{ // transformEyeToClipPos
|
{ // transformEyeToClipPos
|
||||||
<$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0);
|
<$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0);
|
||||||
|
|
||||||
|
<$transformStereoClipsSpace($cameraTransform$, $clipPos$)$>
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
|
@ -36,4 +36,6 @@ void main(void) {
|
||||||
|
|
||||||
// Position is supposed to come in clip space
|
// Position is supposed to come in clip space
|
||||||
gl_Position = vec4(inPosition.xy, 0.0, 1.0);
|
gl_Position = vec4(inPosition.xy, 0.0, 1.0);
|
||||||
|
|
||||||
|
<$transformStereoClipsSpace(cam, gl_Position)$>
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ out vec4 _texCoord0;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
if (sphereParam.w != 0.0) {
|
if (sphereParam.w != 0.0) {
|
||||||
|
|
||||||
// standard transform
|
// standard transform
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
TransformObject obj = getTransformObject();
|
TransformObject obj = getTransformObject();
|
||||||
|
@ -33,9 +33,14 @@ void main(void) {
|
||||||
vec4 projected = gl_Position / gl_Position.w;
|
vec4 projected = gl_Position / gl_Position.w;
|
||||||
projected.xy = (projected.xy + 1.0) * 0.5;
|
projected.xy = (projected.xy + 1.0) * 0.5;
|
||||||
|
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN
|
||||||
|
#else
|
||||||
if (cam_isStereo()) {
|
if (cam_isStereo()) {
|
||||||
projected.x = 0.5 * (projected.x + cam_getStereoSide());
|
projected.x = 0.5 * (projected.x + cam_getStereoSide());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
_texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w;
|
_texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w;
|
||||||
} else {
|
} else {
|
||||||
const float depth = -1.0; //Draw at near plane
|
const float depth = -1.0; //Draw at near plane
|
||||||
|
@ -47,11 +52,27 @@ void main(void) {
|
||||||
);
|
);
|
||||||
vec4 pos = UNIT_QUAD[gl_VertexID];
|
vec4 pos = UNIT_QUAD[gl_VertexID];
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN
|
||||||
|
TransformCamera cam = getTransformCamera();
|
||||||
|
<$transformStereoClipsSpace(cam, pos)$>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
_texCoord0 = vec4((pos.xy + 1.0) * 0.5, 0.0, 1.0);
|
_texCoord0 = vec4((pos.xy + 1.0) * 0.5, 0.0, 1.0);
|
||||||
|
|
||||||
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN
|
||||||
|
#else
|
||||||
if (cam_isStereo()) {
|
if (cam_isStereo()) {
|
||||||
_texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide());
|
_texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
gl_Position = pos;
|
gl_Position = pos;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,13 @@ void main(void) {
|
||||||
vec4 projected = gl_Position / gl_Position.w;
|
vec4 projected = gl_Position / gl_Position.w;
|
||||||
projected.xy = (projected.xy + 1.0) * 0.5;
|
projected.xy = (projected.xy + 1.0) * 0.5;
|
||||||
|
|
||||||
if (cam_isStereo()) {
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
projected.x = 0.5 * (projected.x + cam_getStereoSide());
|
#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN
|
||||||
}
|
#else
|
||||||
|
if (cam_isStereo()) {
|
||||||
|
projected.x = 0.5 * (projected.x + cam_getStereoSide());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
_texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w;
|
_texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1188,20 +1188,15 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
||||||
thisURL = resolvePath(file);
|
thisURL = resolvePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_includedURLs.contains(thisURL)) {
|
if (!isStandardLibrary && !currentSandboxURL.isEmpty() && (thisURL.scheme() == "file") &&
|
||||||
if (!isStandardLibrary && !currentSandboxURL.isEmpty() && (thisURL.scheme() == "file") &&
|
(currentSandboxURL.scheme() != "file" ||
|
||||||
(currentSandboxURL.scheme() != "file" ||
|
!thisURL.toString(strippingFlags).startsWith(currentSandboxURL.toString(strippingFlags), getSensitivity()))) {
|
||||||
!thisURL.toString(strippingFlags).startsWith(currentSandboxURL.toString(strippingFlags), getSensitivity()))) {
|
qCWarning(scriptengine) << "Script.include() ignoring file path"
|
||||||
qCWarning(scriptengine) << "Script.include() ignoring file path"
|
<< thisURL << "outside of original entity script" << currentSandboxURL;
|
||||||
<< thisURL << "outside of original entity script" << currentSandboxURL;
|
|
||||||
} else {
|
|
||||||
// We could also check here for CORS, but we don't yet.
|
|
||||||
// It turns out that QUrl.resolve will not change hosts and copy authority, so we don't need to check that here.
|
|
||||||
urls.append(thisURL);
|
|
||||||
_includedURLs << thisURL;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
qCDebug(scriptengine) << "Script.include() ignoring previously included url:" << thisURL;
|
// We could also check here for CORS, but we don't yet.
|
||||||
|
// It turns out that QUrl.resolve will not change hosts and copy authority, so we don't need to check that here.
|
||||||
|
urls.append(thisURL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1221,13 +1216,20 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
||||||
if (contents.isNull()) {
|
if (contents.isNull()) {
|
||||||
qCDebug(scriptengine) << "Error loading file: " << url << "line:" << __LINE__;
|
qCDebug(scriptengine) << "Error loading file: " << url << "line:" << __LINE__;
|
||||||
} else {
|
} else {
|
||||||
// Set the parent url so that path resolution will be relative
|
std::lock_guard<std::recursive_mutex> lock(_lock);
|
||||||
// to this script's url during its initial evaluation
|
if (!_includedURLs.contains(url)) {
|
||||||
_parentURL = url.toString();
|
_includedURLs << url;
|
||||||
auto operation = [&]() {
|
// Set the parent url so that path resolution will be relative
|
||||||
evaluate(contents, url.toString());
|
// to this script's url during its initial evaluation
|
||||||
};
|
_parentURL = url.toString();
|
||||||
doWithEnvironment(capturedEntityIdentifier, capturedSandboxURL, operation);
|
auto operation = [&]() {
|
||||||
|
evaluate(contents, url.toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
doWithEnvironment(capturedEntityIdentifier, capturedSandboxURL, operation);
|
||||||
|
} else {
|
||||||
|
qCDebug(scriptengine) << "Script.include() skipping evaluation of previously included url:" << url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_parentURL = parentURL;
|
_parentURL = parentURL;
|
||||||
|
|
|
@ -245,6 +245,7 @@ protected:
|
||||||
|
|
||||||
std::function<bool()> _emitScriptUpdates{ [](){ return true; } };
|
std::function<bool()> _emitScriptUpdates{ [](){ return true; } };
|
||||||
|
|
||||||
|
std::recursive_mutex _lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ScriptEngine_h
|
#endif // hifi_ScriptEngine_h
|
||||||
|
|
|
@ -401,9 +401,13 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
memset(&timing, 0, sizeof(timing));
|
memset(&timing, 0, sizeof(timing));
|
||||||
timing.m_nSize = sizeof(vr::Compositor_FrameTiming);
|
timing.m_nSize = sizeof(vr::Compositor_FrameTiming);
|
||||||
vr::VRCompositor()->GetFrameTiming(&timing);
|
vr::VRCompositor()->GetFrameTiming(&timing);
|
||||||
_asyncReprojectionActive = timing.m_nReprojectionFlags & VRCompositor_ReprojectionAsync;
|
auto usingOpenVRForOculus = oculusViaOpenVR();
|
||||||
|
_asyncReprojectionActive = (timing.m_nReprojectionFlags & VRCompositor_ReprojectionAsync) || usingOpenVRForOculus;
|
||||||
|
|
||||||
_threadedSubmit = !_asyncReprojectionActive;
|
_threadedSubmit = !_asyncReprojectionActive;
|
||||||
|
if (usingOpenVRForOculus) {
|
||||||
|
qDebug() << "Oculus active via OpenVR: " << usingOpenVRForOculus;
|
||||||
|
}
|
||||||
qDebug() << "OpenVR Async Reprojection active: " << _asyncReprojectionActive;
|
qDebug() << "OpenVR Async Reprojection active: " << _asyncReprojectionActive;
|
||||||
qDebug() << "OpenVR Threaded submit enabled: " << _threadedSubmit;
|
qDebug() << "OpenVR Threaded submit enabled: " << _threadedSubmit;
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,12 @@ bool isOculusPresent() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool oculusViaOpenVR() {
|
||||||
|
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR");
|
||||||
|
static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||||
|
return enableDebugOpenVR && isOculusPresent() && vr::VR_IsHmdPresent();
|
||||||
|
}
|
||||||
|
|
||||||
bool openVrSupported() {
|
bool openVrSupported() {
|
||||||
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR");
|
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR");
|
||||||
static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <controllers/Forward.h>
|
#include <controllers/Forward.h>
|
||||||
#include <plugins/Forward.h>
|
#include <plugins/Forward.h>
|
||||||
|
|
||||||
|
bool oculusViaOpenVR(); // is the user using Oculus via OpenVR
|
||||||
bool openVrSupported();
|
bool openVrSupported();
|
||||||
|
|
||||||
vr::IVRSystem* acquireOpenVrSystem();
|
vr::IVRSystem* acquireOpenVrSystem();
|
||||||
|
|
|
@ -19,6 +19,7 @@ exports.handlers = {
|
||||||
'../../libraries/script-engine/src',
|
'../../libraries/script-engine/src',
|
||||||
'../../libraries/networking/src',
|
'../../libraries/networking/src',
|
||||||
'../../libraries/animation/src',
|
'../../libraries/animation/src',
|
||||||
|
'../../libraries/entities/src',
|
||||||
];
|
];
|
||||||
var exts = ['.h', '.cpp'];
|
var exts = ['.h', '.cpp'];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue