diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 90c5d32449..ffd7cc703b 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -386,8 +386,11 @@ bool AudioMixer::prepareMixForListeningNode(Node* node) { // loop through all other nodes that have sufficient audio to mix DependencyManager::get()->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 - if (otherNode->getLinkedData() && !node->isIgnoringNodeWithID(otherNode->getUUID())) { + // make sure that we have audio data for this other node + // 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(); // enumerate the ARBs attached to the otherNode and add all that should be added to mix diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 041449dc57..2c9fadc7b1 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -230,9 +230,11 @@ void AvatarMixer::broadcastAvatarData() { [&](const SharedNodePointer& otherNode)->bool { // 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 + // or that has ignored the viewing node if (!otherNode->getLinkedData() || otherNode->getUUID() == node->getUUID() - || node->isIgnoringNodeWithID(otherNode->getUUID())) { + || node->isIgnoringNodeWithID(otherNode->getUUID()) + || otherNode->isIgnoringNodeWithID(node->getUUID())) { return false; } else { return true; diff --git a/interface/resources/images/steam-min-spec-failed.png b/interface/resources/images/steam-min-spec-failed.png index 99abac9e1c..0061167a92 100644 Binary files a/interface/resources/images/steam-min-spec-failed.png and b/interface/resources/images/steam-min-spec-failed.png differ diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index 428bf86c6f..f24a9bb932 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -50,7 +50,8 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) { valid = true; override = false; - QGLWidget* glWidget = new QGLWidget(); + QGLWidget* glWidget = new QGLWidget(getDefaultGLFormat()); + valid = glWidget->isValid(); // Inform user if no OpenGL support if (!valid) { diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 3513d7a05b..719989a07a 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -307,11 +307,20 @@ void GLBackend::render(const Batch& batch) { renderPassTransfer(batch); } +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + if (_stereo._enable) { + glEnable(GL_CLIP_DISTANCE0); + } +#endif { PROFILE_RANGE(_stereo._enable ? "Render Stereo" : "Render"); renderPassDraw(batch); } - +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + if (_stereo._enable) { + glDisable(GL_CLIP_DISTANCE0); + } +#endif // Restore the saved stereo state for the next batch _stereo._enable = savedStereo; } @@ -326,13 +335,24 @@ void GLBackend::syncCache() { glEnable(GL_LINE_SMOOTH); } +#ifdef GPU_STEREO_DRAWCALL_DOUBLED void GLBackend::setupStereoSide(int side) { ivec4 vp = _transform._viewport; vp.z /= 2; 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); +#endif + } +#else +#endif void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) { 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 // 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 +#endif void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) { if (_pipeline._program == 0) { diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 417b090d31..42557ddd97 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -29,6 +29,29 @@ #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 { class GLBackend : public Backend, public std::enable_shared_from_this { @@ -204,7 +227,10 @@ protected: void renderPassTransfer(const Batch& batch); void renderPassDraw(const Batch& batch); + +#ifdef GPU_STEREO_DRAWCALL_DOUBLED void setupStereoSide(int side); +#endif virtual void initInput() final; virtual void killInput() final; @@ -262,7 +288,19 @@ protected: }; 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; +#endif using TransformCameras = std::vector; TransformCamera _camera; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendInput.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendInput.cpp index 9256a42b80..618988a217 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendInput.cpp @@ -187,7 +187,11 @@ void GLBackend::updateInput() { glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize); glVertexAttribBinding(slot + locNum, attrib._channel); } +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glVertexBindingDivisor(attrib._channel, attrib._frequency * (isStereo() ? 2 : 1)); +#else glVertexBindingDivisor(attrib._channel, attrib._frequency); +#endif } (void)CHECK_GL_ERROR(); } @@ -306,7 +310,11 @@ void GLBackend::updateInput() { for (size_t locNum = 0; locNum < locationCount; ++locNum) { glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride, reinterpret_cast(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); +#endif } // TODO: Support properly the IAttrib version diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp index ed0b9607e6..81d38c3339 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp @@ -48,7 +48,13 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) { // check the program cache // 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(); +#endif if (_pipeline._program != glprogram) { _pipeline._program = glprogram; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp index 7f821078cd..eb53f5d45b 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp @@ -31,10 +31,25 @@ void GLBackend::do_setProjectionTransform(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)); +#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()) { ivec4& vp = _transform._viewport; 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 _transform._invalidViewport = true; @@ -100,13 +115,21 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo if (_invalidView || _invalidProj || _invalidViewport) { size_t offset = _cameraUboSize * _cameras.size(); _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 @@ -122,9 +145,13 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta } if (offset != INVALID_OFFSET) { +#ifdef GPU_STEREO_CAMERA_BUFFER + bindCurrentCamera(0); +#else if (!stereo._enable) { bindCurrentCamera(0); } +#endif } (void)CHECK_GL_ERROR(); } @@ -148,7 +175,11 @@ void GLBackend::updateTransform(const Batch& batch) { glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer); glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0, _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); +#endif } (void)CHECK_GL_ERROR(); diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp index f8d493c25b..23439a640a 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp @@ -54,9 +54,24 @@ static const std::array DOMAIN_DEFINES { { "#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 static const std::array VERSION_DEFINES { { - "" + "", + stereoVersion } }; 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 if (version == 0) { shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs); - } else { + } // else + { GLShader::UniformMapping mapping; for (auto srcUniform : shader.getUniforms()) { mapping[srcUniform._location] = uniforms.findLocation(srcUniform._name); diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.h b/libraries/gpu-gl/src/gpu/gl/GLShader.h index e75e96cf16..40dd0b7be9 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.h @@ -19,6 +19,8 @@ public: enum Version { Mono = 0, + Stereo, + NumVersions }; @@ -40,8 +42,8 @@ public: GLint getUniformLocation(GLint srcLoc, Version version = Mono) { // THIS will be used in the future PR as we grow the number of versions - // return _uniformMappings[version][srcLoc]; - return srcLoc; + return _uniformMappings[version][srcLoc]; + // return srcLoc; } const std::weak_ptr _backend; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp index 6c2b2f434e..a87d0ad6b8 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp @@ -25,11 +25,14 @@ void GL41Backend::do_draw(const Batch& batch, size_t paramOffset) { uint32 startVertex = batch._params[paramOffset + 0]._uint; if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, 2); +#else setupStereoSide(0); glDrawArrays(mode, startVertex, numVertices); setupStereoSide(1); glDrawArrays(mode, startVertex, numVertices); - +#endif _stats._DSNumTriangles += 2 * numVertices / 3; _stats._DSNumDrawcalls += 2; @@ -55,11 +58,14 @@ void GL41Backend::do_drawIndexed(const Batch& batch, size_t paramOffset) { GLvoid* indexBufferByteOffset = reinterpret_cast(startIndex * typeByteSize + _input._indexBufferOffset); if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2); +#else setupStereoSide(0); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); setupStereoSide(1); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); - +#endif _stats._DSNumTriangles += 2 * numIndices / 3; _stats._DSNumDrawcalls += 2; } else { @@ -83,11 +89,14 @@ void GL41Backend::do_drawInstanced(const Batch& batch, size_t paramOffset) { if (isStereo()) { GLint trueNumInstances = 2 * numInstances; +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, trueNumInstances); +#else setupStereoSide(0); - glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); + glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); setupStereoSide(1); - glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); - + glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); +#endif _stats._DSNumTriangles += (trueNumInstances * numVertices) / 3; _stats._DSNumDrawcalls += trueNumInstances; } else { @@ -124,10 +133,14 @@ void GL41Backend::do_drawIndexedInstanced(const Batch& batch, size_t paramOffset if (isStereo()) { GLint trueNumInstances = 2 * numInstances; +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance); +#else setupStereoSide(0); glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); setupStereoSide(1); glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); +#endif _stats._DSNumTriangles += (trueNumInstances * numIndices) / 3; _stats._DSNumDrawcalls += trueNumInstances; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp index bae6326e8f..d7dde8b7d6 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp @@ -25,10 +25,14 @@ void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) { uint32 startVertex = batch._params[paramOffset + 0]._uint; if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, 2); +#else setupStereoSide(0); glDrawArrays(mode, startVertex, numVertices); setupStereoSide(1); glDrawArrays(mode, startVertex, numVertices); +#endif _stats._DSNumTriangles += 2 * numVertices / 3; _stats._DSNumDrawcalls += 2; @@ -55,11 +59,14 @@ void GL45Backend::do_drawIndexed(const Batch& batch, size_t paramOffset) { GLvoid* indexBufferByteOffset = reinterpret_cast(startIndex * typeByteSize + _input._indexBufferOffset); if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2); +#else setupStereoSide(0); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); setupStereoSide(1); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); - +#endif _stats._DSNumTriangles += 2 * numIndices / 3; _stats._DSNumDrawcalls += 2; } else { @@ -83,10 +90,14 @@ void GL45Backend::do_drawInstanced(const Batch& batch, size_t paramOffset) { if (isStereo()) { GLint trueNumInstances = 2 * numInstances; +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, trueNumInstances); +#else setupStereoSide(0); glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); setupStereoSide(1); glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); +#endif _stats._DSNumTriangles += (trueNumInstances * numVertices) / 3; _stats._DSNumDrawcalls += trueNumInstances; @@ -112,10 +123,15 @@ void GL45Backend::do_drawIndexedInstanced(const Batch& batch, size_t paramOffset if (isStereo()) { GLint trueNumInstances = 2 * numInstances; + +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance); +#else setupStereoSide(0); glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); setupStereoSide(1); glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); +#endif _stats._DSNumTriangles += (trueNumInstances * numIndices) / 3; _stats._DSNumDrawcalls += trueNumInstances; } else { diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 12a1cd10f1..db7808e781 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -22,29 +22,84 @@ struct TransformCamera { }; layout(std140) uniform transformCameraBuffer { +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_CAMERA + TransformCamera _camera[2]; +#else 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() { +#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; +#endif } vec3 getEyeWorldPos() { - return _camera._viewInverse[3].xyz; + return getTransformCamera()._viewInverse[3].xyz; } - bool cam_isStereo() { +#ifdef GPU_TRANSFORM_IS_STEREO + return getTransformCamera()._stereoInfo.x > 0.0; +#else return _camera._stereoInfo.x > 0.0; +#endif } float cam_getStereoSide() { +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_CAMERA + return getTransformCamera()._stereoInfo.y; +#else return _camera._stereoInfo.y; +#endif +#else + return _camera._stereoInfo.y; +#endif } <@endfunc@> - <@func declareStandardObjectTransform()@> struct TransformObject { mat4 _model; @@ -92,6 +147,25 @@ TransformObject getTransformObject() { <$viewport$> = <$cameraTransform$>._viewport; <@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)@> { // _transformModelToEyeWorldAlignedPos @@ -108,6 +182,8 @@ TransformObject getTransformObject() { <$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$> <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; + + <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> @@ -117,6 +193,8 @@ TransformObject getTransformObject() { <$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$> <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; <$eyePos$> = vec4((<$cameraTransform$>._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0); + + <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> @@ -135,11 +213,10 @@ TransformObject getTransformObject() { <@endfunc@> <@func transformModelToWorldDir(cameraTransform, objectTransform, modelDir, worldDir)@> - { // transformModelToEyeDir + { // transformModelToEyeDir vec3 mr0 = <$objectTransform$>._modelInverse[0].xyz; vec3 mr1 = <$objectTransform$>._modelInverse[1].xyz; vec3 mr2 = <$objectTransform$>._modelInverse[2].xyz; - <$worldDir$> = vec3(dot(mr0, <$modelDir$>), dot(mr1, <$modelDir$>), dot(mr2, <$modelDir$>)); } <@endfunc@> @@ -173,6 +250,8 @@ TransformObject getTransformObject() { <@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@> { // transformEyeToClipPos <$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0); + + <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> diff --git a/libraries/model/src/model/skybox.slv b/libraries/model/src/model/skybox.slv index 5df1aa0a4a..6fd9532fa1 100755 --- a/libraries/model/src/model/skybox.slv +++ b/libraries/model/src/model/skybox.slv @@ -36,4 +36,6 @@ void main(void) { // Position is supposed to come in clip space gl_Position = vec4(inPosition.xy, 0.0, 1.0); + + <$transformStereoClipsSpace(cam, gl_Position)$> } diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index 0525509f0b..36e281ab5b 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -24,7 +24,7 @@ out vec4 _texCoord0; void main(void) { if (sphereParam.w != 0.0) { - + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -33,9 +33,14 @@ void main(void) { vec4 projected = gl_Position / gl_Position.w; projected.xy = (projected.xy + 1.0) * 0.5; +#ifdef GPU_TRANSFORM_IS_STEREO +#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; } else { const float depth = -1.0; //Draw at near plane @@ -47,11 +52,27 @@ void main(void) { ); 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); +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN +#else if (cam_isStereo()) { _texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide()); } +#endif +#endif + gl_Position = pos; + } + } diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index 4a1a0472aa..935d756b28 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -46,9 +46,14 @@ void main(void) { vec4 projected = gl_Position / gl_Position.w; projected.xy = (projected.xy + 1.0) * 0.5; +#ifdef GPU_TRANSFORM_IS_STEREO +#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; } else { const float depth = -1.0; //Draw at near plane @@ -60,10 +65,24 @@ void main(void) { ); 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); + +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN +#else if (cam_isStereo()) { _texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide()); } +#endif +#endif + gl_Position = pos; } } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index eb0e58eb4a..bfa61f3b36 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -401,9 +401,13 @@ bool OpenVrDisplayPlugin::internalActivate() { memset(&timing, 0, sizeof(timing)); timing.m_nSize = sizeof(vr::Compositor_FrameTiming); vr::VRCompositor()->GetFrameTiming(&timing); - _asyncReprojectionActive = timing.m_nReprojectionFlags & VRCompositor_ReprojectionAsync; + auto usingOpenVRForOculus = oculusViaOpenVR(); + _asyncReprojectionActive = (timing.m_nReprojectionFlags & VRCompositor_ReprojectionAsync) || usingOpenVRForOculus; _threadedSubmit = !_asyncReprojectionActive; + if (usingOpenVRForOculus) { + qDebug() << "Oculus active via OpenVR: " << usingOpenVRForOculus; + } qDebug() << "OpenVR Async Reprojection active: " << _asyncReprojectionActive; qDebug() << "OpenVR Threaded submit enabled: " << _threadedSubmit; diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 0c3a2faed6..56a5dd3f5b 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -60,6 +60,12 @@ bool isOculusPresent() { 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() { static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR"); static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG); diff --git a/plugins/openvr/src/OpenVrHelpers.h b/plugins/openvr/src/OpenVrHelpers.h index be79dd1155..f00cd9e117 100644 --- a/plugins/openvr/src/OpenVrHelpers.h +++ b/plugins/openvr/src/OpenVrHelpers.h @@ -15,6 +15,7 @@ #include #include +bool oculusViaOpenVR(); // is the user using Oculus via OpenVR bool openVrSupported(); vr::IVRSystem* acquireOpenVrSystem();