diff --git a/libraries/entities-renderer/src/RenderableProceduralItemShader.h b/libraries/entities-renderer/src/RenderableProceduralItemShader.h index 4762f619bf..d7df43de14 100644 --- a/libraries/entities-renderer/src/RenderableProceduralItemShader.h +++ b/libraries/entities-renderer/src/RenderableProceduralItemShader.h @@ -314,6 +314,8 @@ in vec4 _position; // TODO add more uniforms uniform float iGlobalTime; // shader playback time (in seconds) uniform vec3 iWorldScale; // the dimensions of the object being rendered +uniform mat3 iWorldOrientation; // the orientation of the object being rendered +uniform vec3 iWorldEyePosition; // the world position of the eye // TODO add support for textures // TODO document available inputs other than the uniforms diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index c93ae252e3..2b04478831 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -98,7 +98,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { } batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation if (_procedural->ready()) { - _procedural->prepare(batch, getPosition(), getDimensions()); + _procedural->prepare(batch, getPosition(), getDimensions(), getOrientation(), args->getViewFrustum().getPosition()); auto outColor = _procedural->getColor(color); batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); DependencyManager::get()->renderShape(batch, MAPPING[_shape]); diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index ece1ee730c..e18b784018 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -114,6 +114,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_glUniform3fv), (&::gpu::gl::GLBackend::do_glUniform4fv), (&::gpu::gl::GLBackend::do_glUniform4iv), + (&::gpu::gl::GLBackend::do_glUniformMatrix3fv), (&::gpu::gl::GLBackend::do_glUniformMatrix4fv), (&::gpu::gl::GLBackend::do_glColor4f), @@ -515,6 +516,22 @@ void GLBackend::do_glUniform4iv(Batch& batch, size_t paramOffset) { (void)CHECK_GL_ERROR(); } +void GLBackend::do_glUniformMatrix3fv(Batch& batch, size_t paramOffset) { + if (_pipeline._program == 0) { + // We should call updatePipeline() to bind the program but we are not doing that + // because these uniform setters are deprecated and we don;t want to create side effect + return; + } + updatePipeline(); + + glUniformMatrix3fv( + GET_UNIFORM_LOCATION(batch._params[paramOffset + 3]._int), + batch._params[paramOffset + 2]._uint, + batch._params[paramOffset + 1]._uint, + (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint)); + (void)CHECK_GL_ERROR(); +} + void GLBackend::do_glUniformMatrix4fv(Batch& batch, size_t paramOffset) { if (_pipeline._program == 0) { // We should call updatePipeline() to bind the program but we are not doing that diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 610672f44f..5255a6cb25 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -136,6 +136,7 @@ public: virtual void do_glUniform3fv(Batch& batch, size_t paramOffset) final; virtual void do_glUniform4fv(Batch& batch, size_t paramOffset) final; virtual void do_glUniform4iv(Batch& batch, size_t paramOffset) final; + virtual void do_glUniformMatrix3fv(Batch& batch, size_t paramOffset) final; virtual void do_glUniformMatrix4fv(Batch& batch, size_t paramOffset) final; virtual void do_glColor4f(Batch& batch, size_t paramOffset) final; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 9126f11acf..6dc1d63ca8 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -567,6 +567,16 @@ void Batch::_glUniform4iv(int32 location, int count, const int32* value) { _params.push_back(location); } +void Batch::_glUniformMatrix3fv(int32 location, int count, uint8 transpose, const float* value) { + ADD_COMMAND(glUniformMatrix3fv); + + const int MATRIX3_SIZE = 9 * sizeof(float); + _params.push_back(cacheData(count * MATRIX3_SIZE, value)); + _params.push_back(transpose); + _params.push_back(count); + _params.push_back(location); +} + void Batch::_glUniformMatrix4fv(int32 location, int count, uint8 transpose, const float* value) { ADD_COMMAND(glUniformMatrix4fv); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index a2ee57759f..f8b447975c 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -269,6 +269,7 @@ public: void _glUniform3fv(int location, int count, const float* value); void _glUniform4fv(int location, int count, const float* value); void _glUniform4iv(int location, int count, const int* value); + void _glUniformMatrix3fv(int location, int count, unsigned char transpose, const float* value); void _glUniformMatrix4fv(int location, int count, unsigned char transpose, const float* value); void _glUniform(int location, int v0) { @@ -291,6 +292,10 @@ public: _glUniform4f(location, v.x, v.y, v.z, v.w); } + void _glUniform(int location, const glm::quat& v) { + _glUniformMatrix3fv(location, 1, false, reinterpret_cast< const float* >(&glm::mat3_cast(v))); + } + void _glColor4f(float red, float green, float blue, float alpha); enum Command { @@ -348,6 +353,7 @@ public: COMMAND_glUniform3fv, COMMAND_glUniform4fv, COMMAND_glUniform4iv, + COMMAND_glUniformMatrix3fv, COMMAND_glUniformMatrix4fv, COMMAND_glColor4f, diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 781b508bc7..4f308e0812 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -39,6 +39,8 @@ static const std::string STANDARD_UNIFORM_NAMES[Procedural::NUM_STANDARD_UNIFORM "iFrameCount", "iWorldScale", "iWorldPosition", + "iWorldOrientation", + "iWorldEyePosition", "iChannelResolution" }; @@ -202,9 +204,11 @@ bool Procedural::ready() { return true; } -void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size) { +void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const glm::vec3& eyePos) { _entityDimensions = size; _entityPosition = position; + _entityOrientation = orientation; + _eyePos = eyePos; if (_shaderUrl.isLocalFile()) { auto lastModified = (quint64)QFileInfo(_shaderPath).lastModified().toMSecsSinceEpoch(); if (lastModified > _shaderModified) { @@ -404,10 +408,10 @@ void Procedural::setupUniforms() { }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[SCALE]) { + if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[ORIENTATION]) { // FIXME move into the 'set once' section, since this doesn't change over time _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[SCALE], _entityDimensions); + batch._glUniform(_standardUniformSlots[ORIENTATION], _entityOrientation); }); } @@ -417,6 +421,14 @@ void Procedural::setupUniforms() { batch._glUniform(_standardUniformSlots[POSITION], _entityPosition); }); } + + if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[EYE_POSITION]) { + // FIXME move into the 'set once' section, since this doesn't change over time + _uniforms.push_back([=](gpu::Batch& batch) { + batch._glUniform(_standardUniformSlots[EYE_POSITION], _eyePos); + }); + } + } void Procedural::setupChannels(bool shouldCreate) { diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index f928d0e594..e27f8ade44 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -38,7 +38,7 @@ public: void parse(const QString& userDataJson); bool ready(); - void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size); + void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const glm::vec3& eyePos); const gpu::ShaderPointer& getShader() const { return _shader; } glm::vec4 getColor(const glm::vec4& entityColor); @@ -56,6 +56,8 @@ public: FRAME_COUNT, SCALE, POSITION, + ORIENTATION, + EYE_POSITION, CHANNEL_RESOLUTION, NUM_STANDARD_UNIFORMS }; @@ -93,6 +95,8 @@ protected: // Entity metadata glm::vec3 _entityDimensions; glm::vec3 _entityPosition; + glm::quat _entityOrientation; + glm::vec3 _eyePos; private: // This should only be called from the render thread, as it shares data with Procedural::prepare diff --git a/libraries/procedural/src/procedural/ProceduralShaders.h b/libraries/procedural/src/procedural/ProceduralShaders.h index eddf53cb09..00571c3a94 100644 --- a/libraries/procedural/src/procedural/ProceduralShaders.h +++ b/libraries/procedural/src/procedural/ProceduralShaders.h @@ -289,6 +289,8 @@ const vec4 iChannelTime = vec4(0.0); uniform vec4 iDate; uniform int iFrameCount; uniform vec3 iWorldPosition; +uniform mat3 iWorldOrientation; +uniform vec3 iWorldEyePosition; uniform vec3 iChannelResolution[4]; uniform sampler2D iChannel0; uniform sampler2D iChannel1; diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 1aa59c90d7..5905bfb017 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -52,7 +52,7 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, batch.setModelTransform(Transform()); // only for Mac auto& procedural = skybox._procedural; - procedural.prepare(batch, glm::vec3(0), glm::vec3(1)); + procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat(1, 0, 0, 0), glm::vec3(0)); auto textureSlot = procedural.getShader()->getTextures().findLocation("cubeMap"); auto bufferSlot = procedural.getShader()->getBuffers().findLocation("skyboxBuffer"); skybox.prepare(batch, textureSlot, bufferSlot);