diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index b15ee4fe29..cd4f4d7d2c 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -153,10 +153,10 @@ void Batch::setViewTransform(const Transform& view) { _params.push_back(_transforms.cache(view)); } -void Batch::setProjectionTransform(const Transform& proj) { +void Batch::setProjectionTransform(const Mat4& proj) { ADD_COMMAND(setProjectionTransform); - _params.push_back(_transforms.cache(proj)); + _params.push_back(cacheData(sizeof(Mat4), &proj); } void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 0657eacd6e..b9467f7fdc 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -89,7 +89,7 @@ public: // with the ModelTransformu to create the equivalent of the glModelViewMatrix void setModelTransform(const Transform& model); void setViewTransform(const Transform& view); - void setProjectionTransform(const Transform& proj); + void setProjectionTransform(const Mat4& proj); // Shader Stage void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index b17bd7b2b8..0ef68c9fd0 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -13,6 +13,23 @@ <@if GLPROFILE == PC_GL @> <@def VERSION_HEADER #version 330 compatibility@> + +<@func inputPosition name@> +layout(location = 0) in vec3 <$name$>; +<@endfunc@> + +<@func inputNormal name@> +layout(location = 1) in vec3 <$name$>; +<@endfunc@> + +<@func inputTexcoord name@> +layout(location = 4) in vec2 <$name$>; +<@endfunc@> + +<@func inputColor name@> +layout(location = 4) vec3 <$name$>; +<@endfunc@> + <@elif GLPROFILE == MAC_GL @> <@def VERSION_HEADER #version 120@> <@else@> diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index b8cba3ded1..2bbf9ea032 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -29,6 +29,21 @@ class Batch; class Backend { public: + class TransformObject { + public: + Mat4 _model; + Mat4 _modelInverse; + Mat4 _modelView; + Mat4 _modelViewInverseTranspose; + }; + + class TransformCamera { + public: + Mat4 _view; + Mat4 _viewInverse; + Mat4 _projection; + }; + template< typename T > static void setGPUObject(const Buffer& buffer, T* bo) { buffer.setGPUObject(reinterpret_cast(bo)); diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 6274c294ec..cbf90384ce 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -11,6 +11,7 @@ #ifndef hifi_gpu_Format_h #define hifi_gpu_Format_h +#include #include namespace gpu { @@ -24,6 +25,12 @@ typedef char int8; typedef uint32 Offset; +typedef glm::mat4 Mat4; +typedef glm::mat3 Mat3; +typedef glm::vec4 Vec4; +typedef glm::vec3 Vec3; +typedef glm::vec2 Vec2; + // Description of a scalar type enum Type { diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 34ca47f300..7cc3958497 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -386,18 +386,49 @@ void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) { } void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) { - _transform._projection = batch._transforms.get(batch._params[paramOffset]._uint); + memcpy(&_transform._projection, batch.editData(batch._params[paramOffset]._uint), sizeof(Mat4)); _transform._invalidProj = true; } +void GLBackend::initTransform() { +#if defined(Q_OS_MAC) +#elif defined(Q_OS_WIN) + glGenBuffers(1, &_transform._transformObjectBuffer); + glGenBuffers(1, &_transform._transformCameraBuffer); + + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); + + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); + + + glBindBuffer(GL_UNIFORM_BUFFER, 0); +#else +#endif +} + +void GLBackend::killTransform() { +#if defined(Q_OS_MAC) +#elif defined(Q_OS_WIN) + glDeleteBuffers(1, &_transform._transformObjectBuffer); + glDeleteBuffers(1, &_transform._transformCameraBuffer); +#else +#endif +} + void GLBackend::updateTransform() { +#define LEGACY_TRANSFORM_PIPELINE +#ifdef LEGACY_TRANSFORM_PIPELINE if (_transform._invalidProj) { // TODO: implement the projection matrix assignment to gl state - /* if (_transform._lastMode != GL_PROJECTION) { + if (_transform._lastMode != GL_PROJECTION) { glMatrixMode(GL_PROJECTION); _transform._lastMode = GL_PROJECTION; } - CHECK_GL_ERROR();*/ + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&_transform._projection)); + + CHECK_GL_ERROR(); } if (_transform._invalidModel || _transform._invalidView) { @@ -434,6 +465,46 @@ void GLBackend::updateTransform() { _transform._invalidModel = false; _transform._invalidView = false; } +#else + + if (_transform._invalidProj) { + _transform._transformCamera._projection = _transform._projection; + } + + if (_transform._invalidView) { + _transform._view.getInverseMatrix(_transform._transformCamera._view); + _transform._view.getMatrix(_transform._transformCamera._viewInverse); + } + + if (_transform._invalidModel) { + _transform._model.getMatrix(_transform._transformObject._model); + _transform._model.getInverseMatrix(_transform._transformObject._modelInverse); + } + + if (_transform._invalidView || _transform._invalidModel) { + Transform mvx; + Transform::inverseMult(mvx, _transform._view, _transform._model); + mvx.getMatrix(_transform._transformObject._modelView); + mvx.getInverseTransposeMatrix(_transform._transformObject._modelViewInverseTranspose); + } + + if (_transform._invalidView || _transform._invalidProj) { + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + if (_transform._invalidView || _transform._invalidModel) { + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(_transform._transformObject), (const void*) &_transform._transformObject); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + glBindBufferRange(GL_UNIFORM_BUFFER, 0, _transform._transformCameraBuffer, 0, sizeof(TransformCamera)); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, _transform._transformObjectBuffer, 0, sizeof(TransformObject)); + + _transform._invalidView = _transform._invalidProj = _transform._invalidModel = false; +#endif } void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index e3450ae71a..1c5906525b 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -113,11 +113,17 @@ protected: void do_setViewTransform(Batch& batch, uint32 paramOffset); void do_setProjectionTransform(Batch& batch, uint32 paramOffset); + void initTransform(); + void killTransform(); void updateTransform(); struct TransformStageState { + TransformObject _transformObject; + TransformCamera _transformCamera; + GLuint _transformObjectBuffer; + GLuint _transformCameraBuffer; Transform _model; Transform _view; - Transform _projection; + Mat4 _projection; bool _invalidModel; bool _invalidView; bool _invalidProj; @@ -125,6 +131,8 @@ protected: GLenum _lastMode; TransformStageState() : + _transformObjectBuffer(0), + _transformCameraBuffer(0), _model(), _view(), _projection(), diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 04ed408b03..1ae422cd08 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -13,19 +13,19 @@ struct TransformObject { mat4 _model; mat4 _modelInverseTranspose; + mat4 _modelView; + mat4 _modelViewInverseTranspose; }; struct TransformCamera { mat4 _view; - mat4 _viewInverseTranspose; - mat4 _proj; - mat4 _projInverseTranspose; - mat4 _viewProj; - mat4 _viewProjInverseTranspose; + mat4 _viewInverse; + mat4 _projection; + }; vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { - return camera._proj * (camera._view * (object._model * pos))); + return camera._projection * (object._modelView * pos); } diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 81ce31d767..8181a1098b 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -866,4 +866,11 @@ float ViewFrustum::distanceToCamera(const glm::vec3& point) const { return distanceToPoint; } +void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { + if (isOrthographic()) { + proj = glm::ortho(getWidth() * -0.5, getWidth() * +0.5, getHeight() * -0.5, getHeight() * 0.5); + } else { + proj = glm::perspective(getFieldOfView(), getAspectRatio(), getNearClip(), getFarClip()); + } +} diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index c40bc37652..a74140b94f 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -124,6 +124,7 @@ public: float distanceToCamera(const glm::vec3& point) const; + void evalProjectionMatrix(glm::mat4& proj) const; private: // Used for keyhole calculations ViewFrustum::location pointInKeyhole(const glm::vec3& point) const; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f166aecae9..edbce6b814 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1659,11 +1659,26 @@ void Model::setupBatchTransform(gpu::Batch& batch) { void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); + RenderArgs::RenderSide renderSide = RenderArgs::MONO; if (args) { renderSide = args->_renderSide; } + if (args) { + glm::mat4 proj; + args->_viewFrustum->evalProjectionMatrix(proj); + gpu::Batch batch; + batch.setProjectionTransform(proj); + ::gpu::GLBackend::renderBatch(batch); + + } + + _viewState->getViewTransform(); + // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) + _transforms[0].preTranslate(-_translation); + + // Do the rendering batch creation for mono or left eye, not for right eye if (renderSide != RenderArgs::STEREO_RIGHT) { // Let's introduce a gpu::Batch to capture all the calls to the graphics api diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 260dd8f0f9..1da88a3876 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -14,6 +14,11 @@ <@include gpu/Transform.slh@> const int MAX_TEXCOORDS = 2; +<$inputPosition(vin_position)$> +<$inputNormal(vin_normal)$> +<$inputTexcoord(vin_texcoord)$> +<$inputColor(vin_color)$> + uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the interpolated normal @@ -30,6 +35,23 @@ void main(void) { gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform - gl_Position = ftransform(); + gl_Position = gl_ModelViewProjectionMatrix * vec4(vin_position, 1.0); } + + +/* +void main(void) { + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // pass along the diffuse color + gl_FrontColor = gl_Color; + + // and the texture coordinates + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + + // use standard pipeline transform + gl_Position = ftransform(); +} +*/ diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 346a82a3b0..4f5f441170 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -90,6 +90,7 @@ public: Mat4& getMatrix(Mat4& result) const; Mat4& getInverseMatrix(Mat4& result) const; + Mat4& getInverseTransposeMatrix(Mat4& result) const; Transform& evalInverse(Transform& result) const; @@ -329,6 +330,13 @@ inline Transform::Mat4& Transform::getInverseMatrix(Transform::Mat4& result) con return inverse.getMatrix(result); } +inline Transform::Mat4& Transform::getInverseTransposeMatrix(Transform::Mat4& result) const { + getInverseMatrix(result); + result = glm::transpose(result); + return result; +} + + inline void Transform::evalFromRawMatrix(const Mat4& matrix) { // for now works only in the case of TRS transformation if ((matrix[0][3] == 0) && (matrix[1][3] == 0) && (matrix[2][3] == 0) && (matrix[3][3] == 1.0f)) {