diff options
54 files changed, 3025 insertions, 267 deletions
diff --git a/src/Runtime/Qt3DSRuntimeStatic.pro b/src/Runtime/Qt3DSRuntimeStatic.pro index 072eaa3a..92fead0c 100644 --- a/src/Runtime/Qt3DSRuntimeStatic.pro +++ b/src/Runtime/Qt3DSRuntimeStatic.pro @@ -241,7 +241,8 @@ SOURCES += \ Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp \ Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp \ Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp \ - Source/Qt3DSRender/Source/backends/software/Qt3DSRenderBackendNULL.cpp + Source/Qt3DSRender/Source/backends/software/Qt3DSRenderBackendNULL.cpp \ + Source/Qt3DSRender/Source/backends/gl/Q3DSRenderBackendGLES2.cpp HEADERS += \ Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h \ @@ -254,7 +255,8 @@ HEADERS += \ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h \ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h \ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h \ - Source/Qt3DSRender/Include/render/backends/software/Qt3DSRenderBackendNULL.h + Source/Qt3DSRender/Include/render/backends/software/Qt3DSRenderBackendNULL.h \ + Source/Qt3DSRender/Include/render/backends/gl/Q3DSRenderBackendGLES2.h # UICDM SOURCES += \ diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h index 34b2eb73..bee5811a 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h @@ -37,6 +37,7 @@ #include "foundation/Qt3DSDataRef.h" #include "foundation/Qt3DSMemoryBuffer.h" #include "render/glg/Qt3DSGLImplObjects.h" +#include "render/backends/gl/Q3DSRenderBackendGLES2.h" #include "render/backends/gl/Qt3DSRenderBackendGL3.h" #include "render/backends/gl/Qt3DSRenderBackendGL4.h" #include "render/backends/software/Qt3DSRenderBackendNULL.h" @@ -149,6 +150,8 @@ namespace render { virtual bool IsBlendCoherencySupported() const = 0; virtual bool IsAdvancedBlendHwSupported() const = 0; virtual bool IsAdvancedBlendHwSupportedKHR() const = 0; + virtual bool IsStandardDerivativesSupported() const = 0; + virtual bool IsTextureLodSupported() const = 0; virtual void SetDefaultRenderTarget(QT3DSU64 targetID) = 0; virtual void SetDefaultDepthBufferBitCount(QT3DSI32 depthBits) = 0; @@ -763,6 +766,14 @@ namespace render { { return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::BlendCoherency); } + bool IsStandardDerivativesSupported() const override + { + return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::StandardDerivatives); + } + bool IsTextureLodSupported() const override + { + return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::TextureLod); + } void SetDefaultRenderTarget(QT3DSU64 targetID) override { diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h index ffbbda72..8fd89bac 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h @@ -215,7 +215,7 @@ namespace render { virtual void Release() = 0; virtual void Validate(NVRenderShaderProgram *inShader) = 0; - virtual void BindToPorgram(NVRenderShaderProgram *inShader) = 0; + virtual void BindToProgram(NVRenderShaderProgram *inShader) = 0; virtual void Update() = 0; }; @@ -271,7 +271,7 @@ namespace render { m_pCB->Update(); } - void BindToPorgram(NVRenderShaderProgram *inShader) override + void BindToProgram(NVRenderShaderProgram *inShader) override { if (m_pCB) m_pCB->BindToShaderProgram(inShader, m_Location, m_Binding); @@ -329,7 +329,7 @@ namespace render { m_pSB->Update(); } - void BindToPorgram(NVRenderShaderProgram * /*inShader*/) override + void BindToProgram(NVRenderShaderProgram * /*inShader*/) override { if (m_pSB) m_pSB->BindToShaderProgram(m_Location); @@ -388,7 +388,7 @@ namespace render { m_pAcB->Update(); } - void BindToPorgram(NVRenderShaderProgram * /*inShader*/) override + void BindToProgram(NVRenderShaderProgram * /*inShader*/) override { if (m_pAcB) m_pAcB->BindToShaderProgram(m_Location); diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h index 73e123c1..ae737ba2 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h @@ -407,6 +407,11 @@ namespace render { NVRenderShaderProgram *m_Shader; ///< pointer to shader program NVRenderShaderConstantBase *m_Constant; ///< poiner to shader constant object + NVRenderCachedShaderProperty(const QString &inConstantName, NVRenderShaderProgram &inShader) + : NVRenderCachedShaderProperty(qPrintable(inConstantName), inShader) + { + } + NVRenderCachedShaderProperty(const char *inConstantName, NVRenderShaderProgram &inShader) : m_Shader(&inShader) , m_Constant(NULL) @@ -424,6 +429,7 @@ namespace render { } } } + NVRenderCachedShaderProperty() : m_Shader(NULL) , m_Constant(NULL) @@ -468,7 +474,7 @@ namespace render { if (m_ShaderBuffer) { m_ShaderBuffer->Validate(m_Shader); m_ShaderBuffer->Update(); - m_ShaderBuffer->BindToPorgram(m_Shader); + m_ShaderBuffer->BindToProgram(m_Shader); } } diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h index 00811539..12de5d88 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h @@ -126,6 +126,9 @@ namespace render { BlendCoherency, ///< Hardware supports blend coherency gpuShader5, // for high precision sampling AdvancedBlendKHR, ///< Driver supports advanced blend modes + VertexArrayObject, + StandardDerivatives, + TextureLod }; } NVRenderBackendCaps; @@ -2213,8 +2216,8 @@ namespace render { bool bTimerQuerySupported : 1; ///< Hardware supports timer queries bool bProgramInterfaceSupported : 1; ///< API supports program interface queries bool bStorageBufferSupported : 1; ///< Shader storage buffers are supported - bool - bAtomicCounterBufferSupported : 1; ///< Atomic counter buffers are supported + bool bAtomicCounterBufferSupported : 1; ///< Atomic counter buffers are + /// supported bool bShaderImageLoadStoreSupported : 1; ///< Shader image load / store ///operations are supported bool bProgramPipelineSupported : 1; ///< Driver supports separate programs @@ -2225,6 +2228,9 @@ namespace render { bool bGPUShader5ExtensionSupported : 1; bool bKHRAdvancedBlendSupported : 1; ///< Advanced blend modes supported bool bKHRBlendCoherenceSupported : 1; ///< Advanced blend done coherently + bool bVertexArrayObjectSupported : 1; + bool bStandardDerivativesSupported : 1; + bool bTextureLodSupported : 1; } bits; QT3DSU32 u32Values; diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Q3DSRenderBackendGLES2.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Q3DSRenderBackendGLES2.h new file mode 100644 index 00000000..eefc7996 --- /dev/null +++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Q3DSRenderBackendGLES2.h @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DS_RENDER_BACKEND_GLES2_H +#define QT3DS_RENDER_BACKEND_GLES2_H + +#include "foundation/Qt3DSAtomic.h" +#include "render/backends/gl/Qt3DSRenderBackendGLBase.h" +#include "render/backends/gl/Qt3DSOpenGLExtensions.h" + +#include <QtGui/qopenglextrafunctions.h> +#include <QtOpenGLExtensions/QtOpenGLExtensions> + +namespace qt3ds { +namespace render { + + ///< forward declaration + class NVRenderBackendMiscStateGL; + + using namespace foundation; + + class NVRenderBackendGLES2Impl : public NVRenderBackendGLBase + { + public: + /// constructor + NVRenderBackendGLES2Impl(NVFoundationBase &fnd, + qt3ds::foundation::IStringTable &stringTable, + const QSurfaceFormat &format); + /// destructor + virtual ~NVRenderBackendGLES2Impl(); + + QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation) + + public: + QT3DSU32 GetDepthBits() const override; + QT3DSU32 GetStencilBits() const override; + void GenerateMipMaps(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, + NVRenderHint::Enum genType) override; + + void SetMultisampledTextureData2D(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, + size_t samples, + NVRenderTextureFormats::Enum internalFormat, + size_t width, size_t height, + bool fixedsamplelocations) override; + + void SetTextureData3D(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, QT3DSU32 level, + NVRenderTextureFormats::Enum internalFormat, size_t width, + size_t height, size_t depth, QT3DSI32 border, + NVRenderTextureFormats::Enum format, + const void *hostPtr = nullptr) override; + + void SetTextureData2D(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, QT3DSU32 level, + NVRenderTextureFormats::Enum internalFormat, size_t width, + size_t height, QT3DSI32 border, + NVRenderTextureFormats::Enum format, + const void *hostPtr = nullptr) override; + + void UpdateSampler( + NVRenderBackendSamplerObject so, NVRenderTextureTargetType::Enum target, + NVRenderTextureMinifyingOp::Enum minFilter = NVRenderTextureMinifyingOp::Linear, + NVRenderTextureMagnifyingOp::Enum magFilter = NVRenderTextureMagnifyingOp::Linear, + NVRenderTextureCoordOp::Enum wrapS = NVRenderTextureCoordOp::ClampToEdge, + NVRenderTextureCoordOp::Enum wrapT = NVRenderTextureCoordOp::ClampToEdge, + NVRenderTextureCoordOp::Enum wrapR = NVRenderTextureCoordOp::ClampToEdge, + QT3DSF32 minLod = -1000.0f, QT3DSF32 maxLod = 1000.0f, QT3DSF32 lodBias = 0.0f, + NVRenderTextureCompareMode::Enum compareMode = NVRenderTextureCompareMode::NoCompare, + NVRenderTextureCompareOp::Enum compareFunc = NVRenderTextureCompareOp::LessThanOrEqual, + QT3DSF32 anisotropy = 1.0f, QT3DSF32 *borderColor = nullptr) override; + + void UpdateTextureObject(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, QT3DSI32 baseLevel, + QT3DSI32 maxLevel) override; + + void UpdateTextureSwizzle(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, + NVRenderTextureSwizzleMode::Enum swizzleMode) override; + + bool SetInputAssembler(NVRenderBackendInputAssemblerObject iao, + NVRenderBackendShaderProgramObject po) override; + + void SetDrawBuffers(NVRenderBackendRenderTargetObject rto, + NVConstDataRef<QT3DSI32> inDrawBufferSet) override; + void SetReadBuffer(NVRenderBackendRenderTargetObject rto, + NVReadFaces::Enum inReadFace) override; + + void BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, QT3DSI32 srcY1, + QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1, + NVRenderClearFlags flags, + NVRenderTextureMagnifyingOp::Enum filter) override; + + + NVRenderBackendRenderTargetObject CreateRenderTarget() override; + void ReleaseRenderTarget(NVRenderBackendRenderTargetObject rto) override; + void RenderTargetAttach(NVRenderBackendRenderTargetObject rto, + NVRenderFrameBufferAttachments::Enum attachment, + NVRenderBackendRenderbufferObject rbo) override; + void RenderTargetAttach(NVRenderBackendRenderTargetObject rto, + NVRenderFrameBufferAttachments::Enum attachment, + NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target + = NVRenderTextureTargetType::Texture2D) override; + void RenderTargetAttach(NVRenderBackendRenderTargetObject rto, + NVRenderFrameBufferAttachments::Enum attachment, + NVRenderBackendTextureObject to, QT3DSI32 level, + QT3DSI32 layer) override; + void SetRenderTarget(NVRenderBackendRenderTargetObject rto) override; + bool RenderTargetIsValid(NVRenderBackendRenderTargetObject rto) override; + + virtual NVRenderBackendRenderbufferObject + CreateRenderbuffer(NVRenderRenderBufferFormats::Enum storageFormat, size_t width, + size_t height) override; + void SetReadTarget(NVRenderBackendRenderTargetObject rto) override; + void ReleaseRenderbuffer(NVRenderBackendRenderbufferObject rbo) override; + bool ResizeRenderbuffer(NVRenderBackendRenderbufferObject rbo, + NVRenderRenderBufferFormats::Enum storageFormat, + size_t width, size_t height) override; + + void *MapBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags, + size_t offset, size_t length, + NVRenderBufferAccessFlags accessFlags) override; + bool UnmapBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags) override; + + QT3DSI32 GetConstantBufferCount(NVRenderBackendShaderProgramObject po) override; + QT3DSI32 GetConstantBufferInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id, + QT3DSU32 nameBufSize, QT3DSI32 *paramCount, + QT3DSI32 *bufferSize, QT3DSI32 *length, + char *nameBuf) override; + void GetConstantBufferParamIndices(NVRenderBackendShaderProgramObject po, QT3DSU32 id, + QT3DSI32 *indices) override; + void GetConstantBufferParamInfoByIndices(NVRenderBackendShaderProgramObject po, + QT3DSU32 count, QT3DSU32 *indices, + QT3DSI32 *type, + QT3DSI32 *size, QT3DSI32 *offset) override; + void ProgramSetConstantBlock(NVRenderBackendShaderProgramObject po, + QT3DSU32 blockIndex, QT3DSU32 binding) override; + void ProgramSetConstantBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) override; + + NVRenderBackendQueryObject CreateQuery() override; + void ReleaseQuery(NVRenderBackendQueryObject qo) override; + void BeginQuery(NVRenderBackendQueryObject qo, NVRenderQueryType::Enum type) override; + void EndQuery(NVRenderBackendQueryObject qo, NVRenderQueryType::Enum type) override; + void GetQueryResult(NVRenderBackendQueryObject qo, + NVRenderQueryResultType::Enum resultType, QT3DSU32 *params) override; + void GetQueryResult(NVRenderBackendQueryObject qo, + NVRenderQueryResultType::Enum resultType, QT3DSU64 *params) override; + void SetQueryTimer(NVRenderBackendQueryObject qo) override; + + NVRenderBackendSyncObject CreateSync(NVRenderSyncType::Enum tpye, + NVRenderSyncFlags syncFlags) override; + void ReleaseSync(NVRenderBackendSyncObject so) override; + void WaitSync(NVRenderBackendSyncObject so, NVRenderCommandFlushFlags syncFlags, + QT3DSU64 timeout) override; + + protected: + NVRenderBackendMiscStateGL *m_pCurrentMiscState; ///< this holds the current misc state +#if defined(QT_OPENGL_ES) + Qt3DSOpenGLES2Extensions *m_qt3dsExtensions; +#endif + }; +} +} + +#endif diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h index 4fae0a46..fd8680e5 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h @@ -77,6 +77,10 @@ public: GLsizei, GLfloat *); void (QOPENGLF_APIENTRYP GetPathSpacingNV)(GLenum, GLsizei, GLenum, const void *, GLuint, GLfloat, GLfloat, GLenum, GLfloat *); + void (QOPENGLF_APIENTRYP BindVertexArrayOES) (GLuint array); + void (QOPENGLF_APIENTRYP DeleteVertexArraysOES) (GLsizei n, const GLuint *arrays); + void (QOPENGLF_APIENTRYP GenVertexArraysOES) (GLsizei n, GLuint *arrays); + GLboolean (QOPENGLF_APIENTRYP IsVertexArrayOES) (GLuint array); #endif }; @@ -180,6 +184,10 @@ public: GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); + void glBindVertexArrayOES(GLuint array); + void glDeleteVertexArraysOES(GLsizei n, const GLuint *arrays); + void glGenVertexArraysOES(GLsizei n, GLuint *arrays); + GLboolean glIsVertexArrayOES(GLuint array); bool initializeOpenGLFunctions() Q_DECL_FINAL; }; @@ -355,6 +363,30 @@ inline void Qt3DSOpenGLES2Extensions::glGetPathSpacingNV(GLenum pathListMode, advanceScale, kerningScale, transformType, returnedSpacing); } +inline void Qt3DSOpenGLES2Extensions::glBindVertexArrayOES(GLuint array) +{ + Q_D(Qt3DSOpenGLExtensions); + d->BindVertexArrayOES(array); +} + +inline void Qt3DSOpenGLES2Extensions::glDeleteVertexArraysOES(GLsizei n, const GLuint *arrays) +{ + Q_D(Qt3DSOpenGLExtensions); + d->DeleteVertexArraysOES(n, arrays); +} + +inline void Qt3DSOpenGLES2Extensions::glGenVertexArraysOES(GLsizei n, GLuint *arrays) +{ + Q_D(Qt3DSOpenGLExtensions); + d->GenVertexArraysOES(n, arrays); +} + +inline GLboolean Qt3DSOpenGLES2Extensions::glIsVertexArrayOES(GLuint array) +{ + Q_D(Qt3DSOpenGLExtensions); + return d->IsVertexArrayOES(array); +} + #endif // QT_OPENGL_ES #endif // QT3DSOPENGLEXTENSIONS_H diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h index 2cbc8b6a..0e6dc6d4 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h @@ -33,13 +33,13 @@ #include <QtGui/qtguiglobal.h> #if defined(QT_OPENGL_ES) #define GL_GLEXT_PROTOTYPES -// We require a minimum of GLES 3.1 for Qt3DStudio when building against a -// non-desktop OpenGL target #if defined(QT_OPENGL_ES_3_2) #include <GLES3/gl32.h> #else -#include <GLES3/gl31.h> +#include <GLES2/gl2.h> +#include <GLES3/gl3.h> #endif + // Adding this to ensure that platform version of gl2ext.h is included // before Qt's qopengles2ext.h which is missing symbols we need #include <GLES2/gl2ext.h> diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h index ebfb20c2..71162a56 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h @@ -46,6 +46,38 @@ namespace qt3ds { namespace render { +#ifndef GL_TEXTURE_2D_MULTISAMPLE +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#endif + +#ifndef GL_IMAGE_2D +#define GL_IMAGE_2D 0x904D +#endif + +#ifndef GL_MULTISAMPLE_EXT +#define GL_MULTISAMPLE_EXT 0x809D +#endif + +#ifndef GL_COLOR_ATTACHMENT1 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#endif + +#ifndef GL_RED +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#endif + +#ifndef GL_PATCHES +#define GL_PATCHES 0x000E +#endif + #define QT3DS_RENDER_ITERATE_QT3DS_GL_COLOR_FUNC \ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ZERO, Zero) \ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ONE, One) \ @@ -156,7 +188,7 @@ namespace render { QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_MAT2, QT3DSF32, 4) \ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_MAT3, QT3DSF32, 9) \ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_MAT4, QT3DSF32, 16) - +#if defined(GL_DEPTH_COMPONENT32) #define QT3DS_RENDER_ITERATE_GL_QT3DS_RENDERBUFFER_FORMATS \ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_RGBA4, RGBA4) \ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_RGB565, RGB565) \ @@ -165,6 +197,15 @@ namespace render { QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_DEPTH_COMPONENT24, Depth24) \ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_DEPTH_COMPONENT32, Depth32) \ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_STENCIL_INDEX8, StencilIndex8) +#else +#define QT3DS_RENDER_ITERATE_GL_QT3DS_RENDERBUFFER_FORMATS \ + QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_RGBA4, RGBA4) \ + QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_RGB565, RGB565) \ + QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_RGB5_A1, RGBA5551) \ + QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_DEPTH_COMPONENT16, Depth16) \ + QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_DEPTH_COMPONENT24, Depth24) \ + QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_STENCIL_INDEX8, StencilIndex8) +#endif #define QT3DS_RENDER_ITERATE_GL_QT3DS_FRAMEBUFFER_ATTACHMENTS \ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color0, 0) \ @@ -324,8 +365,7 @@ namespace render { } } - // TODO: Why aren't these defined? -#ifndef __APPLE__ +#if defined(GL_KHR_blend_equation_advanced) if (khrAdvancedBlendSupported) { switch (value) { case NVRenderBlendEquation::Overlay: @@ -619,12 +659,14 @@ namespace render { retval = GL_ELEMENT_ARRAY_BUFFER; else if (value & NVRenderBufferBindValues::Constant) retval = GL_UNIFORM_BUFFER; +#if defined(GL_ARB_shader_storage_buffer_object) else if (value & NVRenderBufferBindValues::Storage) retval = GL_SHADER_STORAGE_BUFFER; else if (value & NVRenderBufferBindValues::Atomic_Counter) retval = GL_ATOMIC_COUNTER_BUFFER; else if (value & NVRenderBufferBindValues::Draw_Indirect) retval = GL_DRAW_INDIRECT_BUFFER; +#endif else QT3DS_ASSERT(false); @@ -641,12 +683,14 @@ namespace render { retval |= NVRenderBufferBindValues::Index; else if (value == GL_UNIFORM_BUFFER) retval |= NVRenderBufferBindValues::Constant; +#if defined(GL_ARB_shader_storage_buffer_object) else if (value == GL_SHADER_STORAGE_BUFFER) retval |= NVRenderBufferBindValues::Storage; else if (value == GL_ATOMIC_COUNTER_BUFFER) retval |= NVRenderBufferBindValues::Atomic_Counter; else if (value == GL_DRAW_INDIRECT_BUFFER) retval |= NVRenderBufferBindValues::Draw_Indirect; +#endif else QT3DS_ASSERT(false); @@ -688,8 +732,13 @@ namespace render { GLenum retval = GL_INVALID_ENUM; if (type == NVRenderQueryType::Samples) retval = GL_ANY_SAMPLES_PASSED; +#if defined(GL_TIME_ELAPSED) else if (type == NVRenderQueryType::Timer) retval = GL_TIME_ELAPSED; +#elif defined(GL_TIME_ELAPSED_EXT) + else if (type == NVRenderQueryType::Timer) + retval = GL_TIME_ELAPSED_EXT; +#endif else QT3DS_ASSERT(false); @@ -796,8 +845,13 @@ namespace render { { switch (value) { case NVRenderTextureFormats::R8: - outFormat = GL_RED; - outInternalFormat = GL_R8; + if (type == NVRenderContextValues::GLES2) { + outFormat = GL_ALPHA; + outInternalFormat = GL_ALPHA; + } else { + outFormat = GL_RED; + outInternalFormat = GL_R8; + } outDataType = GL_UNSIGNED_BYTE; return true; case NVRenderTextureFormats::RG8: @@ -859,6 +913,7 @@ namespace render { // check extented texture formats if (!(type & contextFlags)) { switch (value) { +#if !defined(QT_OPENGL_ES) case NVRenderTextureFormats::R16: { if (IsGlEsContext(type)) { outFormat = GL_RED_INTEGER; @@ -870,6 +925,7 @@ namespace render { outDataType = GL_UNSIGNED_SHORT; return true; } +#endif case NVRenderTextureFormats::R16F: outFormat = GL_RED; outInternalFormat = GL_R16F; @@ -1240,8 +1296,10 @@ namespace render { return GL_INVALID_ENUM; } + static GLenum fromImageAccessToGL(NVRenderImageAccessType::Enum value) { +#if defined(GL_READ_ONLY) switch (value) { case NVRenderImageAccessType::Read: return GL_READ_ONLY; @@ -1252,7 +1310,7 @@ namespace render { default: break; } - +#endif QT3DS_ASSERT(false); return GL_INVALID_ENUM; } @@ -1279,7 +1337,7 @@ namespace render { { QT3DSU32 value = flags; GLbitfield retval = 0; - +#if !defined(QT_OPENGL_ES) if (value & NVRenderBufferBarrierValues::AtomicCounter) retval |= GL_ATOMIC_COUNTER_BARRIER_BIT; if (value & NVRenderBufferBarrierValues::BufferUpdate) @@ -1306,7 +1364,7 @@ namespace render { retval |= GL_UNIFORM_BARRIER_BIT; if (value & NVRenderBufferBarrierValues::VertexAttribArray) retval |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT; - +#endif QT3DS_ASSERT(retval); return retval; } @@ -1315,7 +1373,7 @@ namespace render { { QT3DSU32 value = flags; GLbitfield retval = 0; - +#if !defined(QT_OPENGL_ES) if (value & NVRenderShaderTypeValue::Vertex) retval |= GL_VERTEX_SHADER_BIT; if (value & NVRenderShaderTypeValue::Fragment) @@ -1325,12 +1383,12 @@ namespace render { if (value & NVRenderShaderTypeValue::TessEvaluation) retval |= GL_TESS_EVALUATION_SHADER_BIT; if (value & NVRenderShaderTypeValue::Geometry) -#if defined(QT_OPENGL_ES) +#if defined(QT_OPENGL_ES_3_1) retval |= GL_GEOMETRY_SHADER_BIT_EXT; #else retval |= GL_GEOMETRY_SHADER_BIT; #endif - +#endif QT3DS_ASSERT(retval || !value); return retval; } @@ -1360,10 +1418,12 @@ namespace render { #undef QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES case GL_SAMPLER_2D_SHADOW: return NVRenderShaderDataTypes::NVRenderTexture2DPtr; +#if !defined(QT_OPENGL_ES) case GL_UNSIGNED_INT_ATOMIC_COUNTER: return NVRenderShaderDataTypes::QT3DSU32; case GL_UNSIGNED_INT_IMAGE_2D: return NVRenderShaderDataTypes::NVRenderImage2DPtr; +#endif default: break; } @@ -1644,6 +1704,7 @@ namespace render { GLenum glFillMode; switch (inMode) { +#if !defined(QT_OPENGL_ES) case NVRenderPathFillMode::Fill: glFillMode = GL_PATH_FILL_MODE_NV; break; @@ -1656,9 +1717,9 @@ namespace render { case NVRenderPathFillMode::Invert: glFillMode = GL_INVERT; break; +#endif default: QT3DS_ASSERT(false); - glFillMode = GL_PATH_FILL_MODE_NV; break; } @@ -1670,6 +1731,7 @@ namespace render { GLenum glFontTarget; switch (inFontTarget) { +#if !defined(QT_OPENGL_ES) case NVRenderPathFontTarget::StandardFont: glFontTarget = GL_STANDARD_FONT_NAME_NV; break; @@ -1679,9 +1741,9 @@ namespace render { case NVRenderPathFontTarget::FileFont: glFontTarget = GL_FILE_NAME_NV; break; +#endif default: QT3DS_ASSERT(false); - glFontTarget = GL_STANDARD_FONT_NAME_NV; break; } @@ -1693,6 +1755,7 @@ namespace render { NVRenderPathReturnValues::Enum returnValue; switch (inReturnValue) { +#if !defined(QT_OPENGL_ES) case GL_FONT_GLYPHS_AVAILABLE_NV: returnValue = NVRenderPathReturnValues::FontGlypsAvailable; break; @@ -1705,6 +1768,7 @@ namespace render { case GL_FONT_UNINTELLIGIBLE_NV: returnValue = NVRenderPathReturnValues::FontUnintelligible; break; +#endif case GL_INVALID_ENUM: case GL_INVALID_VALUE: returnValue = NVRenderPathReturnValues::InvalidEnum; @@ -1726,15 +1790,16 @@ namespace render { GLenum glMissingGlyphs; switch (inHandleGlyphs) { +#if !defined(QT_OPENGL_ES) case NVRenderPathMissingGlyphs::SkipMissing: glMissingGlyphs = GL_SKIP_MISSING_GLYPH_NV; break; case NVRenderPathMissingGlyphs::UseMissing: glMissingGlyphs = GL_USE_MISSING_GLYPH_NV; break; +#endif default: QT3DS_ASSERT(false); - glMissingGlyphs = GL_SKIP_MISSING_GLYPH_NV; break; } @@ -1746,6 +1811,7 @@ namespace render { GLenum glListMode; switch (inListMode) { +#if !defined(QT_OPENGL_ES) case NVRenderPathListMode::AccumAdjacentPairs: glListMode = GL_ACCUM_ADJACENT_PAIRS_NV; break; @@ -1755,9 +1821,9 @@ namespace render { case NVRenderPathListMode::FirstToRest: glListMode = GL_FIRST_TO_REST_NV; break; +#endif default: QT3DS_ASSERT(false); - glListMode = GL_ACCUM_ADJACENT_PAIRS_NV; break; } @@ -1769,6 +1835,7 @@ namespace render { GLenum glCoverMode; switch (inMode) { +#if !defined(QT_OPENGL_ES) case NVRenderPathCoverMode::ConvexHull: glCoverMode = GL_CONVEX_HULL_NV; break; @@ -1784,9 +1851,9 @@ namespace render { case NVRenderPathCoverMode::PathStrokeCover: glCoverMode = GL_PATH_STROKE_COVER_MODE_NV; break; +#endif default: QT3DS_ASSERT(false); - glCoverMode = GL_BOUNDING_BOX_NV; break; } @@ -1815,11 +1882,11 @@ namespace render { return GL_3_BYTES_NV; case NVRenderPathFormatType::Bytes4: return GL_4_BYTES_NV; -#endif case NVRenderPathFormatType::Utf8: return GL_UTF8_NV; case NVRenderPathFormatType::Utf16: return GL_UTF16_NV; +#endif default: break; } @@ -1831,12 +1898,12 @@ namespace render { { QT3DSU32 value = flags; GLbitfield retval = 0; - +#if !defined(QT_OPENGL_ES) if (value & NVRenderPathFontStyleValues::Bold) retval |= GL_BOLD_BIT_NV; if (value & NVRenderPathFontStyleValues::Italic) retval |= GL_ITALIC_BIT_NV; - +#endif QT3DS_ASSERT(retval || !value); return retval; } @@ -1846,6 +1913,7 @@ namespace render { switch (value) { case NVRenderPathTransformType::NoTransform: return GL_NONE; +#if !defined(QT_OPENGL_ES) case NVRenderPathTransformType::TranslateX: return GL_TRANSLATE_X_NV; case NVRenderPathTransformType::TranslateY: @@ -1862,6 +1930,7 @@ namespace render { return GL_TRANSPOSE_AFFINE_2D_NV; case NVRenderPathTransformType::TransposeAffine3D: return GL_TRANSPOSE_AFFINE_3D_NV; +#endif default: break; } @@ -1873,7 +1942,7 @@ namespace render { { QT3DSU32 value = flags; GLbitfield retval = 0; - +#if !defined(QT_OPENGL_ES) if (value & NVRenderPathGlyphFontMetricValues::GlyphWidth) retval |= GL_GLYPH_WIDTH_BIT_NV; if (value & NVRenderPathGlyphFontMetricValues::GlyphHeight) @@ -1921,7 +1990,7 @@ namespace render { retval |= GL_FONT_HAS_KERNING_BIT_NV; if (value & NVRenderPathGlyphFontMetricValues::FontNumGlyphIndices) retval |= GL_FONT_NUM_GLYPH_INDICES_BIT_NV; - +#endif QT3DS_ASSERT(retval || !value); return retval; } diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h index 088a279f..7147b341 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h @@ -156,7 +156,7 @@ namespace render { protected: NVRenderBackendMiscStateGL *m_pCurrentMiscState; ///< this holds the current misc state -#if defined(QT_OPENGL_ES) +#if defined(QT_OPENGL_ES_2) Qt3DSOpenGLES2Extensions *m_qt3dsExtensions; #else QOpenGLExtension_ARB_timer_query *m_timerExtension; diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h index 6cde45ef..9048a9c4 100644 --- a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h +++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h @@ -46,6 +46,9 @@ #define NVRENDER_BACKEND_UNUSED(arg) (void)arg; +// Enable this to log opengl errors instead of an assert +//#define RENDER_BACKEND_LOG_GL_ERRORS + namespace qt3ds { namespace render { @@ -492,7 +495,8 @@ namespace render { eastl::string &errorMessage, bool binary); virtual const char *getVersionString(); virtual const char *getVendorString(); - virtual const char *geRendererString(); + virtual const char *getRendererString(); + virtual const char *getExtensionString(); virtual void setAndInspectHardwareCaps(); @@ -502,7 +506,7 @@ namespace render { NVScopedRefCounted<qt3ds::foundation::IStringTable> m_StringTable; ///< pointer to a string table GLConversion m_Conversion; ///< Class for conversion from base type to GL types - nvvector<TContextStr> m_Extensions; ///< contains the OpenGL extension string + QStringList m_extensions; ///< contains the OpenGL extension string QT3DSI32 m_MaxAttribCount; ///< Maximum attributes which can be used nvvector<GLenum> m_DrawBuffersArray; ///< Contains the drawbuffer enums QSurfaceFormat m_format; @@ -512,7 +516,11 @@ namespace render { NVRenderBackendDepthStencilStateGL *m_pCurrentDepthStencilState; ///< this holds the current depth stencil state +#ifdef RENDER_BACKEND_LOG_GL_ERRORS + void checkGLError(const char *function, const char *file, const unsigned int line) const; +#else void checkGLError() const; +#endif QOpenGLFunctions *m_glFunctions; QOpenGLExtraFunctions *m_glExtraFunctions; }; diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp index 33c8f271..b404a972 100644 --- a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp +++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp @@ -86,7 +86,7 @@ namespace render { NVRenderConstantBuffer::~NVRenderConstantBuffer() { - // chekc if we should release memory + // check if we should release memory if (m_ShadowCopy.size()) { m_Foundation.getAllocator().deallocate(m_ShadowCopy.begin()); } diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Q3DSRenderBackendGLES2.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Q3DSRenderBackendGLES2.cpp new file mode 100644 index 00000000..fbe75b6f --- /dev/null +++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Q3DSRenderBackendGLES2.cpp @@ -0,0 +1,873 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "render/backends/gl/Q3DSRenderBackendGLES2.h" +#include "render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h" +#include "render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h" +#include "render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h" + +#ifdef RENDER_BACKEND_LOG_GL_ERRORS +#define RENDER_LOG_ERROR_PARAMS(x) checkGLError(#x, __FILE__, __LINE__) +#else +#define RENDER_LOG_ERROR_PARAMS(x) checkGLError() +#endif + +#if defined(QT_OPENGL_ES) +#define GL_CALL_TIMER_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_TESSELATION_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_MULTISAMPLE_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_EXTENSION_FUNCTION(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); +#else +#define GL_CALL_TIMER_EXT(x) +#define GL_CALL_TESSELATION_EXT(x) +#define GL_CALL_MULTISAMPLE_EXT(x) +#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_EXTENSION_FUNCTION(x) +#endif + +#ifndef GL_DEPTH_STENCIL_OES +#define GL_DEPTH_STENCIL_OES 0x84F9 +#endif + +namespace qt3ds { +namespace render { + +/// constructor +NVRenderBackendGLES2Impl::NVRenderBackendGLES2Impl(NVFoundationBase &fnd, + qt3ds::foundation::IStringTable &stringTable, + const QSurfaceFormat &format) + : NVRenderBackendGLBase(fnd, stringTable, format) +{ + QString exts3tc = QStringLiteral("GL_EXT_texture_compression_s3tc"); + QString extsAniso = QStringLiteral("GL_EXT_texture_filter_anisotropic"); + QString extsTexSwizzle = QStringLiteral("GL_ARB_texture_swizzle"); + QString extsFPRenderTarget = QStringLiteral("GL_EXT_color_buffer_float"); + QString extsTimerQuery = QStringLiteral("GL_EXT_timer_query"); + QString extsGpuShader5 = QStringLiteral("EXT_gpu_shader5"); + QString extDepthTexture = QStringLiteral("GL_ANGLE_depth_texture"); + QString extvao = QStringLiteral("GL_OES_vertex_array_object"); + QString extStdDd = QStringLiteral("GL_OES_standard_derivatives"); + QString extTexLod = QStringLiteral("GL_EXT_shader_texture_lod"); + + const char *languageVersion = GetShadingLanguageVersion(); + qCInfo(TRACE_INFO, "GLSL version: %s", languageVersion); + + eastl::string apiVersion(getVersionString()); + qCInfo(TRACE_INFO, "GL version: %s", apiVersion.c_str()); + + eastl::string apiVendor(getVendorString()); + qCInfo(TRACE_INFO, "HW vendor: %s", apiVendor.c_str()); + + eastl::string apiRenderer(getRendererString()); + qCInfo(TRACE_INFO, "Vendor renderer: %s", apiRenderer.c_str()); + + // clear support bits + m_backendSupport.caps.u32Values = 0; + + const char *extensions = getExtensionString(); + m_extensions = QString::fromLocal8Bit(extensions).split(" "); + + // get extension count + GLint numExtensions = m_extensions.size(); + + for (QT3DSI32 i = 0; i < numExtensions; i++) { + + const QString &extensionString = m_extensions.at(i); + + // search for extension + if (!m_backendSupport.caps.bits.bDXTImagesSupported + && exts3tc.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bDXTImagesSupported = true; + } else if (!m_backendSupport.caps.bits.bAnistropySupported + && extsAniso.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bAnistropySupported = true; + } else if (!m_backendSupport.caps.bits.bFPRenderTargetsSupported + && extsFPRenderTarget.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bFPRenderTargetsSupported = true; + } else if (!m_backendSupport.caps.bits.bTimerQuerySupported + && extsTimerQuery.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bTimerQuerySupported = true; + } else if (!m_backendSupport.caps.bits.bGPUShader5ExtensionSupported + && extsGpuShader5.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bGPUShader5ExtensionSupported = true; + } else if (!m_backendSupport.caps.bits.bTextureSwizzleSupported + && extsTexSwizzle.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bTextureSwizzleSupported = true; + } else if (!m_backendSupport.caps.bits.bDepthStencilSupported + && extDepthTexture.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bDepthStencilSupported = true; + } else if (!m_backendSupport.caps.bits.bVertexArrayObjectSupported + && extvao.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bVertexArrayObjectSupported = true; + } else if (!m_backendSupport.caps.bits.bStandardDerivativesSupported + && extStdDd.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bStandardDerivativesSupported = true; + } else if (!m_backendSupport.caps.bits.bTextureLodSupported + && extTexLod.compare(extensionString) == 0) { + m_backendSupport.caps.bits.bTextureLodSupported = true; + } + } + + qCInfo(TRACE_INFO, "OpenGL extensions: %s", extensions); + + // constant buffers support is always not true + m_backendSupport.caps.bits.bConstantBufferSupported = false; + + // query hardware + GL_CALL_EXTRA_FUNCTION(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_MaxAttribCount)); + + // internal state tracker + m_pCurrentMiscState = QT3DS_NEW(m_Foundation.getAllocator(), NVRenderBackendMiscStateGL)(); + + // finally setup caps based on device + setAndInspectHardwareCaps(); + + // Initialize extensions +#if defined(QT_OPENGL_ES) + m_qt3dsExtensions = new Qt3DSOpenGLES2Extensions; + m_qt3dsExtensions->initializeOpenGLFunctions(); +#endif +} +/// destructor +NVRenderBackendGLES2Impl::~NVRenderBackendGLES2Impl() +{ + if (m_pCurrentMiscState) + NVDelete(m_Foundation.getAllocator(), m_pCurrentMiscState); +#if defined(QT_OPENGL_ES) + if (m_qt3dsExtensions) + delete m_qt3dsExtensions; +#endif +} + +void NVRenderBackendGLES2Impl::SetMultisampledTextureData2D( + NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, size_t samples, + NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, + bool fixedsamplelocations) +{ + NVRENDER_BACKEND_UNUSED(to); + NVRENDER_BACKEND_UNUSED(target); + NVRENDER_BACKEND_UNUSED(samples); + NVRENDER_BACKEND_UNUSED(internalFormat); + NVRENDER_BACKEND_UNUSED(width); + NVRENDER_BACKEND_UNUSED(height); + NVRENDER_BACKEND_UNUSED(fixedsamplelocations); +} + +void NVRenderBackendGLES2Impl::SetTextureData3D( + NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level, + NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, size_t depth, + QT3DSI32 border, NVRenderTextureFormats::Enum format, const void *hostPtr) +{ + GLuint texID = HandleToID_cast(GLuint, size_t, to); + GLenum glTarget = m_Conversion.fromTextureTargetToGL(target); + GL_CALL_EXTRA_FUNCTION(glActiveTexture(GL_TEXTURE0)); + GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID)); + bool conversionRequired = format != internalFormat; + + NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle; + internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(), + internalFormat, swizzleMode); + + GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE; + + if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat)) { + m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat, + glformat, gltype, glInternalFormat); + } + + if (conversionRequired) { + GLenum dummy; + m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat, + gltype, dummy); + } else if (NVRenderTextureFormats::isCompressedTextureFormat(internalFormat)) { + m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat, + gltype, glInternalFormat); + glInternalFormat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat); + } else if (NVRenderTextureFormats::isDepthTextureFormat(format)) { + m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), format, glformat, + gltype, glInternalFormat); + } + + GL_CALL_EXTRA_FUNCTION(glTexImage3D(glTarget, level, glInternalFormat, (GLsizei)width, + (GLsizei)height, (GLsizei)depth, border, glformat, + gltype, hostPtr)); + + GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0)); +} + +void NVRenderBackendGLES2Impl::SetTextureData2D( + NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level, + NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border, + NVRenderTextureFormats::Enum format, const void *hostPtr) +{ + GLuint texID = HandleToID_cast(GLuint, size_t, to); + GLenum glTarget = m_Conversion.fromTextureTargetToGL(target); + GL_CALL_EXTRA_FUNCTION(glActiveTexture(GL_TEXTURE0)); + GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID)); + bool conversionRequired = format != internalFormat; + + NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle; + internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(), + internalFormat, swizzleMode); + + GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE; + + if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat)) { + m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat, + glformat, gltype, glInternalFormat); + glInternalFormat = glformat; + } + + if (conversionRequired) { + GLenum dummy; + m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat, + gltype, dummy); + } else if (NVRenderTextureFormats::isCompressedTextureFormat(internalFormat)) { + m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat, + gltype, glInternalFormat); + glInternalFormat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat); + } else if (NVRenderTextureFormats::isDepthTextureFormat(format)) { + m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), format, glformat, + gltype, glInternalFormat); + if (format == NVRenderTextureFormats::Depth24Stencil8) { + glformat = GL_DEPTH_STENCIL_OES; + gltype = GL_UNSIGNED_INT_24_8; + } + glInternalFormat = glformat; + } + + Q_ASSERT(glformat == glInternalFormat); + GL_CALL_EXTRA_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width, + (GLsizei)height, border, glformat, gltype, hostPtr)); + GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0)); +} + +void NVRenderBackendGLES2Impl::UpdateSampler( + NVRenderBackendSamplerObject /* so */, NVRenderTextureTargetType::Enum target, + NVRenderTextureMinifyingOp::Enum minFilter, NVRenderTextureMagnifyingOp::Enum magFilter, + NVRenderTextureCoordOp::Enum wrapS, NVRenderTextureCoordOp::Enum wrapT, + NVRenderTextureCoordOp::Enum wrapR, QT3DSF32 minLod, QT3DSF32 maxLod, QT3DSF32 lodBias, + NVRenderTextureCompareMode::Enum compareMode, NVRenderTextureCompareOp::Enum compareFunc, + QT3DSF32 anisotropy, QT3DSF32 *borderColor) +{ + + // Satisfy the compiler + // These are not available in GLES 3 and we don't use them right now + QT3DS_ASSERT(lodBias == 0.0); + QT3DS_ASSERT(!borderColor); + NVRENDER_BACKEND_UNUSED(lodBias); + NVRENDER_BACKEND_UNUSED(borderColor); + + GLenum glTarget = m_Conversion.fromTextureTargetToGL(target); + + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MIN_FILTER, + m_Conversion.fromTextureMinifyingOpToGL(minFilter))); + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MAG_FILTER, + m_Conversion.fromTextureMagnifyingOpToGL(magFilter))); + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_S, + m_Conversion.fromTextureCoordOpToGL(wrapS))); + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_T, + m_Conversion.fromTextureCoordOpToGL(wrapT))); + + if (m_backendSupport.caps.bits.bAnistropySupported) { + GL_CALL_EXTRA_FUNCTION(glTexParameterf(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, + anisotropy)); + } +} + +void NVRenderBackendGLES2Impl::UpdateTextureObject(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, + QT3DSI32 baseLevel, QT3DSI32 maxLevel) +{ + NVRENDER_BACKEND_UNUSED(to); + + GLenum glTarget = m_Conversion.fromTextureTargetToGL(target); + + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_BASE_LEVEL, baseLevel)); + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MAX_LEVEL, maxLevel)); +} + +void NVRenderBackendGLES2Impl::UpdateTextureSwizzle(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, + NVRenderTextureSwizzleMode::Enum swizzleMode) +{ + NVRENDER_BACKEND_UNUSED(to); + if (m_backendSupport.caps.bits.bTextureSwizzleSupported) { + GLint glSwizzle[4]; + GLenum glTarget = m_Conversion.fromTextureTargetToGL(target); + m_Conversion.NVRenderConvertSwizzleModeToGL(swizzleMode, glSwizzle); +#if defined(QT_OPENGL_ES) + // since ES3 spec has no GL_TEXTURE_SWIZZLE_RGBA set it separately + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_R, glSwizzle[0])); + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_G, glSwizzle[1])); + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_B, glSwizzle[2])); + GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_A, glSwizzle[3])); +#endif + } +} + +QT3DSU32 +NVRenderBackendGLES2Impl::GetDepthBits() const +{ + QT3DSI32 depthBits; + GL_CALL_EXTRA_FUNCTION( + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depthBits)); + + return depthBits; +} + +QT3DSU32 +NVRenderBackendGLES2Impl::GetStencilBits() const +{ + QT3DSI32 stencilBits; + GL_CALL_EXTRA_FUNCTION( + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, + &stencilBits)); + + return stencilBits; +} + +void NVRenderBackendGLES2Impl::GenerateMipMaps(NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target, + NVRenderHint::Enum /*genType*/) +{ + GLuint texID = HandleToID_cast(GLuint, size_t, to); + GLenum glTarget = m_Conversion.fromTextureTargetToGL(target); + GL_CALL_EXTRA_FUNCTION(glActiveTexture(GL_TEXTURE0)); + GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID)); + GL_CALL_EXTRA_FUNCTION(glGenerateMipmap(glTarget)); + GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0)); +} + +bool NVRenderBackendGLES2Impl::SetInputAssembler(NVRenderBackendInputAssemblerObject iao, + NVRenderBackendShaderProgramObject po) +{ + if (iao == nullptr) { + // unbind and return; + GL_CALL_EXTENSION_FUNCTION(glBindVertexArrayOES(0)); + return true; + } + + NVRenderBackendInputAssemblerGL *inputAssembler = (NVRenderBackendInputAssemblerGL *)iao; + NVRenderBackendAttributeLayoutGL *attribLayout = inputAssembler->m_attribLayout; + NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; + GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); + NVDataRef<NVRenderBackendShaderInputEntryGL> shaderAttribBuffer; + if (pProgram->m_shaderInput) + shaderAttribBuffer = pProgram->m_shaderInput->m_ShaderInputEntries; + + if ((attribLayout->m_LayoutAttribEntries.size() < shaderAttribBuffer.size()) + || (inputAssembler->m_VertexbufferHandles.size() <= attribLayout->m_MaxInputSlot)) { + return false; + } + + if (inputAssembler->m_VaoID == 0) { + // generate vao + GL_CALL_EXTENSION_FUNCTION(glGenVertexArraysOES(1, &inputAssembler->m_VaoID)); + QT3DS_ASSERT(inputAssembler->m_VaoID); + } + + if (inputAssembler->m_cachedShaderHandle != programID) { + GL_CALL_EXTENSION_FUNCTION(glBindVertexArrayOES(inputAssembler->m_VaoID)); + inputAssembler->m_cachedShaderHandle = programID; + + UICBASE_FOREACH(idx, shaderAttribBuffer.size()) + { + const NVRenderBackendShaderInputEntryGL &attrib(shaderAttribBuffer[idx]); + NVRenderBackendLayoutEntryGL *entry = + attribLayout->getEntryByName(attrib.m_AttribName); + + if (entry) { + NVRenderBackendLayoutEntryGL &entryData(*entry); + if (entryData.m_Type != attrib.m_Type + || entryData.m_NumComponents != attrib.m_NumComponents) { + qCCritical(INVALID_OPERATION, "Attrib %s dn't match vertex layout", + attrib.m_AttribName.c_str()); + QT3DS_ASSERT(false); + return false; + } else { + entryData.m_AttribIndex = attrib.m_AttribLocation; + } + } else { + qCWarning(WARNING, "Failed to Bind attribute %s", attrib.m_AttribName.c_str()); + } + } + + // disable max possible used first + // this is currently sufficient since we always re-arrange input attributes from 0 + for (QT3DSU32 i = 0; i < attribLayout->m_LayoutAttribEntries.size(); i++) + GL_CALL_EXTRA_FUNCTION(glDisableVertexAttribArray(i)); + + // setup all attribs + UICBASE_FOREACH(idx, shaderAttribBuffer.size()) + { + NVRenderBackendLayoutEntryGL *entry = + attribLayout->getEntryByName(shaderAttribBuffer[idx].m_AttribName); + if (entry) { + const NVRenderBackendLayoutEntryGL &entryData(*entry); + GLuint id = HandleToID_cast( + GLuint, size_t, + inputAssembler->m_VertexbufferHandles.mData[entryData.m_InputSlot]); + GL_CALL_EXTRA_FUNCTION(glBindBuffer(GL_ARRAY_BUFFER, id)); + GL_CALL_EXTRA_FUNCTION(glEnableVertexAttribArray(entryData.m_AttribIndex)); + GLuint offset = inputAssembler->m_offsets[entryData.m_InputSlot]; + GLuint stride = inputAssembler->m_strides[entryData.m_InputSlot]; + GL_CALL_EXTRA_FUNCTION(glVertexAttribPointer( + entryData.m_AttribIndex, entryData.m_NumComponents, GL_FLOAT, GL_FALSE, + stride, (const void *)(entryData.m_Offset + offset))); + + } else { + GL_CALL_EXTRA_FUNCTION(glDisableVertexAttribArray(idx)); + } + } + + // setup index buffer. + if (inputAssembler->m_IndexbufferHandle) { + GL_CALL_EXTRA_FUNCTION(glBindBuffer( + GL_ELEMENT_ARRAY_BUFFER, + HandleToID_cast(GLuint, size_t, inputAssembler->m_IndexbufferHandle))); + } else { + GL_CALL_EXTRA_FUNCTION(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + } + } else { + GL_CALL_EXTENSION_FUNCTION(glBindVertexArrayOES(inputAssembler->m_VaoID)); + } +#ifdef _DEBUG + if (inputAssembler->m_VaoID) { + UICBASE_FOREACH(idx, shaderAttribBuffer.size()) + { + const NVRenderBackendShaderInputEntryGL &attrib(shaderAttribBuffer[idx]); + NVRenderBackendLayoutEntryGL *entry = + attribLayout->getEntryByName(attrib.m_AttribName); + + if (entry) { + NVRenderBackendLayoutEntryGL &entryData(*entry); + if (entryData.m_Type != attrib.m_Type + || entryData.m_NumComponents != attrib.m_NumComponents + || entryData.m_AttribIndex != attrib.m_AttribLocation) { + qCCritical(INVALID_OPERATION, "Attrib %s dn't match vertex layout", + attrib.m_AttribName.c_str()); + QT3DS_ASSERT(false); + } + } else { + qCWarning(WARNING, "Failed to Bind attribute %s", attrib.m_AttribName.c_str()); + } + } + } +#endif // _DEBUG + + return true; +} + +void NVRenderBackendGLES2Impl::SetDrawBuffers(NVRenderBackendRenderTargetObject rto, + NVConstDataRef<QT3DSI32> inDrawBufferSet) +{ + NVRENDER_BACKEND_UNUSED(rto); + + m_DrawBuffersArray.clear(); + + for (QT3DSU32 idx = 0, end = inDrawBufferSet.size(); idx < end; ++idx) { + if (inDrawBufferSet[idx] < 0) + m_DrawBuffersArray.push_back(GL_NONE); + else + m_DrawBuffersArray.push_back(GL_COLOR_ATTACHMENT0 + inDrawBufferSet[idx]); + } + + GL_CALL_EXTRA_FUNCTION(glDrawBuffers((int)m_DrawBuffersArray.size(), + m_DrawBuffersArray.data())); +} + +void NVRenderBackendGLES2Impl::SetReadBuffer(NVRenderBackendRenderTargetObject rto, + NVReadFaces::Enum inReadFace) +{ + NVRENDER_BACKEND_UNUSED(rto); + +} + +void NVRenderBackendGLES2Impl::RenderTargetAttach(NVRenderBackendRenderTargetObject, + NVRenderFrameBufferAttachments::Enum attachment, + NVRenderBackendTextureObject to, QT3DSI32 level, + QT3DSI32 layer) +{ + Q_ASSERT(false); +} + +void NVRenderBackendGLES2Impl::BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, + QT3DSI32 srcY1, QT3DSI32 dstX0, QT3DSI32 dstY0, + QT3DSI32 dstX1, QT3DSI32 dstY1, + NVRenderClearFlags flags, + NVRenderTextureMagnifyingOp::Enum filter) +{ + GL_CALL_EXTRA_FUNCTION(glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, + dstY1, + m_Conversion.fromClearFlagsToGL(flags), + m_Conversion.fromTextureMagnifyingOpToGL(filter))); +} + + +NVRenderBackend::NVRenderBackendRenderTargetObject NVRenderBackendGLES2Impl::CreateRenderTarget() +{ + GLuint fboID = 0; + GL_CALL_EXTRA_FUNCTION(glGenFramebuffers(1, &fboID)); + return (NVRenderBackend::NVRenderBackendRenderTargetObject)fboID; +} + +void NVRenderBackendGLES2Impl::ReleaseRenderTarget(NVRenderBackendRenderTargetObject rto) +{ + GLuint fboID = HandleToID_cast(GLuint, size_t, rto); + + if (fboID) + GL_CALL_EXTRA_FUNCTION(glDeleteFramebuffers(1, &fboID)); +} + +void NVRenderBackendGLES2Impl::RenderTargetAttach(NVRenderBackendRenderTargetObject /* rto */, + NVRenderFrameBufferAttachments::Enum attachment, + NVRenderBackendRenderbufferObject rbo) +{ + // rto must be the current render target + GLuint rbID = HandleToID_cast(GLuint, size_t, rbo); + + GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment); + + GL_CALL_EXTRA_FUNCTION(glFramebufferRenderbuffer(GL_FRAMEBUFFER, glAttach, GL_RENDERBUFFER, + rbID)); +} + +void NVRenderBackendGLES2Impl::RenderTargetAttach(NVRenderBackendRenderTargetObject /* rto */, + NVRenderFrameBufferAttachments::Enum attachment, + NVRenderBackendTextureObject to, + NVRenderTextureTargetType::Enum target) +{ + // rto must be the current render target + GLuint texID = HandleToID_cast(GLuint, size_t, to); + + QT3DS_ASSERT(target == NVRenderTextureTargetType::Texture2D + || m_backendSupport.caps.bits.bMsTextureSupported); + + GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment); + GLenum glTarget = m_Conversion.fromTextureTargetToGL(target); + + if (attachment == NVRenderFrameBufferAttachments::DepthStencil) { + GL_CALL_EXTRA_FUNCTION(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + glTarget, texID, 0)); + GL_CALL_EXTRA_FUNCTION(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + glTarget, texID, 0)); + } else { + GL_CALL_EXTRA_FUNCTION(glFramebufferTexture2D(GL_FRAMEBUFFER, glAttach, glTarget, texID, + 0)); + } +} + +void NVRenderBackendGLES2Impl::SetRenderTarget(NVRenderBackendRenderTargetObject rto) +{ + GLuint fboID = HandleToID_cast(GLuint, size_t, rto); + + GL_CALL_EXTRA_FUNCTION(glBindFramebuffer(GL_FRAMEBUFFER, fboID)); +} + +void NVRenderBackendGLES2Impl::SetReadTarget(NVRenderBackendRenderTargetObject rto) +{ + GLuint fboID = HandleToID_cast(GLuint, size_t, rto); + + GL_CALL_EXTRA_FUNCTION(glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID)); +} + +bool NVRenderBackendGLES2Impl::RenderTargetIsValid(NVRenderBackendRenderTargetObject /* rto */) +{ + GLenum completeStatus = GL_CALL_EXTRA_FUNCTION(glCheckFramebufferStatus(GL_FRAMEBUFFER)); + switch (completeStatus) { +#define HANDLE_INCOMPLETE_STATUS(x) \ + case x: \ + qCCritical(INTERNAL_ERROR, "Framebuffer is not complete: %s", #x); \ + return false; + HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) + HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS) + HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) + HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_UNSUPPORTED) + #undef HANDLE_INCOMPLETE_STATUS + } + return true; +} + +NVRenderBackend::NVRenderBackendRenderbufferObject +NVRenderBackendGLES2Impl::CreateRenderbuffer(NVRenderRenderBufferFormats::Enum storageFormat, + size_t width, size_t height) +{ + GLuint bufID = 0; + + GL_CALL_EXTRA_FUNCTION(glGenRenderbuffers(1, &bufID)); + GL_CALL_EXTRA_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, bufID)); + GL_CALL_EXTRA_FUNCTION(glRenderbufferStorage(GL_RENDERBUFFER, + GLConversion::fromRenderBufferFormatsToRenderBufferGL(storageFormat), + (GLsizei)width, (GLsizei)height)); + + // check for error + GLenum error = m_glFunctions->glGetError(); + if (error != GL_NO_ERROR) { + qCCritical(GL_ERROR, GLConversion::processGLError(error)); + QT3DS_ASSERT(false); + GL_CALL_EXTRA_FUNCTION(glDeleteRenderbuffers(1, &bufID)); + bufID = 0; + } + + GL_CALL_EXTRA_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, 0)); + + return (NVRenderBackend::NVRenderBackendRenderbufferObject)bufID; +} + +void NVRenderBackendGLES2Impl::ReleaseRenderbuffer(NVRenderBackendRenderbufferObject rbo) +{ + GLuint bufID = HandleToID_cast(GLuint, size_t, rbo); + + if (bufID) + GL_CALL_EXTRA_FUNCTION(glDeleteRenderbuffers(1, &bufID)); +} + +bool NVRenderBackendGLES2Impl::ResizeRenderbuffer(NVRenderBackendRenderbufferObject rbo, + NVRenderRenderBufferFormats::Enum storageFormat, + size_t width, size_t height) +{ + bool success = true; + GLuint bufID = HandleToID_cast(GLuint, size_t, rbo); + + QT3DS_ASSERT(bufID); + + GL_CALL_EXTRA_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, bufID)); + GL_CALL_EXTRA_FUNCTION(glRenderbufferStorage(GL_RENDERBUFFER, + GLConversion::fromRenderBufferFormatsToRenderBufferGL(storageFormat), + (GLsizei)width, (GLsizei)height)); + + // check for error + GLenum error = m_glFunctions->glGetError(); + if (error != GL_NO_ERROR) { + qCCritical(GL_ERROR, GLConversion::processGLError(error)); + QT3DS_ASSERT(false); + success = false; + } + + return success; +} + +void *NVRenderBackendGLES2Impl::MapBuffer(NVRenderBackendBufferObject, + NVRenderBufferBindFlags bindFlags, size_t offset, + size_t length, NVRenderBufferAccessFlags accessFlags) +{ + void *ret = nullptr; + ret = GL_CALL_EXTRA_FUNCTION( + glMapBufferRange(m_Conversion.fromBindBufferFlagsToGL(bindFlags), offset, + length, m_Conversion.fromBufferAccessBitToGL(accessFlags))); + + return ret; +} + +bool NVRenderBackendGLES2Impl::UnmapBuffer(NVRenderBackendBufferObject, + NVRenderBufferBindFlags bindFlags) +{ + GLboolean ret; + + ret = GL_CALL_EXTRA_FUNCTION(glUnmapBuffer(m_Conversion.fromBindBufferFlagsToGL(bindFlags))); + + return (ret) ? true : false; +} + +QT3DSI32 NVRenderBackendGLES2Impl::GetConstantBufferCount(NVRenderBackendShaderProgramObject po) +{ + QT3DS_ASSERT(po); + GLint numUniformBuffers = 0; + if (GetRenderBackendCap(NVRenderBackendCaps::ConstantBuffer)) { + NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; + GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); + + GL_CALL_EXTRA_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_UNIFORM_BLOCKS, + &numUniformBuffers)); + } + return numUniformBuffers; +} + +QT3DSI32 NVRenderBackendGLES2Impl::GetConstantBufferInfoByID( + NVRenderBackendShaderProgramObject po, + QT3DSU32 id, QT3DSU32 nameBufSize, + QT3DSI32 *paramCount, QT3DSI32 *bufferSize, + QT3DSI32 *length, char *nameBuf) +{ + QT3DS_ASSERT(po); + QT3DS_ASSERT(length); + QT3DS_ASSERT(nameBuf); + + NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; + GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); + GLuint blockIndex = GL_INVALID_INDEX; + + GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockName(programID, id, nameBufSize, length, + nameBuf)); + + if (*length > 0) { + blockIndex = GL_CALL_EXTRA_FUNCTION(glGetUniformBlockIndex(programID, nameBuf)); + if (blockIndex != GL_INVALID_INDEX) { + GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, blockIndex, + GL_UNIFORM_BLOCK_DATA_SIZE, bufferSize)); + GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, blockIndex, + GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, paramCount)); + } + } + + return blockIndex; +} + +void NVRenderBackendGLES2Impl::GetConstantBufferParamIndices(NVRenderBackendShaderProgramObject po, + QT3DSU32 id, QT3DSI32 *indices) +{ + QT3DS_ASSERT(po); + QT3DS_ASSERT(indices); + + NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; + GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); + + if (indices) { + GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, id, + GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, + indices)); + } +} + +void NVRenderBackendGLES2Impl::GetConstantBufferParamInfoByIndices( + NVRenderBackendShaderProgramObject po, QT3DSU32 count, QT3DSU32 *indices, QT3DSI32 *type, + QT3DSI32 *size, QT3DSI32 *offset) +{ + QT3DS_ASSERT(po); + QT3DS_ASSERT(count); + QT3DS_ASSERT(indices); + + NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; + GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); + + if (count && indices) { + if (type) { + GL_CALL_EXTRA_FUNCTION(glGetActiveUniformsiv(programID, count, indices, + GL_UNIFORM_TYPE, type)); + // convert to UIC types + UICBASE_FOREACH(idx, count) + { + type[idx] = m_Conversion.fromShaderGLToPropertyDataTypes(type[idx]); + } + } + if (size) { + GL_CALL_EXTRA_FUNCTION(glGetActiveUniformsiv(programID, count, indices, + GL_UNIFORM_SIZE, size)); + } + if (offset) { + GL_CALL_EXTRA_FUNCTION( + glGetActiveUniformsiv(programID, count, indices, GL_UNIFORM_OFFSET, offset)); + } + } +} + +void NVRenderBackendGLES2Impl::ProgramSetConstantBlock(NVRenderBackendShaderProgramObject po, + QT3DSU32 blockIndex, QT3DSU32 binding) +{ + NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; + GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); + + GL_CALL_EXTRA_FUNCTION(glUniformBlockBinding(programID, blockIndex, binding)); +} + +void NVRenderBackendGLES2Impl::ProgramSetConstantBuffer(QT3DSU32 index, + NVRenderBackendBufferObject bo) +{ + QT3DS_ASSERT(bo); + + GLuint bufID = HandleToID_cast(GLuint, size_t, bo); + GL_CALL_EXTRA_FUNCTION(glBindBufferBase(GL_UNIFORM_BUFFER, index, bufID)); +} + +NVRenderBackend::NVRenderBackendQueryObject NVRenderBackendGLES2Impl::CreateQuery() +{ + QT3DSU32 glQueryID = 0; + + return (NVRenderBackendQueryObject)glQueryID; +} + +void NVRenderBackendGLES2Impl::ReleaseQuery(NVRenderBackendQueryObject) +{ + +} + +void NVRenderBackendGLES2Impl::BeginQuery(NVRenderBackendQueryObject, + NVRenderQueryType::Enum) +{ + +} + +void NVRenderBackendGLES2Impl::EndQuery(NVRenderBackendQueryObject, NVRenderQueryType::Enum) +{ + +} + +void NVRenderBackendGLES2Impl::GetQueryResult(NVRenderBackendQueryObject, + NVRenderQueryResultType::Enum, + QT3DSU32 *) +{ + +} + +void NVRenderBackendGLES2Impl::GetQueryResult(NVRenderBackendQueryObject, + NVRenderQueryResultType::Enum, + QT3DSU64 *) +{ + +} + +void NVRenderBackendGLES2Impl::SetQueryTimer(NVRenderBackendQueryObject) +{ + +} + +NVRenderBackend::NVRenderBackendSyncObject +NVRenderBackendGLES2Impl::CreateSync(NVRenderSyncType::Enum, NVRenderSyncFlags) +{ + GLsync syncID = 0; + return NVRenderBackendSyncObject(syncID); +} + +void NVRenderBackendGLES2Impl::ReleaseSync(NVRenderBackendSyncObject) +{ + +} + +void NVRenderBackendGLES2Impl::WaitSync(NVRenderBackendSyncObject, NVRenderCommandFlushFlags, + QT3DSU64) +{ + +} +} +} diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp index 71c4e41a..ac493c68 100644 --- a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp +++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp @@ -151,6 +151,18 @@ bool Qt3DSOpenGLES2Extensions::initializeOpenGLFunctions() GLenum, GLsizei, GLenum, const void *, GLuint, GLfloat, GLfloat, GLenum, GLfloat *)>( context->getProcAddress("glGetPathSpacingNV")); + d->BindVertexArrayOES = reinterpret_cast<void (QOPENGLF_APIENTRYP) + (GLuint)>( + context->getProcAddress("glBindVertexArrayOES")); + d->DeleteVertexArraysOES = reinterpret_cast<void (QOPENGLF_APIENTRYP) + (GLsizei, const GLuint *)>( + context->getProcAddress("glDeleteVertexArraysOES")); + d->GenVertexArraysOES = reinterpret_cast<void (QOPENGLF_APIENTRYP) + (GLsizei, GLuint *)>( + context->getProcAddress("glGenVertexArraysOES")); + d->IsVertexArrayOES = reinterpret_cast<GLboolean (QOPENGLF_APIENTRYP) + (GLuint)>( + context->getProcAddress("glIsVertexArrayOES")); #endif Qt3DSOpenGLExtensions::initializeOpenGLFunctions(); return true; diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp index c8a99cb2..8d9640bb 100644 --- a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp +++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp @@ -33,15 +33,21 @@ #include "render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h" #include "render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h" -#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; checkGLError(); +#ifdef RENDER_BACKEND_LOG_GL_ERRORS +#define RENDER_LOG_ERROR_PARAMS(x) checkGLError(#x, __FILE__, __LINE__) +#else +#define RENDER_LOG_ERROR_PARAMS(x) checkGLError() +#endif + +#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; RENDER_LOG_ERROR_PARAMS(x); #if defined(QT_OPENGL_ES) -#define GL_CALL_TIMER_EXT(x) m_qt3dsExtensions->x; checkGLError(); -#define GL_CALL_TESSELATION_EXT(x) m_qt3dsExtensions->x; checkGLError(); +#define GL_CALL_TIMER_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_TESSELATION_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); #else -#define GL_CALL_TIMER_EXT(x) m_timerExtension->x; checkGLError(); -#define GL_CALL_TESSELATION_EXT(x) m_tessellationShader->x; checkGLError(); -#define GL_CALL_MULTISAMPLE_EXT(x) m_multiSample->x; checkGLError(); +#define GL_CALL_TIMER_EXT(x) m_timerExtension->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_TESSELATION_EXT(x) m_tessellationShader->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_MULTISAMPLE_EXT(x) m_multiSample->x; RENDER_LOG_ERROR_PARAMS(x); #endif namespace qt3ds { @@ -71,7 +77,7 @@ namespace render { eastl::string apiVendor(getVendorString()); qCInfo(TRACE_INFO, "HW vendor: %s", apiVendor.c_str()); - eastl::string apiRenderer(geRendererString()); + eastl::string apiRenderer(getRendererString()); qCInfo(TRACE_INFO, "Vendor renderer: %s", apiRenderer.c_str()); // clear support bits @@ -85,11 +91,8 @@ namespace render { for (QT3DSI32 i = 0; i < numExtensions; i++) { char *extensionString = (char *)GL_CALL_EXTRA_FUNCTION(glGetStringi(GL_EXTENSIONS, i)); - const TContextStr::value_type *thePtr = - reinterpret_cast<TContextStr::value_type *>(extensionString); - m_Extensions.push_back( - TContextStr(ForwardingAllocator(m_Foundation.getAllocator(), "ExtensionStr"))); - m_Extensions.back().assign(thePtr); + + m_extensions.push_back(QString::fromLocal8Bit(extensionString)); if (extensionBuffer.size()) extensionBuffer.append(" "); @@ -123,6 +126,9 @@ namespace render { m_backendSupport.caps.bits.bDepthStencilSupported = true; // constant buffers support is always true m_backendSupport.caps.bits.bConstantBufferSupported = true; + m_backendSupport.caps.bits.bStandardDerivativesSupported = true; + m_backendSupport.caps.bits.bVertexArrayObjectSupported = true; + m_backendSupport.caps.bits.bTextureLodSupported = true; if (!isESCompatible()) { // render to float textures is always supported on none ES systems which support >=GL3 @@ -143,7 +149,7 @@ namespace render { setAndInspectHardwareCaps(); // Initialize extensions -#if defined(QT_OPENGL_ES) +#if defined(QT_OPENGL_ES_2) m_qt3dsExtensions = new Qt3DSOpenGLES2Extensions; m_qt3dsExtensions->initializeOpenGLFunctions(); #else @@ -162,7 +168,7 @@ namespace render { { if (m_pCurrentMiscState) NVDelete(m_Foundation.getAllocator(), m_pCurrentMiscState); -#if !defined(QT_OPENGL_ES) +#if !defined(QT_OPENGL_ES_2) if (m_timerExtension) delete m_timerExtension; if (m_tessellationShader) @@ -393,7 +399,9 @@ namespace render { && m_pCurrentMiscState->m_PatchVertexCount != inputAssembler->m_PatchVertexCount) { m_pCurrentMiscState->m_PatchVertexCount = inputAssembler->m_PatchVertexCount; #if defined(QT_OPENGL_ES) +#if !defined (QT_OPENGL_ES_2) GL_CALL_TESSELATION_EXT(glPatchParameteriEXT(GL_PATCH_VERTICES, inputAssembler->m_PatchVertexCount)); +#endif #else GL_CALL_TESSELATION_EXT(glPatchParameteri(GL_PATCH_VERTICES, inputAssembler->m_PatchVertexCount)); #endif @@ -736,7 +744,7 @@ namespace render { if (m_backendSupport.caps.bits.bTimerQuerySupported) { GLuint queryID = HandleToID_cast(GLuint, size_t, qo); #if defined(QT_OPENGL_ES) - GL_CALL_TIMER_EXT(glQueryCounterEXT(queryID, GL_TIMESTAMP)); + GL_CALL_TIMER_EXT(glQueryCounterEXT(queryID, GL_TIMESTAMP_EXT)); #else GL_CALL_TIMER_EXT(glQueryCounter(queryID, GL_TIMESTAMP)); #endif diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp index ef383f6d..467534f5 100644 --- a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp +++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp @@ -34,15 +34,25 @@ #define NVRENDER_BACKEND_UNUSED(arg) (void)arg; -#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; checkGLError(); +#ifdef RENDER_BACKEND_LOG_GL_ERRORS +#define RENDER_LOG_ERROR_PARAMS(x) checkGLError(#x, __FILE__, __LINE__) +#else +#define RENDER_LOG_ERROR_PARAMS(x) checkGLError() +#endif + +#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; RENDER_LOG_ERROR_PARAMS(x); #if defined(QT_OPENGL_ES) -#define GL_CALL_NVPATH_EXT(x) m_qt3dsExtensions->x; checkGLError(); -#define GL_CALL_QT3DS_EXT(x) m_qt3dsExtensions->x; checkGLError(); +#define GL_CALL_NVPATH_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_QT3DS_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); #else -#define GL_CALL_NVPATH_EXT(x) m_nvPathRendering->x; checkGLError(); -#define GL_CALL_DIRECTSTATE_EXT(x) m_directStateAccess->x; checkGLError(); -#define GL_CALL_QT3DS_EXT(x) m_qt3dsExtensions->x; checkGLError(); +#define GL_CALL_NVPATH_EXT(x) m_nvPathRendering->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_DIRECTSTATE_EXT(x) m_directStateAccess->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_QT3DS_EXT(x) m_qt3dsExtensions->x; RENDER_LOG_ERROR_PARAMS(x); +#endif + +#ifndef GL_GEOMETRY_SHADER_EXT +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 #endif namespace qt3ds { @@ -233,8 +243,11 @@ namespace render { NVRenderBackendGL4Impl::CreateTessControlShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) { +#if !defined(QT_OPENGL_ES) GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_TESS_CONTROL_SHADER)); - +#else + GLuint shaderID = 0; +#endif if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) { GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID)); shaderID = 0; @@ -247,7 +260,11 @@ namespace render { NVRenderBackendGL4Impl::CreateTessEvaluationShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) { +#if !defined(QT_OPENGL_ES) GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_TESS_EVALUATION_SHADER)); +#else + GLuint shaderID = 0; +#endif if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) { GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID)); @@ -307,9 +324,11 @@ namespace render { NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); +#if defined(GL_VERSION_4_3) || defined (QT_OPENGL_ES_3_1) if (m_backendSupport.caps.bits.bProgramInterfaceSupported) GL_CALL_EXTRA_FUNCTION(glGetProgramInterfaceiv(programID, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numStorageBuffers)); +#endif return numStorageBuffers; } @@ -329,7 +348,7 @@ namespace render { NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); - +#if defined(GL_VERSION_4_3) || defined (QT_OPENGL_ES_3_1) if (m_backendSupport.caps.bits.bProgramInterfaceSupported) { GL_CALL_EXTRA_FUNCTION(glGetProgramResourceName(programID, GL_SHADER_STORAGE_BLOCK, id, nameBufSize, length, nameBuf)); @@ -351,14 +370,17 @@ namespace render { *paramCount = params[2]; } } +#endif return bufferIndex; } void NVRenderBackendGL4Impl::ProgramSetStorageBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) { +#if defined(GL_VERSION_4_3) || defined (QT_OPENGL_ES_3_1) GL_CALL_EXTRA_FUNCTION( glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, HandleToID_cast(GLuint, size_t, bo))); +#endif } QT3DSI32 NVRenderBackendGL4Impl::GetAtomicCounterBufferCount(NVRenderBackendShaderProgramObject po) @@ -367,10 +389,11 @@ namespace render { QT3DS_ASSERT(po); NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); - +#if defined(GL_VERSION_4_3) || defined (QT_OPENGL_ES_3_1) if (m_backendSupport.caps.bits.bProgramInterfaceSupported) GL_CALL_EXTRA_FUNCTION(glGetProgramInterfaceiv(programID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numAtomicCounterBuffers)); +#endif return numAtomicCounterBuffers; } @@ -390,7 +413,7 @@ namespace render { NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po; GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID); - +#if defined(GL_VERSION_4_3) || defined (QT_OPENGL_ES_3_1) if (m_backendSupport.caps.bits.bProgramInterfaceSupported) { { #define QUERY_COUNT 3 @@ -419,14 +442,17 @@ namespace render { length, nameBuf)); } } +#endif return bufferIndex; } void NVRenderBackendGL4Impl::ProgramSetAtomicCounterBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) { +#if defined(GL_VERSION_4_3) || defined (QT_OPENGL_ES_3_1) GL_CALL_EXTRA_FUNCTION( glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, index, HandleToID_cast(GLuint, size_t, bo))); +#endif } void NVRenderBackendGL4Impl::SetConstantValue(NVRenderBackendShaderProgramObject po, QT3DSU32 id, @@ -494,13 +520,15 @@ namespace render { NVRenderBackendGL4Impl::CreateComputeShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) { - GLuint shaderID = m_glExtraFunctions->glCreateShader(GL_COMPUTE_SHADER); + GLuint shaderID = 0; +#if defined(GL_VERSION_4_3) || defined (QT_OPENGL_ES_3_1) + shaderID = m_glExtraFunctions->glCreateShader(GL_COMPUTE_SHADER); if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) { GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID)); shaderID = 0; } - +#endif return (NVRenderBackend::NVRenderBackendComputeShaderObject)shaderID; } @@ -583,35 +611,43 @@ namespace render { NVRenderBackendGL4Impl::GetPathObjectBoundingBox(NVRenderBackendPathObject inPathObject) { float data[4]; +#if defined(GL_NV_path_rendering) GL_CALL_NVPATH_EXT(glGetPathParameterfvNV( HandleToID_cast(GLuint, size_t, inPathObject), GL_PATH_OBJECT_BOUNDING_BOX_NV, data)); +#endif return NVBounds3(QT3DSVec3(data[0], data[1], 0.0f), QT3DSVec3(data[2], data[3], 0.0f)); } NVBounds3 NVRenderBackendGL4Impl::GetPathObjectFillBox(NVRenderBackendPathObject inPathObject) { float data[4]; +#if defined(GL_NV_path_rendering) GL_CALL_NVPATH_EXT(glGetPathParameterfvNV( HandleToID_cast(GLuint, size_t, inPathObject), GL_PATH_FILL_BOUNDING_BOX_NV, data)); +#endif return NVBounds3(QT3DSVec3(data[0], data[1], 0.0f), QT3DSVec3(data[2], data[3], 0.0f)); } NVBounds3 NVRenderBackendGL4Impl::GetPathObjectStrokeBox(NVRenderBackendPathObject inPathObject) { float data[4]; +#if defined(GL_NV_path_rendering) GL_CALL_NVPATH_EXT(glGetPathParameterfvNV( HandleToID_cast(GLuint, size_t, inPathObject), GL_PATH_STROKE_BOUNDING_BOX_NV, data)); +#endif return NVBounds3(QT3DSVec3(data[0], data[1], 0.0f), QT3DSVec3(data[2], data[3], 0.0f)); } void NVRenderBackendGL4Impl::SetStrokeWidth(NVRenderBackendPathObject inPathObject, QT3DSF32 inStrokeWidth) { +#if defined(GL_NV_path_rendering) GL_CALL_NVPATH_EXT(glPathParameterfNV(HandleToID_cast(GLuint, size_t, inPathObject), GL_PATH_STROKE_WIDTH_NV, inStrokeWidth)); +#endif } void NVRenderBackendGL4Impl::SetPathProjectionMatrix(const QT3DSMat44 inPathProjection) @@ -649,8 +685,10 @@ namespace render { void NVRenderBackendGL4Impl::StencilFillPath(NVRenderBackendPathObject inPathObject) { +#if defined(GL_NV_path_rendering) GL_CALL_NVPATH_EXT(glStencilFillPathNV(HandleToID_cast(GLuint, size_t, inPathObject), GL_COUNT_UP_NV, (GLuint)~0)); +#endif } void NVRenderBackendGL4Impl::ReleasePathNVObject(NVRenderBackendPathObject po, size_t range) diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp index ee496c61..30049e76 100644 --- a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp +++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp @@ -34,12 +34,30 @@ #include "render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h" #include "foundation/StringTable.h" -#define GL_CALL_FUNCTION(x) m_glFunctions->x; checkGLError(); -#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; checkGLError(); +#ifdef RENDER_BACKEND_LOG_GL_ERRORS +#define RENDER_LOG_ERROR_PARAMS(x) checkGLError(#x, __FILE__, __LINE__) +#else +#define RENDER_LOG_ERROR_PARAMS(x) checkGLError() +#endif + +#define GL_CALL_FUNCTION(x) m_glFunctions->x; RENDER_LOG_ERROR_PARAMS(x); +#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; RENDER_LOG_ERROR_PARAMS(x); namespace qt3ds { namespace render { +#ifndef GL_PROGRAM_SEPARABLE +#define GL_PROGRAM_SEPARABLE 0x8258 +#endif + +#ifndef GL_UNSIGNED_INT_IMAGE_2D +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#endif + +#ifndef GL_UNSIGNED_INT_ATOMIC_COUNTER +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#endif + /// constructor NVRenderBackendGLBase::NVRenderBackendGLBase(NVFoundationBase &fnd, qt3ds::foundation::IStringTable &stringTable, @@ -48,7 +66,6 @@ namespace render { , m_Foundation(fnd) , m_StringTable(stringTable) , m_Conversion() - , m_Extensions(m_Foundation.getAllocator(), "NVRenderBackendGLBase::m_Extensions") , m_MaxAttribCount(0) , m_DrawBuffersArray(m_Foundation.getAllocator(), "NVRenderBackendGLBase::m_DrawBuffersArray") @@ -213,6 +230,15 @@ namespace render { case NVRenderBackendCaps::gpuShader5: bSupported = m_backendSupport.caps.bits.bGPUShader5ExtensionSupported; break; + case NVRenderBackendCaps::VertexArrayObject: + bSupported = m_backendSupport.caps.bits.bVertexArrayObjectSupported; + break; + case NVRenderBackendCaps::StandardDerivatives: + bSupported = m_backendSupport.caps.bits.bStandardDerivativesSupported; + break; + case NVRenderBackendCaps::TextureLod: + bSupported = m_backendSupport.caps.bits.bTextureLodSupported; + break; default: QT3DS_ASSERT(false); bSupported = false; @@ -849,7 +875,6 @@ namespace render { GLuint texID = 0; GL_CALL_FUNCTION(glGenTextures(1, &texID)); - return (NVRenderBackend::NVRenderBackendTextureObject)texID; } @@ -940,6 +965,7 @@ namespace render { m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat, glformat, gltype, glInternalFormat); + if (conversionRequired) { GLenum dummy; m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat, @@ -951,7 +977,9 @@ namespace render { } else if (NVRenderTextureFormats::isDepthTextureFormat(format)) m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), format, glformat, gltype, glInternalFormat); - +#ifdef QT_OPENGL_ES_2 + glInternalFormat = glformat; +#endif GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width, (GLsizei)height, border, glformat, gltype, hostPtr)); @@ -2115,7 +2143,7 @@ namespace render { return retval; } - const char *NVRenderBackendGLBase::geRendererString() + const char *NVRenderBackendGLBase::getRendererString() { const char *retval = (const char *)GL_CALL_FUNCTION(glGetString(GL_RENDERER)); if (retval == NULL) @@ -2124,6 +2152,15 @@ namespace render { return retval; } + const char *NVRenderBackendGLBase::getExtensionString() + { + const char *retval = (const char *)GL_CALL_FUNCTION(glGetString(GL_EXTENSIONS)); + if (retval == NULL) + return ""; + + return retval; + } + /** * @brief This function inspects the various strings to setup * HW capabilities of the device. @@ -2145,6 +2182,17 @@ namespace render { } } +#ifdef RENDER_BACKEND_LOG_GL_ERRORS + void NVRenderBackendGLBase::checkGLError(const char *function, const char *file, + const unsigned int line) const + { + GLenum error = m_glFunctions->glGetError(); + if (error != GL_NO_ERROR) { + qCCritical(GL_ERROR) << GLConversion::processGLError(error) << " " + << function << " " << file << " " << line; + } + } +#else void NVRenderBackendGLBase::checkGLError() const { #if !defined(NDEBUG) || defined(_DEBUG) @@ -2155,6 +2203,7 @@ namespace render { } #endif } +#endif } } diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp index ec0445b3..93229199 100644 --- a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp +++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp @@ -54,7 +54,12 @@ namespace render { NVScopedRefCounted<IStringTable> theStringTable(inStringTable); NVScopedRefCounted<NVRenderBackend> theBackend; bool isES = format.renderableType() == QSurfaceFormat::OpenGLES; - if (format.majorVersion() == 3 && format.minorVersion() >= 1 && !isES) { + if (isES && (format.majorVersion() == 2 + || (format.majorVersion() == 3 && format.minorVersion() == 0))) { + theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGLES2Impl)(foundation, + *theStringTable, + format); + } else if (format.majorVersion() == 3 && format.minorVersion() >= 1 && !isES) { theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL3Impl)(foundation, *theStringTable, format); diff --git a/src/Runtime/Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h b/src/Runtime/Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h index 105ffc64..fe80eb68 100644 --- a/src/Runtime/Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h +++ b/src/Runtime/Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h @@ -36,6 +36,8 @@ namespace uic { namespace render { class UICShadowMap; + struct SShaderGeneratorGeneratedShader; + struct SLightConstantProperties; class IDefaultMaterialVertexPipeline : public IShaderStageGenerator { @@ -110,6 +112,8 @@ namespace render { static IDefaultMaterialShaderGenerator & CreateDefaultMaterialShaderGenerator(IUICRenderContext &inRenderContext); + + SLightConstantProperties *GetLightConstantProperties(SShaderGeneratorGeneratedShader &shader); }; } } diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.cpp index 592b41d5..a6f90c43 100644 --- a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.cpp +++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.cpp @@ -1172,9 +1172,14 @@ namespace render { m_UICContext.GetRenderContext().SetRenderTarget(theAtlasFB); // this texture contains our single entries - NVRenderTexture2D *theTexture = m_UICContext.GetResourceManager().AllocateTexture2D( - 32, 32, NVRenderTextureFormats::Alpha8); - + NVRenderTexture2D *theTexture = nullptr; + if (m_Context->GetRenderContextType() == NVRenderContextValues::GLES2) { + theTexture = m_UICContext.GetResourceManager() + .AllocateTexture2D(32, 32, NVRenderTextureFormats::RGBA8); + } else { + theTexture = m_UICContext.GetResourceManager() + .AllocateTexture2D(32, 32, NVRenderTextureFormats::Alpha8); + } m_Context->SetClearColor(QT3DSVec4(0, 0, 0, 0)); m_Context->Clear(NVRenderClearValues::Color); m_Context->SetDepthTestEnabled(false); diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp index 12dab8a9..d8dc4cee 100644 --- a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp +++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp @@ -254,6 +254,8 @@ namespace render { shader->m_ViewMatrix.Set(m_Camera->m_GlobalTransform); shader->m_DepthTexture.Set(m_LayerDepthTexture); + shader->m_DepthSamplerSize.Set(QT3DSVec2(m_LayerDepthTexture->GetTextureDetails().m_Width, + m_LayerDepthTexture->GetTextureDetails().m_Height)); // Important uniforms for AO calculations QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar); @@ -290,6 +292,8 @@ namespace render { shader->m_DepthTexture.Set(theDepthTex); shader->m_CubeTexture.Set(theDepthCube); + shader->m_DepthSamplerSize.Set(QT3DSVec2(theDepthTex->GetTextureDetails().m_Width, + theDepthTex->GetTextureDetails().m_Height)); // Important uniforms for AO calculations QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar); @@ -721,7 +725,9 @@ namespace render { *pEntry->m_DepthRender); (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color0, *pEntry->m_DepthCube, curFace); + (*theFB)->IsComplete(); theRenderContext.Clear(clearFlags); + RunRenderPass(RenderRenderableShadowMapPass, false, true, true, i, theCameras[k]); } @@ -787,7 +793,6 @@ namespace render { qt3ds::render::NVRenderClearFlags clearFlags(qt3ds::render::NVRenderClearValues::Stencil | qt3ds::render::NVRenderClearValues::Depth); - theRenderContext.Clear(clearFlags); RunRenderPass(RenderRenderableDepthPass, false, true, inEnableTransparentDepthWrite, 0, @@ -1201,7 +1206,8 @@ namespace render { SWindowDimensions theLayerOriginalTextureDimensions = theLayerTextureDimensions; NVRenderTextureFormats::Enum DepthTextureFormat = NVRenderTextureFormats::Depth24Stencil8; NVRenderTextureFormats::Enum ColorTextureFormat = NVRenderTextureFormats::RGBA8; - if (thePrepResult.m_LastEffect) { + if (thePrepResult.m_LastEffect + && theRenderContext.GetRenderContextType() != NVRenderContextValues::GLES2) { if (m_Layer.m_Background != LayerBackground::Transparent) ColorTextureFormat = NVRenderTextureFormats::R11G11B10; else @@ -1216,8 +1222,10 @@ namespace render { && theRenderContext.AreMultisampleTexturesSupported()) sampleCount = (QT3DSU32)m_Layer.m_MultisampleAAMode; - bool isMultisamplePass = - (sampleCount > 1) || (m_Layer.m_MultisampleAAMode == AAModeValues::SSAA); + bool isMultisamplePass = false; + if (theRenderContext.GetRenderContextType() != NVRenderContextValues::GLES2) + isMultisamplePass = + (sampleCount > 1) || (m_Layer.m_MultisampleAAMode == AAModeValues::SSAA); qt3ds::render::NVRenderTextureTargetType::Enum thFboAttachTarget = qt3ds::render::NVRenderTextureTargetType::Texture2D; diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp index d06a7678..e496fbfc 100644 --- a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp +++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp @@ -1169,7 +1169,8 @@ namespace render { thePrepResult.m_Flags.SetRequiresDepthTexture(requiresDepthPrepass || NeedsWidgetTexture()); thePrepResult.m_Flags.SetShouldRenderToTexture(shouldRenderToTexture); - thePrepResult.m_Flags.SetRequiresSsaoPass(SSAOEnabled); + if (m_Renderer.GetContext().GetRenderContextType() != NVRenderContextValues::GLES2) + thePrepResult.m_Flags.SetRequiresSsaoPass(SSAOEnabled); if (thePrepResult.IsLayerVisible()) { if (shouldRenderToTexture) { @@ -1248,8 +1249,9 @@ namespace render { if (theLight->m_Flags.IsGloballyActive()) { if (theLight->m_Scope == NULL) { m_Lights.push_back(theLight); - - if (theLight->m_CastShadow && GetShadowMapManager()) { + if (m_Renderer.GetContext().GetRenderContextType() + != NVRenderContextValues::GLES2 + && theLight->m_CastShadow && GetShadowMapManager()) { // PKC -- use of "res" as an exponent of two is an annoying // artifact of the XML interface // I'll change this with an enum interface later on, but that's @@ -1263,7 +1265,6 @@ namespace render { m_Lights.size() - 1, mapSize, mapSize, NVRenderTextureFormats::R16, 1, mapMode, ShadowFilterValues::NONE); - thePrepResult.m_Flags.SetRequiresShadowMapPass(true); SetShaderFeature("UIC_ENABLE_SSM", true); } diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.cpp index a9a9a947..a752e021 100644 --- a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.cpp +++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.cpp @@ -1880,13 +1880,20 @@ namespace render { // fragmentGenerator.AddInclude( "SSAOCustomMaterial.glsllib" ); theFragmentGenerator.AddInclude("viewProperties.glsllib"); theFragmentGenerator.AddInclude("screenSpaceAO.glsllib"); - - theFragmentGenerator - << "layout (std140) uniform cbAoShadow { " << Endl << " vec4 ao_properties;" - << Endl << " vec4 ao_properties2;" << Endl << " vec4 shadow_properties;" - << Endl << " vec4 aoScreenConst;" << Endl << " vec4 UvToEyeConst;" << Endl - << "};" << Endl; - + if (m_Context->GetRenderContextType() == NVRenderContextValues::GLES2) { + theFragmentGenerator + << "\tuniform vec4 ao_properties;" << Endl + << "\tuniform vec4 ao_properties2;" << Endl + << "\tuniform vec4 shadow_properties;" << Endl + << "\tuniform vec4 aoScreenConst;" << Endl + << "\tuniform vec4 UvToEyeConst;" << Endl; + } else { + theFragmentGenerator + << "layout (std140) uniform cbAoShadow { " << Endl << "\tvec4 ao_properties;" + << Endl << "\tvec4 ao_properties2;" << Endl << "\tvec4 shadow_properties;" + << Endl << "\tvec4 aoScreenConst;" << Endl << "\tvec4 UvToEyeConst;" << Endl + << "};" << Endl; + } theFragmentGenerator.AddUniform("camera_direction", "vec3"); theFragmentGenerator.AddUniform("depth_sampler", "sampler2D"); theFragmentGenerator.Append("void main() {"); @@ -1899,22 +1906,42 @@ namespace render { // values at the edges // surrounding objects, and this also ends up giving us weird AO values. // If we had a proper screen-space normal map, that would also do the trick. - theFragmentGenerator.Append("\tivec2 iCoords = ivec2( gl_FragCoord.xy );"); - theFragmentGenerator.Append("\tfloat depth = getDepthValue( " - "texelFetch(depth_sampler, iCoords, 0), " - "camera_properties );"); - theFragmentGenerator.Append( - "\tdepth = depthValueToLinearDistance( depth, camera_properties );"); - theFragmentGenerator.Append("\tdepth = (depth - camera_properties.x) / " - "(camera_properties.y - camera_properties.x);"); - theFragmentGenerator.Append("\tfloat depth2 = getDepthValue( " - "texelFetch(depth_sampler, iCoords+ivec2(1), 0), " - "camera_properties );"); - theFragmentGenerator.Append( - "\tdepth2 = depthValueToLinearDistance( depth, camera_properties );"); - theFragmentGenerator.Append("\tfloat depth3 = getDepthValue( " - "texelFetch(depth_sampler, iCoords-ivec2(1), 0), " - "camera_properties );"); + if (m_Context->GetRenderContextType() == NVRenderContextValues::GLES2) { + theFragmentGenerator.AddUniform("depth_sampler_size", "vec2"); + theFragmentGenerator.Append("\tivec2 iCoords = ivec2( gl_FragCoord.xy );"); + theFragmentGenerator.Append("\tfloat depth = getDepthValue( " + "texture2D(depth_sampler, vec2(iCoords)" + " / depth_sampler_size), camera_properties );"); + theFragmentGenerator.Append( + "\tdepth = depthValueToLinearDistance( depth, camera_properties );"); + theFragmentGenerator.Append("\tdepth = (depth - camera_properties.x) / " + "(camera_properties.y - camera_properties.x);"); + theFragmentGenerator.Append("\tfloat depth2 = getDepthValue( " + "texture2D(depth_sampler, vec2(iCoords+ivec2(1))" + " / depth_sampler_size), camera_properties );"); + theFragmentGenerator.Append( + "\tdepth2 = depthValueToLinearDistance( depth, camera_properties );"); + theFragmentGenerator.Append("\tfloat depth3 = getDepthValue( " + "texture2D(depth_sampler, vec2(iCoords-ivec2(1))" + " / depth_sampler_size), camera_properties );"); + } else { + theFragmentGenerator.Append("\tivec2 iCoords = ivec2( gl_FragCoord.xy );"); + theFragmentGenerator.Append("\tfloat depth = getDepthValue( " + "texelFetch(depth_sampler, iCoords, 0), " + "camera_properties );"); + theFragmentGenerator.Append( + "\tdepth = depthValueToLinearDistance( depth, camera_properties );"); + theFragmentGenerator.Append("\tdepth = (depth - camera_properties.x) / " + "(camera_properties.y - camera_properties.x);"); + theFragmentGenerator.Append("\tfloat depth2 = getDepthValue( " + "texelFetch(depth_sampler, iCoords+ivec2(1), 0), " + "camera_properties );"); + theFragmentGenerator.Append( + "\tdepth2 = depthValueToLinearDistance( depth, camera_properties );"); + theFragmentGenerator.Append("\tfloat depth3 = getDepthValue( " + "texelFetch(depth_sampler, iCoords-ivec2(1), 0), " + "camera_properties );"); + } theFragmentGenerator.Append( "\tdepth3 = depthValueToLinearDistance( depth, camera_properties );"); theFragmentGenerator.Append("\tvec3 tanU = vec3(10, 0, dFdx(depth));"); diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.h b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.h index fd5e2a1f..fe5af0d0 100644 --- a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.h +++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.h @@ -215,6 +215,7 @@ namespace render { NVRenderCachedShaderProperty<QT3DSVec3> m_CameraDirection; NVRenderCachedShaderProperty<NVRenderTexture2D *> m_DepthTexture; NVRenderCachedShaderProperty<NVRenderTextureCube *> m_CubeTexture; + NVRenderCachedShaderProperty<QT3DSVec2> m_DepthSamplerSize; NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_AoShadowParams; QT3DSI32 m_RefCount; @@ -227,6 +228,7 @@ namespace render { , m_CameraDirection("camera_direction", inShader) , m_DepthTexture("depth_sampler", inShader) , m_CubeTexture("depth_cube", inShader) + , m_DepthSamplerSize("depth_sampler_size", inShader) , m_AoShadowParams("cbAoShadow", inShader) , m_RefCount(0) { diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.cpp index b6230707..1082a532 100644 --- a/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.cpp +++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.cpp @@ -249,12 +249,17 @@ struct SBufferManager : public IBufferManager NVRenderTexture2D *theTexture = m_Context->CreateTexture2D(); if (inLoadedImage.data) { qt3ds::render::NVRenderTextureFormats::Enum destFormat = inLoadedImage.format; - if (inBsdfMipmaps) - destFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F; - else + if (inBsdfMipmaps) { + if (m_Context->GetRenderContextType() == render::NVRenderContextValues::GLES2) + destFormat = qt3ds::render::NVRenderTextureFormats::RGBA8; + else + destFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F; + } + else { theTexture->SetTextureData( NVDataRef<QT3DSU8>((QT3DSU8 *)inLoadedImage.data, inLoadedImage.dataSizeInBytes), 0, inLoadedImage.width, inLoadedImage.height, inLoadedImage.format, destFormat); + } if (inBsdfMipmaps && NVRenderTextureFormats::isUncompressedTextureFormat(inLoadedImage.format)) { diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp index 91cd9cb5..5f9b3558 100644 --- a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp +++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp @@ -240,7 +240,11 @@ static FIBITMAP *DoLoadHDR(FreeImageIO *io, fi_handle handle, SLoadedTexture *SLoadedTexture::LoadHDR(ISeekableIOStream &inStream, NVFoundationBase &inFnd) { FreeImageIO theIO(inFnd.getAllocator(), inFnd); +#ifdef QT_OPENGL_ES_2 + SLoadedTexture *retval = DoLoadHDR(&theIO, &inStream, NVRenderTextureFormats::RGBA8); +#else SLoadedTexture *retval = DoLoadHDR(&theIO, &inStream, NVRenderTextureFormats::RGBA16F); +#endif // Let's just assume we don't support this just yet. // if ( retval ) diff --git a/src/Runtime/Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp b/src/Runtime/Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp index fa5c9e5b..8b962ca4 100644 --- a/src/Runtime/Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp +++ b/src/Runtime/Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp @@ -40,6 +40,7 @@ #include "UICRenderShadowMap.h" #include "UICRenderCustomMaterial.h" #include "UICRenderDynamicObjectSystem.h" +#include "render/Qt3DSRenderShaderProgram.h" using namespace uic::render; using qt3ds::render::NVRenderCachedShaderProperty; @@ -81,11 +82,14 @@ struct SShaderTextureProperties NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler; NVRenderCachedShaderProperty<QT3DSVec3> m_Offsets; NVRenderCachedShaderProperty<QT3DSVec4> m_Rotations; + NVRenderCachedShaderProperty<QT3DSVec2> m_Size; SShaderTextureProperties(const char *sampName, const char *offName, const char *rotName, + const char *sizeName, NVRenderShaderProgram &inShader) : m_Sampler(sampName, inShader) , m_Offsets(offName, inShader) , m_Rotations(rotName, inShader) + , m_Size(sizeName, inShader) { } SShaderTextureProperties() {} @@ -124,6 +128,45 @@ struct SShadowMapProperties } }; +struct SShaderGeneratorGeneratedShader; + +struct SLightConstantProperties +{ + struct LightConstants + { + NVRenderCachedShaderProperty<QT3DSVec4> m_position; + NVRenderCachedShaderProperty<QT3DSVec4> m_direction; + NVRenderCachedShaderProperty<QT3DSVec4> m_up; + NVRenderCachedShaderProperty<QT3DSVec4> m_right; + NVRenderCachedShaderProperty<QT3DSVec4> m_diffuse; + NVRenderCachedShaderProperty<QT3DSVec4> m_ambient; + NVRenderCachedShaderProperty<QT3DSVec4> m_specular; + NVRenderCachedShaderProperty<QT3DSF32> m_spotExponent; + NVRenderCachedShaderProperty<QT3DSF32> m_spotCutoff; + NVRenderCachedShaderProperty<QT3DSF32> m_constantAttenuation; + NVRenderCachedShaderProperty<QT3DSF32> m_linearAttenuation; + NVRenderCachedShaderProperty<QT3DSF32> m_quadraticAttenuation; + NVRenderCachedShaderProperty<QT3DSF32> m_range; + NVRenderCachedShaderProperty<QT3DSF32> m_width; + NVRenderCachedShaderProperty<QT3DSF32> m_height; + NVRenderCachedShaderProperty<QT3DSVec4> m_shadowControls; + NVRenderCachedShaderProperty<QT3DSMat44> m_shadowView; + NVRenderCachedShaderProperty<QT3DSI32> m_shadowIdx; + NVRenderCachedShaderProperty<QT3DSVec3> m_attenuation; + + LightConstants(const QString &lightRef, NVRenderShaderProgram &shader); + + void updateLights(int lIdx, SShaderGeneratorGeneratedShader &shader); + }; + + SLightConstantProperties(SShaderGeneratorGeneratedShader &shader, bool packed); + ~SLightConstantProperties(); + void updateLights(SShaderGeneratorGeneratedShader &shader); + + QVector<LightConstants *> m_constants; + NVRenderCachedShaderProperty<QT3DSI32> m_lightCount; +}; + /** * The results of generating a shader. Caches all possible variable names into * typesafe objects. @@ -161,12 +204,16 @@ struct SShaderGeneratorGeneratedShader NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeOpts; NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeRot; NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeOfs; + NVRenderCachedShaderProperty<QT3DSVec2> m_LightProbeSize; NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LightProbe2; NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbe2Props; + NVRenderCachedShaderProperty<QT3DSVec2> m_LightProbe2Size; NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_AoShadowParams; NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_LightsBuffer; + SLightConstantProperties *m_lightConstantProperties; + // Cache the image property name lookups nvvector<SShaderTextureProperties> m_Images; nvvector<SShaderLightProperties> m_Lights; @@ -203,10 +250,13 @@ struct SShaderGeneratorGeneratedShader , m_LightProbeOpts("light_probe_opts", inShader) , m_LightProbeRot("light_probe_rotation", inShader) , m_LightProbeOfs("light_probe_offset", inShader) + , m_LightProbeSize("light_probe_size", inShader) , m_LightProbe2("light_probe2", inShader) , m_LightProbe2Props("light_probe2_props", inShader) + , m_LightProbe2Size("light_probe2_size", inShader) , m_AoShadowParams("cbAoShadow", inShader) , m_LightsBuffer("cbBufferLights", inShader) + , m_lightConstantProperties(NULL) , m_Images(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_Images") , m_Lights(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_Lights") , m_ShadowMaps(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_ShadowMaps") @@ -214,7 +264,12 @@ struct SShaderGeneratorGeneratedShader { m_Shader.addRef(); } - ~SShaderGeneratorGeneratedShader() { m_Shader.release(); } + ~SShaderGeneratorGeneratedShader() + { + if (m_lightConstantProperties) + delete m_lightConstantProperties; + m_Shader.release(); + } void addRef() { ++m_RefCount; } void release() @@ -227,6 +282,109 @@ struct SShaderGeneratorGeneratedShader } }; +static const QStringList lconstantnames = { + QStringLiteral("position"), + QStringLiteral("direction"), + QStringLiteral("up"), + QStringLiteral("right"), + QStringLiteral("diffuse"), + QStringLiteral("ambient"), + QStringLiteral("specular"), + QStringLiteral("spotExponent"), + QStringLiteral("spotCutoff"), + QStringLiteral("constantAttenuation"), + QStringLiteral("linearAttenuation"), + QStringLiteral("quadraticAttenuation"), + QStringLiteral("range"), + QStringLiteral("width"), + QStringLiteral("height"), + QStringLiteral("shadowControls"), + QStringLiteral("shadowView"), + QStringLiteral("shadowIdx"), + QStringLiteral("attenuation") +}; + +SLightConstantProperties::LightConstants::LightConstants(const QString &lightRef, + NVRenderShaderProgram &shader) + : m_position(QString("%1%2").arg(lightRef, lconstantnames[0]), shader) + , m_direction(QString("%1%2").arg(lightRef).arg(lconstantnames[1]), shader) + , m_up(QString("%1%2").arg(lightRef, lconstantnames[2]), shader) + , m_right(QString("%1%2").arg(lightRef, lconstantnames[3]), shader) + , m_diffuse(QString("%1%2").arg(lightRef, lconstantnames[4]), shader) + , m_ambient(QString("%1%2").arg(lightRef, lconstantnames[5]), shader) + , m_specular(QString("%1%2").arg(lightRef, lconstantnames[6]), shader) + , m_spotExponent(QString("%1%2").arg(lightRef, lconstantnames[7]), shader) + , m_spotCutoff(QString("%1%2").arg(lightRef, lconstantnames[8]), shader) + , m_constantAttenuation(QString("%1%2").arg(lightRef, lconstantnames[9]), shader) + , m_linearAttenuation(QString("%1%2").arg(lightRef, lconstantnames[10]), shader) + , m_quadraticAttenuation(QString("%1%2").arg(lightRef, lconstantnames[11]), shader) + , m_range(QString("%1%2").arg(lightRef, lconstantnames[12]), shader) + , m_width(QString("%1%2").arg(lightRef, lconstantnames[13]), shader) + , m_height(QString("%1%2").arg(lightRef, lconstantnames[14]), shader) + , m_shadowControls(QString("%1%2").arg(lightRef, lconstantnames[15]), shader) + , m_shadowView(QString("%1%2").arg(lightRef, lconstantnames[16]), shader) + , m_shadowIdx(QString("%1%2").arg(lightRef, lconstantnames[17]), shader) + , m_attenuation(QString("%1%2").arg(lightRef, lconstantnames[18]), shader) +{ + +} + +void SLightConstantProperties::LightConstants::updateLights(int lIdx, + SShaderGeneratorGeneratedShader &shader) +{ + m_position.Set(shader.m_Lights[lIdx].m_LightData.m_position); + m_direction.Set(shader.m_Lights[lIdx].m_LightData.m_direction); + m_up.Set(shader.m_Lights[lIdx].m_LightData.m_up); + m_right.Set(shader.m_Lights[lIdx].m_LightData.m_right); + m_diffuse.Set(shader.m_Lights[lIdx].m_LightData.m_diffuse); + m_ambient.Set(shader.m_Lights[lIdx].m_LightData.m_ambient); + m_specular.Set(shader.m_Lights[lIdx].m_LightData.m_specular); + m_spotExponent.Set(shader.m_Lights[lIdx].m_LightData.m_spotExponent); + m_spotCutoff.Set(shader.m_Lights[lIdx].m_LightData.m_spotCutoff); + m_constantAttenuation.Set(shader.m_Lights[lIdx].m_LightData.m_constantAttenuation); + m_linearAttenuation.Set(shader.m_Lights[lIdx].m_LightData.m_linearAttenuation); + m_quadraticAttenuation.Set(shader.m_Lights[lIdx].m_LightData.m_quadraticAttenuation); + m_range.Set(shader.m_Lights[lIdx].m_LightData.m_range); + m_width.Set(shader.m_Lights[lIdx].m_LightData.m_width); + m_height.Set(shader.m_Lights[lIdx].m_LightData.m_height); + m_shadowControls.Set(shader.m_Lights[lIdx].m_LightData.m_shadowControls); + m_shadowView.Set(shader.m_Lights[lIdx].m_LightData.m_shadowView); + m_shadowIdx.Set(shader.m_Lights[lIdx].m_LightData.m_shadowIdx); + m_attenuation.Set(QT3DSVec3(shader.m_Lights[lIdx].m_LightData.m_constantAttenuation, + shader.m_Lights[lIdx].m_LightData.m_linearAttenuation, + shader.m_Lights[lIdx].m_LightData.m_quadraticAttenuation)); +} + + +SLightConstantProperties::SLightConstantProperties(SShaderGeneratorGeneratedShader &shader, + bool packed) + : m_lightCount("uNumLights", shader.m_Shader) +{ + m_constants.resize(shader.m_Lights.size()); + for (unsigned int i = 0; i < shader.m_Lights.size(); ++i) { + QString lref; + if (packed) + lref = QStringLiteral("light_%1_"); + else + lref = QStringLiteral("lights[%1]."); + lref = lref.arg(i); + m_constants[i] = new LightConstants(lref, shader.m_Shader); + } + m_lightCount.Set(shader.m_Lights.size()); +} + +SLightConstantProperties::~SLightConstantProperties() +{ + qDeleteAll(m_constants); +} + +void SLightConstantProperties::updateLights(SShaderGeneratorGeneratedShader &shader) +{ + for (int i = 0; i < m_constants.size(); ++i) + m_constants[i]->updateLights(i, shader); +} + + #ifndef EA_PLATFORM_WINDOWS #define _snprintf snprintf #endif @@ -251,6 +409,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator NVDataRef<SLight *> m_Lights; SRenderableImage *m_FirstImage; bool m_HasTransparency; + bool m_LightsAsSeparateUniforms; TStrType m_ImageStem; TStrType m_ImageSampler; @@ -258,13 +417,14 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator TStrType m_ImageRotations; TStrType m_ImageFragCoords; TStrType m_ImageTemp; + TStrType m_ImageSamplerSize; TStrType m_TexCoordTemp; TStrType m_LightStem; TStrType m_LightColor; TStrType m_LightSpecularColor; - TStrType m_LightAttenutation; + TStrType m_LightAttenuation; TStrType m_LightConstantAttenuation; TStrType m_LightLinearAttenuation; TStrType m_LightQuadraticAttenuation; @@ -301,6 +461,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator , m_ShadowMapManager(NULL) , m_CurrentPipeline(NULL) , m_FirstImage(NULL) + , m_LightsAsSeparateUniforms(false) , m_ProgramToShaderMap(inRc.GetAllocator(), "m_ProgramToShaderMap") , m_ConstantBuffers(inRc.GetAllocator(), "m_ConstantBuffers") , m_RefCount(0) @@ -348,6 +509,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator m_ImageRotations.append("rotations"); m_ImageFragCoords = m_ImageStem; m_ImageFragCoords.append("uv_coords"); + m_ImageSamplerSize = m_ImageStem; + m_ImageSamplerSize.append("size"); } void SetupTexCoordVariableName(size_t uvSet) @@ -500,7 +663,6 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator void OutputDiffuseAreaLighting(IShaderStageGenerator &infragmentShader, const char *inPos, TStrType inLightPrefix) { - m_LightAttenutation = inLightPrefix + "_attenuation"; m_NormalizedDirection = inLightPrefix + "_areaDir"; AddLocalVariable(infragmentShader, m_NormalizedDirection, "vec3"); infragmentShader << "\tlightAttenuation = calculateDiffuseAreaOld( " << m_LightDirection @@ -635,13 +797,16 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator } bool MaybeAddMaterialFresnel(IShaderStageGenerator &fragmentShader, NVConstDataRef<QT3DSU32> inKey, - bool inFragmentHasSpecularAmount) + bool inFragmentHasSpecularAmount, bool supportStandardDerivates) { if (m_DefaultMaterialShaderKeyProperties.m_FresnelEnabled.GetValue(inKey)) { if (inFragmentHasSpecularAmount == false) fragmentShader << "\tfloat specularAmount = 1.0;" << Endl; inFragmentHasSpecularAmount = true; - fragmentShader.AddInclude("defaultMaterialFresnel.glsllib"); + if (supportStandardDerivates) + fragmentShader.AddInclude("defaultMaterialFresnel.glsllib"); + else + fragmentShader.AddInclude("defaultMaterialFresnelNoDvn.glsllib"); fragmentShader.AddUniform("fresnelPower", "float"); fragmentShader.AddUniform("material_specular", "vec4"); fragmentShader << "\tfloat fresnelRatio = defaultMaterialSimpleFresnel( world_normal, " @@ -653,33 +818,58 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator } void SetupLightVariableNames(size_t lightIdx, SLight &inLight) { - m_LightStem = "lights"; - char buf[16]; - _snprintf(buf, 16, "[%lu].", lightIdx); - m_LightStem.append(buf); - - m_LightColor = m_LightStem; - m_LightColor.append("diffuse"); - m_LightDirection = m_LightStem; - m_LightDirection.append("direction"); - m_LightSpecularColor = m_LightStem; - m_LightSpecularColor.append("specular"); - if (inLight.m_LightType == RenderLightTypes::Point) { - m_LightPos = m_LightStem; - m_LightPos.append("position"); - m_LightConstantAttenuation = m_LightStem; - m_LightConstantAttenuation.append("constantAttenuation"); - m_LightLinearAttenuation = m_LightStem; - m_LightLinearAttenuation.append("linearAttenuation"); - m_LightQuadraticAttenuation = m_LightStem; - m_LightQuadraticAttenuation.append("quadraticAttenuation"); - } else if (inLight.m_LightType == RenderLightTypes::Area) { - m_LightPos = m_LightStem; - m_LightPos.append("position"); - m_LightUp = m_LightStem; - m_LightUp.append("up"); - m_LightRt = m_LightStem; - m_LightRt.append("right"); + if (m_LightsAsSeparateUniforms) { + char buf[16]; + _snprintf(buf, 16, "light_%u", lightIdx); + m_LightStem = buf; + m_LightColor = m_LightStem; + m_LightColor.append("_diffuse"); + m_LightDirection = m_LightStem; + m_LightDirection.append("_direction"); + m_LightSpecularColor = m_LightStem; + m_LightSpecularColor.append("_specular"); + if (inLight.m_LightType == RenderLightTypes::Point) { + m_LightPos = m_LightStem; + m_LightPos.append("_position"); + m_LightAttenuation = m_LightStem; + m_LightAttenuation.append("_attenuation"); + } else if (inLight.m_LightType == RenderLightTypes::Area) { + m_LightPos = m_LightStem; + m_LightPos.append("_position"); + m_LightUp = m_LightStem; + m_LightUp.append("_up"); + m_LightRt = m_LightStem; + m_LightRt.append("_right"); + } + } else { + m_LightStem = "lights"; + char buf[16]; + _snprintf(buf, 16, "[%u].", lightIdx); + m_LightStem.append(buf); + + m_LightColor = m_LightStem; + m_LightColor.append("diffuse"); + m_LightDirection = m_LightStem; + m_LightDirection.append("direction"); + m_LightSpecularColor = m_LightStem; + m_LightSpecularColor.append("specular"); + if (inLight.m_LightType == RenderLightTypes::Point) { + m_LightPos = m_LightStem; + m_LightPos.append("position"); + m_LightConstantAttenuation = m_LightStem; + m_LightConstantAttenuation.append("constantAttenuation"); + m_LightLinearAttenuation = m_LightStem; + m_LightLinearAttenuation.append("linearAttenuation"); + m_LightQuadraticAttenuation = m_LightStem; + m_LightQuadraticAttenuation.append("quadraticAttenuation"); + } else if (inLight.m_LightType == RenderLightTypes::Area) { + m_LightPos = m_LightStem; + m_LightPos.append("position"); + m_LightUp = m_LightStem; + m_LightUp.append("up"); + m_LightRt = m_LightStem; + m_LightRt.append("right"); + } } } @@ -784,7 +974,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator SetupImageVariableNames(idx); inShader.m_Images.push_back( SShaderTextureProperties(m_ImageSampler.c_str(), m_ImageOffsets.c_str(), - m_ImageRotations.c_str(), inShader.m_Shader)); + m_ImageRotations.c_str(), m_ImageSamplerSize.c_str(), + inShader.m_Shader)); } SShaderTextureProperties &theShaderProps = inShader.m_Images[idx]; const QT3DSMat44 &textureTransform = inImage.m_Image.m_TextureTransform; @@ -804,13 +995,16 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator // on the shader. // because setting the image on the texture forces the textue to bind and immediately apply // any tex params. + NVRenderTexture2D *imageTexture = inImage.m_Image.m_TextureData.m_Texture; inImage.m_Image.m_TextureData.m_Texture->SetTextureWrapS( inImage.m_Image.m_HorizontalTilingMode); inImage.m_Image.m_TextureData.m_Texture->SetTextureWrapT( inImage.m_Image.m_VerticalTilingMode); - theShaderProps.m_Sampler.Set(inImage.m_Image.m_TextureData.m_Texture); + theShaderProps.m_Sampler.Set(imageTexture); theShaderProps.m_Offsets.Set(offsets); theShaderProps.m_Rotations.Set(rotations); + theShaderProps.m_Size.Set(QT3DSVec2(imageTexture->GetTextureDetails().m_Width, + imageTexture->GetTextureDetails().m_Height)); } void GenerateShadowMapOcclusion(QT3DSU32 lightIdx, bool inShadowEnabled, @@ -884,6 +1078,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator QT3DSU32 lightmapRadiosityImageIdx = 0; SRenderableImage *lightmapShadowImage = NULL; QT3DSU32 lightmapShadowImageIdx = 0; + const bool supportStandardDerivatives + = m_RenderContext.GetRenderContext().IsStandardDerivativesSupported(); for (SRenderableImage *img = m_FirstImage; img != NULL; img = img->m_NextImage, ++imageIdx) { @@ -923,6 +1119,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator bool enableSSAO = false; bool enableSSDO = false; bool enableShadowMaps = false; + bool enableBumpNormal = normalImage || bumpImage; for (QT3DSU32 idx = 0; idx < FeatureSet().size(); ++idx) { eastl::string name(FeatureSet()[idx].m_Name.c_str()); @@ -957,7 +1154,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator } if (hasLighting) { - addFunction(fragmentShader, "sampleLightVars"); + if (!m_LightsAsSeparateUniforms) + addFunction(fragmentShader, "sampleLightVars"); addFunction(fragmentShader, "diffuseReflectionBSDF"); } @@ -975,12 +1173,13 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator fragmentShader.Append("\tvec3 vTransform;"); } - if (includeSSAOSSDOVars || hasSpecMap || hasLighting || hasEnvMap || enableFresnel || hasIblProbe) { + if (includeSSAOSSDOVars || hasSpecMap || hasLighting || hasEnvMap || enableFresnel + || hasIblProbe || enableBumpNormal) { vertexShader.GenerateViewVector(); vertexShader.GenerateWorldNormal(); vertexShader.GenerateWorldPosition(); } - if (includeSSAOSSDOVars || bumpImage || normalImage || specularEnabled || hasIblProbe) + if (includeSSAOSSDOVars || specularEnabled || hasIblProbe || enableBumpNormal) vertexShader.GenerateVarTangentAndBinormal(); // You do bump or normal mapping but not both @@ -988,13 +1187,23 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator GenerateImageUVCoordinates(bumpImageIdx, *bumpImage); fragmentShader.AddUniform("bumpAmount", "float"); - fragmentShader.AddInclude("uicDefaultMaterialFileBumpTexture.glsllib"); - // vec3 simplerFileBumpTexture( in sampler2D sampler, in float factor, vec2 - // texCoord, vec3 tangent, vec3 binormal, vec3 normal ) + if (m_RenderContext.GetRenderContext().GetRenderContextType() + == NVRenderContextValues::GLES2) { + fragmentShader.AddUniform(m_ImageSamplerSize, "vec2"); + fragmentShader.AddInclude("defaultMaterialBumpNoLod.glsllib"); + fragmentShader << "\tworld_normal = defaultMaterialBumpNoLod( " << m_ImageSampler + << ", bumpAmount, " << m_ImageFragCoords + << ", tangent, binormal, world_normal, " + << m_ImageSamplerSize << ");" << Endl; + } else { + fragmentShader.AddInclude("uicDefaultMaterialFileBumpTexture.glsllib"); + // vec3 simplerFileBumpTexture( in sampler2D sampler, in float factor, vec2 + // texCoord, vec3 tangent, vec3 binormal, vec3 normal ) - fragmentShader << "\tworld_normal = simplerFileBumpTexture( " << m_ImageSampler - << ", bumpAmount, " << m_ImageFragCoords - << ", tangent, binormal, world_normal );" << Endl; + fragmentShader << "\tworld_normal = simplerFileBumpTexture( " << m_ImageSampler + << ", bumpAmount, " << m_ImageFragCoords + << ", tangent, binormal, world_normal );" << Endl; + } // Do gram schmidt fragmentShader << "\tbinormal = normalize(cross(world_normal, tangent) );\n"; fragmentShader << "\ttangent = normalize(cross(binormal, world_normal) );\n"; @@ -1010,7 +1219,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator << ", tangent, binormal );" << Endl; } - if (includeSSAOSSDOVars || specularEnabled || hasIblProbe) + if (includeSSAOSSDOVars || specularEnabled || hasIblProbe || enableBumpNormal) fragmentShader << "\tmat3 tanFrame = mat3(tangent, binormal, world_normal);" << Endl; bool fragmentHasSpecularAmount = false; @@ -1099,7 +1308,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator } fragmentHasSpecularAmount = - MaybeAddMaterialFresnel(fragmentShader, inKey, fragmentHasSpecularAmount); + MaybeAddMaterialFresnel(fragmentShader, inKey, fragmentHasSpecularAmount, + supportStandardDerivatives); // Iterate through all lights for (QT3DSU32 lightIdx = 0; lightIdx < m_Lights.size(); ++lightIdx) { @@ -1120,6 +1330,11 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator fragmentShader << "\tlightAttenuation = 1.0;" << Endl; if (isDirectional) { + if (m_LightsAsSeparateUniforms) { + fragmentShader.AddUniform(m_LightDirection, "vec4"); + fragmentShader.AddUniform(m_LightColor, "vec4"); + } + if (enableSSDO) { fragmentShader << "\tshadowFac = customMaterialShadow( " << m_LightDirection << ".xyz, varWorldPos );" << Endl; @@ -1139,12 +1354,22 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator << m_LightColor << ".rgb, 0.0 ).rgb;" << Endl; if (specularEnabled) { + if (m_LightsAsSeparateUniforms) + fragmentShader.AddUniform(m_LightSpecularColor, "vec4"); OutputSpecularEquation(Material().m_SpecularModel, fragmentShader, m_LightDirection.c_str(), m_LightSpecularColor.c_str()); } } else if (isArea) { - addFunction(fragmentShader, "areaLightVars"); + if (m_LightsAsSeparateUniforms) { + fragmentShader.AddUniform(m_LightColor, "vec4"); + fragmentShader.AddUniform(m_LightPos, "vec4"); + fragmentShader.AddUniform(m_LightDirection, "vec4"); + fragmentShader.AddUniform(m_LightUp, "vec4"); + fragmentShader.AddUniform(m_LightRt, "vec4"); + } else { + addFunction(fragmentShader, "areaLightVars"); + } addFunction(fragmentShader, "calculateDiffuseAreaOld"); vertexShader.GenerateWorldPosition(); GenerateShadowMapOcclusion(lightIdx, enableShadowMaps && isShadow, @@ -1171,6 +1396,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator if (specularEnabled) { vertexShader.GenerateViewVector(); + if (m_LightsAsSeparateUniforms) + fragmentShader.AddUniform(m_LightSpecularColor, "vec4"); OutputSpecularAreaLighting(fragmentShader, "varWorldPos", "view_vector", m_LightSpecularColor.c_str()); } @@ -1190,6 +1417,11 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator GenerateShadowMapOcclusion(lightIdx, enableShadowMaps && isShadow, lightNode->m_LightType); + if (m_LightsAsSeparateUniforms) { + fragmentShader.AddUniform(m_LightColor, "vec4"); + fragmentShader.AddUniform(m_LightPos, "vec4"); + } + m_RelativeDirection = m_TempStr; m_RelativeDirection.append("_relativeDirection"); @@ -1216,11 +1448,23 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator addFunction(fragmentShader, "calculatePointLightAttenuation"); - fragmentShader - << "\tlightAttenuation = shadowFac * calculatePointLightAttenuation( vec3( " - << m_LightConstantAttenuation << ", " << m_LightLinearAttenuation << ", " - << m_LightQuadraticAttenuation << "), " << m_RelativeDistance << ");" - << Endl; + if (m_LightsAsSeparateUniforms) { + fragmentShader.AddUniform(m_LightAttenuation, "vec3"); + fragmentShader + << "\tlightAttenuation = shadowFac * calculatePointLightAttenuation(" + << "vec3( " << m_LightAttenuation << ".x, " << m_LightAttenuation + << ".y, " << m_LightAttenuation << ".z), " << m_RelativeDistance + << ");" << Endl; + } else { + fragmentShader + << "\tlightAttenuation = shadowFac * calculatePointLightAttenuation(" + << "vec3( " << m_LightConstantAttenuation << ", " + << m_LightLinearAttenuation << ", " << m_LightQuadraticAttenuation + << "), " << m_RelativeDistance << ");" + << Endl; + } + + AddTranslucencyIrradiance(fragmentShader, translucencyImage, m_TempStr, false); @@ -1230,6 +1474,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator << m_LightColor << ".rgb, 0.0 ).rgb;" << Endl; if (specularEnabled) { + if (m_LightsAsSeparateUniforms) + fragmentShader.AddUniform(m_LightSpecularColor, "vec4"); OutputSpecularEquation(Material().m_SpecularModel, fragmentShader, m_NormalizedDirection.c_str(), m_LightSpecularColor.c_str()); @@ -1255,7 +1501,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator // We still have specular maps and such that could potentially use the fresnel variable. fragmentHasSpecularAmount = - MaybeAddMaterialFresnel(fragmentShader, inKey, fragmentHasSpecularAmount); + MaybeAddMaterialFresnel(fragmentShader, inKey, fragmentHasSpecularAmount, + supportStandardDerivatives); } // Fresnel also modulates alpha. @@ -1400,6 +1647,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator SShaderDefaultMaterialKey theKey(Key()); theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties); + m_LightsAsSeparateUniforms = !m_RenderContext.GetRenderContext().GetConstantBufferSupport(); + GenerateVertexShader(); GenerateFragmentShader(theKey); @@ -1636,16 +1885,15 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator shader.m_LightProbeProps.Set(QT3DSVec4(0.0f, 0.0f, -1.0f, 0.0f)); shader.m_LightProbe2Props.Set(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f)); } - shader.m_LightProbe.Set(theLightProbe->m_TextureData.m_Texture); + NVRenderTexture2D *textureImage = theLightProbe->m_TextureData.m_Texture; + shader.m_LightProbe.Set(textureImage); + shader.m_LightProbeSize.Set(QT3DSVec2(textureImage->GetTextureDetails().m_Width, + textureImage->GetTextureDetails().m_Height)); } else { shader.m_LightProbeProps.Set(QT3DSVec4(0.0f, 0.0f, -1.0f, 0.0f)); shader.m_LightProbe2Props.Set(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f)); } - NVRenderConstantBuffer *pLightCb = GetLightConstantBuffer(shader.m_Lights.size()); - // if we have lights we need a light buffer - QT3DS_ASSERT(shader.m_Lights.size() == 0 || pLightCb); - QT3DSF32 emissivePower = 1.0; QT3DSU32 hasLighting = inMaterial.m_Lighting != DefaultMaterialLighting::NoLighting; @@ -1663,22 +1911,45 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator shader.m_MaterialSpecular.Set(material_specular); shader.m_CameraProperties.Set(inCameraVec); shader.m_FresnelPower.Set(inMaterial.m_FresnelPower); - for (QT3DSU32 idx = 0, end = shader.m_Lights.size(); idx < end && pLightCb; ++idx) { - shader.m_Lights[idx].m_LightData.m_diffuse = - QT3DSVec4(shader.m_Lights[idx].m_LightColor.x * inMaterial.m_DiffuseColor.x, - shader.m_Lights[idx].m_LightColor.y * inMaterial.m_DiffuseColor.y, - shader.m_Lights[idx].m_LightColor.z * inMaterial.m_DiffuseColor.z, 1.0); - - // this is our final change update memory - pLightCb->UpdateRaw(idx * sizeof(SLightSourceShader) + (4 * sizeof(QT3DSI32)), - NVDataRef<QT3DSU8>((QT3DSU8 *)&shader.m_Lights[idx].m_LightData, - sizeof(SLightSourceShader))); - } - // update light buffer to hardware - if (pLightCb) { - QT3DSI32 cgLights = shader.m_Lights.size(); - pLightCb->UpdateRaw(0, NVDataRef<QT3DSU8>((QT3DSU8 *)&cgLights, sizeof(QT3DSI32))); - shader.m_LightsBuffer.Set(); + + if (context.GetConstantBufferSupport()) { + NVRenderConstantBuffer *pLightCb = GetLightConstantBuffer(shader.m_Lights.size()); + // if we have lights we need a light buffer + QT3DS_ASSERT(shader.m_Lights.size() == 0 || pLightCb); + + for (QT3DSU32 idx = 0, end = shader.m_Lights.size(); idx < end && pLightCb; ++idx) { + shader.m_Lights[idx].m_LightData.m_diffuse = + QT3DSVec4(shader.m_Lights[idx].m_LightColor.x * inMaterial.m_DiffuseColor.x, + shader.m_Lights[idx].m_LightColor.y * inMaterial.m_DiffuseColor.y, + shader.m_Lights[idx].m_LightColor.z * inMaterial.m_DiffuseColor.z, 1.0); + + // this is our final change update memory + pLightCb->UpdateRaw(idx * sizeof(SLightSourceShader) + (4 * sizeof(QT3DSI32)), + NVDataRef<QT3DSU8>((QT3DSU8 *)&shader.m_Lights[idx].m_LightData, + sizeof(SLightSourceShader))); + } + // update light buffer to hardware + if (pLightCb) { + QT3DSI32 cgLights = shader.m_Lights.size(); + pLightCb->UpdateRaw(0, NVDataRef<QT3DSU8>((QT3DSU8 *)&cgLights, sizeof(QT3DSI32))); + shader.m_LightsBuffer.Set(); + } + } else { + SLightConstantProperties *pLightConstants = GetLightConstantProperties(shader); + + // if we have lights we need a light buffer + QT3DS_ASSERT(shader.m_Lights.size() == 0 || pLightConstants); + + for (QT3DSU32 idx = 0, end = shader.m_Lights.size(); + idx < end && pLightConstants; ++idx) { + shader.m_Lights[idx].m_LightData.m_diffuse = + QT3DSVec4(shader.m_Lights[idx].m_LightColor.x * inMaterial.m_DiffuseColor.x, + shader.m_Lights[idx].m_LightColor.y * inMaterial.m_DiffuseColor.y, + shader.m_Lights[idx].m_LightColor.z * inMaterial.m_DiffuseColor.z, 1.0); + } + // update light buffer to hardware + if (pLightConstants) + pLightConstants->updateLights(shader); } shader.m_MaterialDiffuseLightAmbientTotal.Set( @@ -1773,6 +2044,18 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator inRenderProperties.m_Probe2Window, inRenderProperties.m_Probe2Pos, inRenderProperties.m_Probe2Fade, inRenderProperties.m_ProbeFOV); } + + SLightConstantProperties *GetLightConstantProperties(SShaderGeneratorGeneratedShader &shader) + { + if (!shader.m_lightConstantProperties + || shader.m_Lights.size() > !shader.m_lightConstantProperties->m_constants.size()) { + if (shader.m_lightConstantProperties) + delete shader.m_lightConstantProperties; + shader.m_lightConstantProperties + = new SLightConstantProperties(shader, m_LightsAsSeparateUniforms); + } + return shader.m_lightConstantProperties; + } }; } diff --git a/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp b/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp index 0a832321..b58b6352 100644 --- a/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp +++ b/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp @@ -119,8 +119,8 @@ struct SPGRenderer : public IPixelGraphicsRenderer m_FragmentGenerator.Begin(); m_VertexGenerator.AddAttribute("attr_pos", "vec2"); m_VertexGenerator.AddUniform("model_view_projection", "mat4"); - m_VertexGenerator.AddUniform("leftright", "float[2]"); - m_VertexGenerator.AddUniform("bottomtop", "float[2]"); + m_VertexGenerator.AddUniform("leftright[2]", "float"); + m_VertexGenerator.AddUniform("bottomtop[2]", "float"); m_FragmentGenerator.AddVarying("rect_uvs", "vec2"); m_FragmentGenerator.AddUniform("rect_color", "vec4"); m_VertexGenerator << "void main() {" << Endl diff --git a/src/Runtime/Source/UICRender/Source/UICRenderShaderCache.cpp b/src/Runtime/Source/UICRender/Source/UICRenderShaderCache.cpp index 1db2e77b..850c81ed 100644 --- a/src/Runtime/Source/UICRender/Source/UICRenderShaderCache.cpp +++ b/src/Runtime/Source/UICRender/Source/UICRenderShaderCache.cpp @@ -287,8 +287,12 @@ struct ShaderCache : public IShaderCache void AddShaderExtensionStrings(ShaderType::Enum shaderType, bool isGLES) { - if (isGLES) - m_InsertStr += "#extension GL_OES_standard_derivatives : enable\n"; + if (isGLES) { + if (m_RenderContext.IsStandardDerivativesSupported()) + m_InsertStr += "#extension GL_OES_standard_derivatives : enable\n"; + else + m_InsertStr += "#extension GL_OES_standard_derivatives : disable\n"; + } if (IUICRenderer::IsGlEs3Context(m_RenderContext.GetRenderContextType())) { if (shaderType == ShaderType::TessControl || shaderType == ShaderType::TessEval) { @@ -304,20 +308,20 @@ struct ShaderCache : public IShaderCache } else { if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment || shaderType == ShaderType::Geometry) { - m_InsertStr += "#extension GL_ARB_gpu_shader5 : enable\n"; - m_InsertStr += "#extension GL_ARB_shading_language_420pack : enable\n"; - if (m_RenderContext.IsShaderImageLoadStoreSupported()) { - m_InsertStr += "#extension GL_ARB_shader_image_load_store : enable\n"; + if (m_RenderContext.GetRenderContextType() != NVRenderContextValues::GLES2) { + m_InsertStr += "#extension GL_ARB_gpu_shader5 : enable\n"; + m_InsertStr += "#extension GL_ARB_shading_language_420pack : enable\n"; } - if (m_RenderContext.IsAtomicCounterBufferSupported()) { + if (isGLES && m_RenderContext.IsTextureLodSupported()) + m_InsertStr += "#extension GL_EXT_shader_texture_lod : enable\n"; + if (m_RenderContext.IsShaderImageLoadStoreSupported()) + m_InsertStr += "#extension GL_ARB_shader_image_load_store : enable\n"; + if (m_RenderContext.IsAtomicCounterBufferSupported()) m_InsertStr += "#extension GL_ARB_shader_atomic_counters : enable\n"; - } - if (m_RenderContext.IsStorageBufferSupported()) { + if (m_RenderContext.IsStorageBufferSupported()) m_InsertStr += "#extension GL_ARB_shader_storage_buffer_object : enable\n"; - } - if (m_RenderContext.IsAdvancedBlendHwSupportedKHR()) { + if (m_RenderContext.IsAdvancedBlendHwSupportedKHR()) m_InsertStr += "#extension GL_KHR_blend_equation_advanced : enable\n"; - } } } } @@ -338,7 +342,7 @@ struct ShaderCache : public IShaderCache const QT3DSU32 type = (QT3DSU32)m_RenderContext.GetRenderContextType(); switch (type) { case NVRenderContextValues::GLES2: - stream << "1" << minor << "0 es\n"; + stream << "1" << minor << "0\n"; break; case NVRenderContextValues::GL2: stream << "1" << minor << "0\n"; @@ -390,11 +394,14 @@ struct ShaderCache : public IShaderCache AddBackwardCompatibilityDefines(shaderType); } else { + // GLES2 m_InsertStr.append("precision mediump float;\n" "precision mediump int;\n" - "precision mediump sampler2D;\n" - "precision mediump sampler2DArray;\n" - "precision mediump sampler2DShadow;\n"); + "#define texture texture2D\n"); + if (m_RenderContext.IsTextureLodSupported()) + m_InsertStr.append("#define textureLod texture2DLodEXT\n"); + else + m_InsertStr.append("#define textureLod(s, co, lod) texture2D(s, co)\n"); } } else { if (!IUICRenderer::IsGl2Context(m_RenderContext.GetRenderContextType())) { diff --git a/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp b/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp index 6d72d322..f7855c74 100644 --- a/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp +++ b/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp @@ -37,6 +37,8 @@ #include "UICRenderContext.h" #include "UICRenderDynamicObjectSystem.h" +#include <QtGui/qopengl.h> + using namespace uic::render; namespace { @@ -92,8 +94,10 @@ struct SStageGeneratorBase : public IShaderStageGenerator { m_Incoming.insert(eastl::make_pair(Str(name), Str(type))); } - - virtual const char8_t *GetIncomingVariableName() { return "in"; } + virtual const char8_t *GetIncomingVariableName() + { + return "in"; + } void AddIncoming(const TStrType &name, const char8_t *type) override { @@ -334,6 +338,7 @@ struct SFragmentShaderGenerator : public SStageGeneratorBase : SStageGeneratorBase(inFnd, strTable, ShaderGeneratorStages::Fragment) { } + void AddShaderIncomingMap() override { AddShaderItemMap("varying", m_Incoming); } void AddShaderOutgoingMap() override {} }; diff --git a/src/Runtime/Source/UICRender/Source/UICRenderTextTextureAtlas.cpp b/src/Runtime/Source/UICRender/Source/UICRenderTextTextureAtlas.cpp index 2f11944d..cc027f8d 100644 --- a/src/Runtime/Source/UICRender/Source/UICRenderTextTextureAtlas.cpp +++ b/src/Runtime/Source/UICRender/Source/UICRenderTextTextureAtlas.cpp @@ -89,8 +89,13 @@ struct STextTextureAtlas : public ITextTextureAtlas m_TextureAtlasInitialized = true; m_textureAtlas->addRef(); // if you change the size you need to adjust UICOnscreenTextRenderer too - m_textureAtlas->SetTextureData(NVDataRef<QT3DSU8>(), 0, TEXTURE_ATLAS_DIM, + if (m_RenderContext->GetRenderContextType() == NVRenderContextValues::GLES2) { + m_textureAtlas->SetTextureData(NVDataRef<QT3DSU8>(), 0, TEXTURE_ATLAS_DIM, + TEXTURE_ATLAS_DIM, NVRenderTextureFormats::RGBA8); + } else { + m_textureAtlas->SetTextureData(NVDataRef<QT3DSU8>(), 0, TEXTURE_ATLAS_DIM, TEXTURE_ATLAS_DIM, NVRenderTextureFormats::Alpha8); + } m_textureAtlas->SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear); m_textureAtlas->SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear); m_textureAtlas->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge); diff --git a/src/Runtime/commoninclude.pri b/src/Runtime/commoninclude.pri index 14fca023..3a10070e 100644 --- a/src/Runtime/commoninclude.pri +++ b/src/Runtime/commoninclude.pri @@ -37,7 +37,7 @@ INCLUDEPATH += \ $$PWD/../Authoring/UICDM \ $$PWD/../Authoring/UICDM/Systems \ $$PWD/../Authoring/UICDM/Systems/Cores \ - ../3rdparty/EASTL/UnknownVersion/include \ + $$PWD/../3rdparty/EASTL/UnknownVersion/include \ ../3rdparty/Lua/UnknownVersion/src \ ../3rdparty/utf8cpp/2.3.2/source \ ../3rdparty/color \ diff --git a/src/Runtime/res.qrc b/src/Runtime/res.qrc index 8941190d..b505c08b 100644 --- a/src/Runtime/res.qrc +++ b/src/Runtime/res.qrc @@ -88,6 +88,15 @@ <file>res/effectlib/viewProperties.glsllib</file> <file>res/effectlib/weightedLayer.glsllib</file> <file>res/effectlib/wireframeCM.glsllib</file> + <file>res/effectlib/defaultMaterialFresnelNoDvn.glsllib</file> + <file>res/effectlib/gles2/funcsampleLightVars.glsllib</file> + <file>res/effectlib/gles2/sampleProbe.glsllib</file> + <file>res/effectlib/gles2/SSAOCustomMaterial.glsllib</file> + <file>res/effectlib/gles2/funcareaLightVars.glsllib</file> + <file>res/effectlib/gles2/monoChannel.glsllib</file> + <file>res/effectlib/gles2/shadowMapping.glsllib</file> + <file>res/effectlib/gles2/tangentSpaceNormalTexture.glsllib</file> + <file>res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib</file> <file>res/primitives/Cone.mesh</file> <file>res/primitives/Cube.mesh</file> <file>res/primitives/Cylinder.mesh</file> diff --git a/src/Runtime/res/effectlib/defaultMaterialFresnelNoDvn.glsllib b/src/Runtime/res/effectlib/defaultMaterialFresnelNoDvn.glsllib new file mode 100644 index 00000000..90958a3f --- /dev/null +++ b/src/Runtime/res/effectlib/defaultMaterialFresnelNoDvn.glsllib @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2014 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEFAULT_MATERIAL_FRESNEL_NO_DVN_GLSLLIB +#define DEFAULT_MATERIAL_FRESNEL_NO_DVN_GLSLLIB + +float defaultMaterialSimpleFresnel( in vec3 N, in vec3 viewDir, in float ior, float fresnelPower ) +{ + float F = ((1.0-ior) * (1.0-ior)) / ((1.0+ior) * (1.0+ior)); + float VdotN = dot(viewDir, N); + VdotN = clamp( VdotN, 0.0, 1.0 ); + float ratio = F + (1.0 - F) * pow(1.0 - VdotN, fresnelPower); + return clamp( ratio * pow( VdotN, fresnelPower ), 0.0, 1.0 ); +} + +#endif diff --git a/src/Runtime/res/effectlib/funcdiffuseReflectionBSDF.glsllib b/src/Runtime/res/effectlib/funcdiffuseReflectionBSDF.glsllib index 250056af..bda0ea60 100644 --- a/src/Runtime/res/effectlib/funcdiffuseReflectionBSDF.glsllib +++ b/src/Runtime/res/effectlib/funcdiffuseReflectionBSDF.glsllib @@ -1,31 +1,31 @@ #ifndef PI -#define PI 3.14159265358979f +#define PI 3.14159265358979 #define PI_SQUARE ( PI * PI ) #endif vec4 diffuseReflectionBSDF(in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightDiffuse, in float roughness) { - float cosThetaI = max( 0.0f, dot( N, L ) ); + float cosThetaI = max( 0.0, dot( N, L ) ); float factor = cosThetaI; - if ( ( 0.0f < factor ) && ( 0.0f < roughness ) ) + if ( ( 0.0 < factor ) && ( 0.0 < roughness ) ) { // see http://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model - float sigmaSquare = 0.25f * PI_SQUARE * roughness * roughness; - float A = 1.0f - 0.5f * sigmaSquare / ( sigmaSquare + 0.33f ); - float B = 0.45f * sigmaSquare / ( sigmaSquare + 0.09f ); + float sigmaSquare = 0.25 * PI_SQUARE * roughness * roughness; + float A = 1.0 - 0.5 * sigmaSquare / ( sigmaSquare + 0.33 ); + float B = 0.45 * sigmaSquare / ( sigmaSquare + 0.09 ); // project L and viewDir on surface to get the azimuthal angle between them // as we don't really need the projections, but the angle between them, // it's enough to just use the cross instead vec3 pl = normalize( cross( L, N ) ); vec3 pv = normalize( cross( viewDir, N ) ); - float cosPhi = max( 0.0f, dot( pl, pv ) ); + float cosPhi = max( 0.0, dot( pl, pv ) ); float sinAlpha, tanBeta; - float cosThetaO = max( 0.0f, dot( N, viewDir ) ); - float sinThetaI = sqrt( max( 0.0f, 1.0f - cosThetaI * cosThetaI ) ); - float sinThetaO = sqrt( max( 0.0f, 1.0f - cosThetaO * cosThetaO ) ); + float cosThetaO = max( 0.0, dot( N, viewDir ) ); + float sinThetaI = sqrt( max( 0.0, 1.0 - cosThetaI * cosThetaI ) ); + float sinThetaO = sqrt( max( 0.0, 1.0 - cosThetaO * cosThetaO ) ); if ( cosThetaI < cosThetaO ) { // -> thetaO < thetaI sinAlpha = sinThetaI; @@ -39,5 +39,5 @@ vec4 diffuseReflectionBSDF(in vec3 N, in vec3 L, in vec3 viewDir, factor *= A + B * cosPhi * sinAlpha * tanBeta; } - return( vec4( factor * lightDiffuse, 1.0f ) ); + return( vec4( factor * lightDiffuse, 1.0 ) ); } diff --git a/src/Runtime/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib b/src/Runtime/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib index 3b8f2d9f..9afc58b4 100644 --- a/src/Runtime/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib +++ b/src/Runtime/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib @@ -1,5 +1,5 @@ vec4 diffuseReflectionWrapBSDF(vec3 normalDir, in vec3 L, in vec3 lightDiffuse, float wrap) { float I = max( 0.0, ((dot(L, normalDir) + wrap)/ (1.0 + wrap)) ); //diffuseIntensity - return vec4( I * lightDiffuse, 1.0f ); + return vec4( I * lightDiffuse, 1.0 ); } diff --git a/src/Runtime/res/effectlib/funcspecularBSDF.glsllib b/src/Runtime/res/effectlib/funcspecularBSDF.glsllib index 44e81966..e9450bfe 100644 --- a/src/Runtime/res/effectlib/funcspecularBSDF.glsllib +++ b/src/Runtime/res/effectlib/funcspecularBSDF.glsllib @@ -9,14 +9,14 @@ vec4 specularBSDF(in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightSpecular, in float ior, in float shininess, in vec3 tint, int mode) { - vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 ); float cosTheta = dot( N, L ); - if ( 0.0f < cosTheta ) + if ( 0.0 < cosTheta ) { if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) ) { vec3 R = reflect( -L, N ); - float cosAlpha = max( 0.0f, dot( R, viewDir ) ); + float cosAlpha = max( 0.0, dot( R, viewDir ) ); float shine = pow( cosAlpha, shininess ); rgba.rgb = shine * lightSpecular; } @@ -25,17 +25,17 @@ vec4 specularBSDF(in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightSpecular, { // check against total reflection vec3 R = refract( -viewDir, N, ior ); - if ( R == vec3( 0.0f, 0.0f, 0.0f ) ) + if ( R == vec3( 0.0, 0.0, 0.0 ) ) { - rgba.a = 1.0f; + rgba.a = 1.0; } else if ( mode == scatter_transmit ) { - rgba.a = 0.0f; + rgba.a = 0.0; } else { - rgba.a = 1.0f - luminance( tint ); + rgba.a = 1.0 - luminance( tint ); } } return( rgba ); diff --git a/src/Runtime/res/effectlib/gles2/SSAOCustomMaterial.glsllib b/src/Runtime/res/effectlib/gles2/SSAOCustomMaterial.glsllib new file mode 100644 index 00000000..d3994a61 --- /dev/null +++ b/src/Runtime/res/effectlib/gles2/SSAOCustomMaterial.glsllib @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2014 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SSAO_CUSTOM_MATERIAL_GLSLLIB +#define SSAO_CUSTOM_MATERIAL_GLSLLIB + +#ifndef UIC_ENABLE_SSAO +#define UIC_ENABLE_SSAO 0 +#endif + +#ifndef UIC_ENABLE_SSDO +#define UIC_ENABLE_SSDO 0 +#endif + +#if UIC_ENABLE_SSAO || UIC_ENABLE_SSDO + +#include "viewProperties.glsllib" +#if UIC_ENABLE_SSDO +#include "screenSpaceDO.glsllib" + + +uniform vec4 ao_properties; +uniform vec4 ao_properties2; +uniform vec4 shadow_properties; +uniform vec4 aoScreenConst; +uniform vec4 UvToEyeConst; + + +uniform sampler2D depth_sampler; +#endif +uniform sampler2D ao_sampler; +uniform vec2 ao_sampler_size; + +#endif // UIC_ENABLE_SSAO || UIC_ENABLE_SSDO + +#if UIC_ENABLE_SSAO + +float customMaterialAO() +{ +#if UIC_ENABLE_SSDO + vec2 smpUV = (gl_FragCoord.xy) * aoScreenConst.zw; +#else + vec2 smpUV = gl_FragCoord.xy / ao_sampler_size; +#endif + return texture(ao_sampler, smpUV).x; +} + +#else + +float customMaterialAO() +{ + return 1.0; +} + +#endif + +#if UIC_ENABLE_SSDO + +float customMaterialShadow( vec3 lightDir, vec3 varWorldPos ) +{ + return shadowOcclusion( depth_sampler, lightDir, varWorldPos, view_matrix, view_projection_matrix, shadow_properties, camera_properties, aoScreenConst, UvToEyeConst ); +} + +#else + +float customMaterialShadow( vec3 lightDir, vec3 varWorldPos ) +{ + return 1.0; +} + +#endif + +#endif // #ifndef SSAO_CUSTOM_MATERIAL_GLSLLIB diff --git a/src/Runtime/res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib b/src/Runtime/res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib new file mode 100644 index 00000000..2f3bd150 --- /dev/null +++ b/src/Runtime/res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +float calcRGBAvg(in vec4 rgba) +{ + return (rgba.r + rgba.g + rgba.b) / 3.0; +} + +vec3 defaultMaterialBumpNoLod(in sampler2D sampler, in float factor, + in vec2 texCoord, in vec3 tangent, in vec3 binormal, + in vec3 normal, in vec2 bumpSize ) +{ + // invert factor + float invFactor = -factor; + + vec2 unitStep = 1.0 / bumpSize; + + float du = calcRGBAvg(texture2D( sampler, vec2( texCoord.x + unitStep.x, texCoord.y ))) + - calcRGBAvg(texture2D( sampler, vec2( texCoord.x, texCoord.y ))); + float dv = calcRGBAvg(texture2D( sampler, vec2( texCoord.x, texCoord.y + unitStep.y ))) + - calcRGBAvg(texture2D( sampler, vec2( texCoord.x, texCoord.y ))); + + vec3 n = normalize(vec3(invFactor * du, invFactor * dv, 1.0)); + n = n.x * normalize(tangent) + n.y * normalize(binormal) + n.z * normal; + return normalize(normal + n); +} diff --git a/src/Runtime/res/effectlib/gles2/funcareaLightVars.glsllib b/src/Runtime/res/effectlib/gles2/funcareaLightVars.glsllib new file mode 100644 index 00000000..cdb8c92a --- /dev/null +++ b/src/Runtime/res/effectlib/gles2/funcareaLightVars.glsllib @@ -0,0 +1,29 @@ +#define MAX_AREA_LIGHTS 16 + +// note this struct must exactly match the memory layout of the +// struct SLightSourceShader in the source code. If you make changes here you need +// to adjust the struct SLightSourceShader as well +struct AreaLight +{ + vec4 position; + vec4 direction; // Specifies the light direction in world coordinates. + vec4 up; + vec4 right; + vec4 diffuse; + vec4 ambient; + vec4 specular; + float spotExponent; // Specifies the intensity distribution of the light. + float spotCutoff; // Specifies the maximum spread angle of the light. + float constantAttenuation; // Specifies the constant light attenuation factor. + float linearAttenuation; // Specifies the linear light attenuation factor. + float quadraticAttenuation; // Specifies the quadratic light attenuation factor. + float range; // Specifies the maximum distance of the light influence + float width; // Specifies the width of the area light surface. + float height; // Specifies the height of the area light surface; + vec4 shadowControls; + mat4 shadowView; + int shadowIdx; +}; + +uniform int uNumAreaLights; +uniform AreaLight arealights[MAX_AREA_LIGHTS]; diff --git a/src/Runtime/res/effectlib/gles2/funcsampleLightVars.glsllib b/src/Runtime/res/effectlib/gles2/funcsampleLightVars.glsllib new file mode 100644 index 00000000..6cb0d831 --- /dev/null +++ b/src/Runtime/res/effectlib/gles2/funcsampleLightVars.glsllib @@ -0,0 +1,27 @@ + +#define MAX_NUM_LIGHTS 16 + +struct LightSource +{ + vec4 position; + vec4 direction; // Specifies the light direction in world coordinates. + vec4 up; + vec4 right; + vec4 diffuse; + vec4 ambient; + vec4 specular; + float spotExponent; // Specifies the intensity distribution of the light. + float spotCutoff; // Specifies the maximum spread angle of the light. + float constantAttenuation; // Specifies the constant light attenuation factor. + float linearAttenuation; // Specifies the linear light attenuation factor. + float quadraticAttenuation; // Specifies the quadratic light attenuation factor. + float range; // Specifies the maximum distance of the light influence + float width; // Specifies the width of the area light surface. + float height; // Specifies the height of the area light surface; + vec4 shadowControls; + mat4 shadowView; + int shadowIdx; +}; + +uniform int uNumLights; +uniform LightSource lights[MAX_NUM_LIGHTS]; diff --git a/src/Runtime/res/effectlib/gles2/monoChannel.glsllib b/src/Runtime/res/effectlib/gles2/monoChannel.glsllib new file mode 100644 index 00000000..1460aae1 --- /dev/null +++ b/src/Runtime/res/effectlib/gles2/monoChannel.glsllib @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2014 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MONO_CHANNEL_GLSLLIB +#define MONO_CHANNEL_GLSLLIB + +#ifdef UIC_DEFINE_API +#define mono_alpha 0 +#define mono_average 1 +#define mono_luminance 2 +#define mono_maximum 3 +#endif + +float monoChannel( in vec4 t, const in int monoSource ) +{ + if ( monoSource == mono_alpha ) + return( t.w ); + + if ( monoSource == mono_average ) + return( ( t.x + t.y + t.z ) / 3.0 ); + + if ( monoSource == mono_luminance ) + return( luminance( t.xyz ) ); + + if ( monoSource == mono_maximum ) + return( max( t.x, max( t.y, t.z ) ) ); + + return( 1.0 ); +} + +#endif diff --git a/src/Runtime/res/effectlib/gles2/sampleProbe.glsllib b/src/Runtime/res/effectlib/gles2/sampleProbe.glsllib new file mode 100644 index 00000000..4b328183 --- /dev/null +++ b/src/Runtime/res/effectlib/gles2/sampleProbe.glsllib @@ -0,0 +1,482 @@ +/**************************************************************************** +** +** Copyright (C) 2014 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SAMPLE_PROBE_GLSLLIB +#define SAMPLE_PROBE_GLSLLIB 1 + +#ifndef UIC_ENABLE_LIGHT_PROBE_2 +#define UIC_ENABLE_LIGHT_PROBE_2 0 +#endif + +#ifndef UIC_ENABLE_IBL_FOV +#define UIC_ENABLE_IBL_FOV 0 +#endif + +uniform sampler2D light_probe; +uniform vec4 light_probe_props; +uniform vec4 light_probe_rotation; +uniform vec4 light_probe_offset; // light_probe_offset.w = number of mipmaps +uniform vec2 light_probe_size; + +#if UIC_ENABLE_LIGHT_PROBE_2 +uniform sampler2D light_probe2; +uniform vec4 light_probe2_props; +uniform vec2 light_probe2_size; +#endif + +#if UIC_ENABLE_IBL_FOV +uniform vec4 light_probe_opts; +#endif + +float noise1d(vec2 n) +{ + return 0.5 + 0.5 * fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453); +} + +mat3 orthoNormalize( in mat3 tanFrame ) +{ + mat3 outMat; + outMat[0] = normalize( cross( tanFrame[1], tanFrame[2] ) ); + outMat[1] = normalize( cross( tanFrame[2], outMat[0] ) ); + outMat[2] = tanFrame[2]; + + return outMat; +} + +mat3 tangentFrame( vec3 N, vec3 p ) +{ + // get edge vectors of the pixel triangle + vec3 dp1 = dFdx( p ); + vec3 dp2 = dFdy( p ); + // Using dPdu and dPdv would be nicer, but the nature of our materials + // are not ones with intrinsic UVs, so we can't really go there. +// vec2 duv1 = dFdx( uv ); +// vec2 duv2 = dFdy( uv ); + + // solve the linear system + vec3 dp2perp = cross( dp2, N ); + vec3 dp1perp = cross( N, dp1 ); +// vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; +// vec3 B = dp2perp * duv1.y + dp1perp * duv2.y; + + vec3 T = normalize(dp1perp); + vec3 B = normalize(dp2perp); + return mat3( T , B , N ); +} + +vec2 transformSample( vec2 origUV, vec4 probeRot, vec2 probeOfs ) +{ + vec2 retUV; + retUV.x = dot( vec3(origUV, 1.0), vec3(probeRot.xy, probeOfs.x) ); + retUV.y = dot( vec3(origUV, 1.0), vec3(probeRot.zw, probeOfs.y) ); + return retUV; +} + +// This is broken out into its own routine so that if we get some other +// format image than a lat-long, then we can account for that by changing +// the code here alone. +vec2 getProbeSampleUV( vec3 smpDir, vec4 probeRot, vec2 probeOfs ) +{ + vec2 smpUV; + +#if UIC_ENABLE_IBL_FOV + smpUV.x = (2.0 * atan(-smpDir.z, smpDir.x) + 3.14159265358 ) / light_probe_opts.x; + smpUV.y = (2.0 * atan(-smpDir.z, smpDir.y) + 3.14159265358 ) / light_probe_opts.x; +#else + smpUV.x = atan( smpDir.x, -smpDir.z) / 3.14159265359; + smpUV.y = 1.0 - (acos(smpDir.y) / 1.57079632679); +#endif + smpUV = transformSample( smpUV.xy * 0.5, probeRot, probeOfs ) + vec2(0.5, 0.5); + + return smpUV; +} + +vec4 getTopLayerSample( vec3 inDir, float lodShift, vec3 lodOffsets ) +{ +#if UIC_ENABLE_LIGHT_PROBE_2 + if ( light_probe2_props.w < 0.5 ) + return vec4(0.0, 0.0, 0.0, 0.0); + + vec2 smpUV = getProbeSampleUV( inDir, vec4(1.0, 0.0, 0.0, 1.0), light_probe_props.xy ); + smpUV.x -= 0.5; + smpUV.x *= light_probe2_props.x; + smpUV.x += light_probe2_props.y; + + vec4 retVal = 0.4 * textureLod( light_probe2, smpUV , lodShift ); + retVal += 0.2 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.x ); + retVal += 0.3 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.y ); + retVal += 0.1 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.z ); + return retVal; +#else + return vec4(0.0, 0.0, 0.0, 0.0); +#endif +} + +vec3 getProbeSample( vec3 smpDir, float lodShift, vec3 normal ) +{ + vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy ); + return textureLod( light_probe, smpUV , lodShift ).xyz; +} + +vec3 getProbeWeightedSample( vec3 smpDir, float lodShift, float roughness, vec3 normal ) +{ + // This gives us a weighted sum that approximates the total filter support + // of the full-blown convolution. + vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy ); + float wt = 1.0; + +#if UIC_ENABLE_IBL_FOV + wt = min(wt, smoothstep(roughness * -0.25, roughness * 0.25, smpUV.x)); + wt = min(wt, smoothstep(roughness * -0.25, roughness * 0.25, smpUV.y)); + wt = min(wt, 1.0 - smoothstep(1.0 - roughness*0.25, 1.0 + roughness*0.25, smpUV.x)); + wt = min(wt, 1.0 - smoothstep(1.0 - roughness*0.25, 1.0 + roughness*0.25, smpUV.y)); +#endif + + vec3 lodOffsets; + lodOffsets.x = mix(-2.0, -0.70710678, roughness); + lodOffsets.y = min( 2.0 * smoothstep(0.0, 0.1, roughness), 2.0 - 1.29289 * smoothstep(0.1, 1.0, roughness) ); + lodOffsets.z = min( 6.0 * smoothstep(0.0, 0.1, roughness), 6.0 - 4.585786 * smoothstep(0.1, 1.0, roughness) ); + + ivec2 iSize = ivec2(light_probe_size); + vec3 ddx = dFdx( smpDir ) * float(iSize.x); + vec3 ddy = dFdy( smpDir ) * float(iSize.y); +// vec2 ddxUV = dFdx( smpUV ) * float(iSize.x); +// vec2 ddyUV = dFdy( smpUV ) * float(iSize.y); + + vec2 deriv; + deriv.x = max( dot(ddx, ddx), dot(ddy, ddy) ); +// deriv.y = max( dot(ddxUV, ddxUV), dot(ddyUV, ddyUV) ); + deriv = clamp( deriv, vec2(1.0), vec2(iSize.x * iSize.y) ); + vec2 lodBound = 0.5 * log2( deriv ) - vec2(1.0); + +// float minLod = 0.5 * (lodBound.x + lodBound.y); + float minLod = lodBound.x; + float maxLod = log2( max(float(iSize.x), float(iSize.y)) ); + minLod = clamp( minLod / maxLod, 0.0, 1.0 ); + minLod *= minLod * maxLod; + + lodShift = max( lodShift, minLod ); + + vec3 retVal = 0.4 * textureLod( light_probe, smpUV , lodShift ).xyz; + retVal += 0.2 * textureLod( light_probe, smpUV , max(minLod, lodShift+lodOffsets.x) ).xyz; + retVal += 0.3 * textureLod( light_probe, smpUV , lodShift+lodOffsets.y ).xyz; + retVal += 0.1 * textureLod( light_probe, smpUV , lodShift+lodOffsets.z ).xyz; + +#if UIC_ENABLE_LIGHT_PROBE_2 + vec4 topSmp = getTopLayerSample( smpDir, lodShift, lodOffsets ); + vec3 tempVal = mix( retVal, topSmp.xyz, topSmp.w ); + retVal = mix( retVal, tempVal, light_probe2_props.z ); +#endif + + if (light_probe_props.z > -1.0) { + float ctr = 0.5 + 0.5 * light_probe_props.z; + float vertWt = smoothstep(ctr-roughness*0.25, ctr+roughness*0.25, smpUV.y); + float wtScaled = mix(1.0, vertWt, light_probe_props.z + 1.0); + retVal *= wtScaled; + } + + return retVal * wt; +} + +vec2 textureSizeLod( vec2 size, int level ) +{ + return size / pow(2.0, float(level)); +} + +vec3 getProbeAnisoSample( vec3 smpDir, float roughU, float roughV, mat3 tanFrame ) +{ + float minRough = min(roughU, roughV); + float maxRough = max(roughU, roughV); + + float lodMin = log2( (minRough*3.0 + maxRough)*0.25 ) + (light_probe_offset.w - 2.0); + + float ratio = clamp( maxRough / minRough, 1.01, 27.0); + vec2 texSize = textureSizeLod( light_probe_size, int(floor( lodMin )) ); + texSize = mix( texSize, texSize * 0.5, fract(lodMin) ); + + // Boundary of 1.0..9.0 is just to keep the number of samples to within a + // reasonable number of samples in the filter. Similarly, with the clamping + // of the ratio to a max of 27.0 is just to prevent the step size in the filter + // to be no bigger than 3 texels (beyond which, there are some artifacts at high + // roughness, aka low texture res). + float stepFig = clamp(floor( ratio ), 1.0, 9.0); + + // numSteps is half the number of samples we need to take, which makes it + // the number of steps to take on each side. + int numSteps = int( floor(stepFig * 0.5) ); + + vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy ); + vec4 result = vec4(0.0); + + vec3 smpDirOfs = (maxRough == roughU) ? 0.01 * tanFrame[0] : 0.01 * tanFrame[1]; + vec2 stepPos = getProbeSampleUV(normalize(smpDir + smpDirOfs), light_probe_rotation, light_probe_offset.xy); + vec2 stepNeg = getProbeSampleUV(normalize(smpDir - smpDirOfs), light_probe_rotation, light_probe_offset.xy); + stepPos -= smpUV; stepNeg -= smpUV; + stepPos *= texSize; stepNeg *= texSize; + + // This ensures that we step along a size that makes sense even if one of the two + // sammpling directions wraps around the edges of the IBL texture. + smpDirOfs /= min( length(stepPos), length(stepNeg) ); + smpDirOfs *= ratio / stepFig; + + float sigma = mix(0.0, 2.0, ratio / 27.0); + sigma *= sigma; + + float wt = (1.0 / (ratio - 1.0)) + 1.0; + result.xyz += wt * getProbeWeightedSample( smpDir, lodMin, minRough, tanFrame[2] ); + result.w += wt; + for (int i = 0; i < numSteps; ++i) + { + wt = sigma / (sigma + float(i * i)); + vec2 uv0 = getProbeSampleUV(normalize(smpDir + smpDirOfs * float(i)), light_probe_rotation, light_probe_offset.xy); + vec2 uv1 = getProbeSampleUV(normalize(smpDir - smpDirOfs * float(i)), light_probe_rotation, light_probe_offset.xy); + result.xyz += wt * textureLod( light_probe, uv0 , lodMin ).xyz; + result.w += wt; + result.xyz += wt * textureLod( light_probe, uv1 , lodMin ).xyz; + result.w += wt; + } + + result /= result.w; + return result.xyz; +} + +vec4 sampleDiffuse( mat3 tanFrame ) +{ + if ( light_probe_props.w < 0.005 ) + return vec4( 0.0 ); + +// if ( light_probe_offset.w > 0.5 ) +// { + // The LOD offset comes from the assumption that a full diffuse convolution + // has a support of pi/2, which translates into x pixels, and the base 2 log + // gives us this LOD... Technically, "x" pixels depends on what the original + // texture resolution was, which is why we use light_probe_offset.w, which holds + // the number of mip levels the texture has. + + return vec4( light_probe_props.w * getProbeWeightedSample( tanFrame[2], light_probe_offset.w - 2.65149613, 1.0, tanFrame[2] ), 1.0 ); +// } + + /* + // PKC -- the code below is for full-blown IBL, which we'll skip for now + + // Hand-calculated Hammersley points for t = 2, n = 33 + // I exclude the 0,0 first point, hence why n=33 and not 32 + // Nice thing about 2d Hammersley points is that any subset is + // also stratified, so even if I have 1000 points and truncate + // anywhere, I'm fine. Each of these represent the y of an xy + // while x for the kth point is always (k+1)/n. + float kernel[32]; + kernel[0] = 0.5; kernel[1] = 0.25; + kernel[2] = 0.75; kernel[3] = 0.125; + kernel[4] = 0.625; kernel[5] = 0.375; + kernel[6] = 0.875; kernel[7] = 0.0625; + kernel[8] = 0.5625; kernel[9] = 0.3125; + kernel[10] = 0.8125; kernel[11] = 0.1875; + kernel[12] = 0.6875; kernel[13] = 0.4375; + kernel[14] = 0.9375; kernel[15] = 0.03125; + kernel[16] = 0.53125; kernel[17] = 0.28125; + kernel[18] = 0.78125; kernel[19] = 0.15625; + kernel[20] = 0.65625; kernel[21] = 0.40625; + kernel[22] = 0.90625; kernel[23] = 0.09375; + kernel[24] = 0.59375; kernel[25] = 0.34375; + kernel[26] = 0.84375; kernel[27] = 0.28175; + kernel[28] = 0.71875; kernel[29] = 0.46875; + kernel[30] = 0.96875; kernel[31] = 0.015625; + + float phiShift = noise1d(gl_FragCoord.xy) - 0.5; + + vec3 ret = vec3(0, 0, 0); + + int ct = 24; + float step = 25.0; + + // Importance sampling a cosine-weighted distribution. Since this + // matches the BSDF exactly, we are just going to assume that the PDF + // and the BSDF cancel out in sampling, so we just need to accumulate + // texture colors. The noise function puts randomized "twist" into + // the sampled directions. + for( int i = 0; i < ct; ++i ) + { + vec3 localDir; + float phi = 6.28318530718 * (kernel[i] + phiShift); + float cosTheta = sqrt( float(i+1) / step); + localDir.z = sqrt(1.0 - cosTheta*cosTheta); + localDir.x = cos(phi) * cosTheta; + localDir.y = sin(phi) * cosTheta; + vec3 smpDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z; + + + float lodShift = light_probe_offset.w - 2 + log2( 3.1415926535 / (localDir.z * step) ); + vec3 smpColor = getProbeSample( smpDir, lodShift, tanFrame[2] ); + + // The assumption here is that the BSDF and the sampling PDF are identical + // so they cancel out and therefore, we don't need to include it here. + ret += smpColor; + } + + ret *= aoFactor / 24.0; + return ret; + */ +} + +vec4 sampleDiffuseCustomMaterial( vec3 normal, vec3 worldPos, float aoFactor ) +{ + + mat3 tanFrame = tangentFrame( normal, worldPos ); + return sampleDiffuse( tanFrame ); +} + +vec4 sampleGlossyAniso( mat3 tanFrame, vec3 viewDir, float roughU, float roughV ) +{ + if ( light_probe_props.w < 0.005 ) + return vec4( 0.0 ); + + // PKC : If we do the full IBL sampling, it's useful to square the roughnesses because + // it makes the effect of roughness feel more linear in the low end. This isn't necessary + // for fast IBL. +// float sigmaU = clamp(roughU*roughU, 0.0001, 1.0); +// float sigmaV = clamp(roughV*roughV, 0.0001, 1.0); + float sigmaU = smoothstep( 0.0, 1.0, clamp(roughU, 0.0001, 1.0) ); + float sigmaV = smoothstep( 0.0, 1.0, clamp(roughV, 0.0001, 1.0) ); + vec3 ret = vec3(0, 0, 0); + +// if ( light_probe_offset.w > 0.5 ) +// { + vec3 smpDir = reflect( -viewDir, tanFrame[2] ); + float sigma = sqrt(sigmaU * sigmaV); + + // Compute the Geometric occlusion/self-shadowing term + float NdotL = clamp( dot( smpDir, tanFrame[2] ), 0.0, 0.999995); + float k = sigma * 0.31830988618; // roughness / pi + float Gl = clamp( (NdotL / (NdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 ); + + vec3 outColor; + + outColor = getProbeAnisoSample( smpDir, sigmaU, sigmaV, tanFrame ); + + return vec4( light_probe_props.w * Gl * outColor, 1.0 ); +// } + + // PKC -- the code below is for full-blown IBL, which we'll skip for now + +/* + float step = clamp( ceil(32.0 * sqrt(max(sigmaU, sigmaV))), 4.0, 32.0 ); + int actualCt = int(step); + float phiShift = noise1d(gl_FragCoord.xy) - 0.5; + + // Hand-calculated Hammersley points for t = 2, n = 33 + // I exclude the 0,0 first point, hence why n=33 and not 32 + // Nice thing about 2d Hammersley points is that any subset is + // also stratified, so even if I have 1000 points and truncate + // anywhere, I'm fine. Each of these represent the y of an xy + // while x for the kth point is always (k+1)/n. + float kernel[32]; + kernel[0] = 0.5; kernel[1] = 0.25; + kernel[2] = 0.75; kernel[3] = 0.125; + kernel[4] = 0.625; kernel[5] = 0.375; + kernel[6] = 0.875; kernel[7] = 0.0625; + kernel[8] = 0.5625; kernel[9] = 0.3125; + kernel[10] = 0.8125; kernel[11] = 0.1875; + kernel[12] = 0.6875; kernel[13] = 0.4375; + kernel[14] = 0.9375; kernel[15] = 0.03125; + kernel[16] = 0.53125; kernel[17] = 0.28125; + kernel[18] = 0.78125; kernel[19] = 0.15625; + kernel[20] = 0.65625; kernel[21] = 0.40625; + kernel[22] = 0.90625; kernel[23] = 0.09375; + kernel[24] = 0.59375; kernel[25] = 0.34375; + kernel[26] = 0.84375; kernel[27] = 0.28175; + kernel[28] = 0.71875; kernel[29] = 0.46875; + kernel[30] = 0.96875; kernel[31] = 0.015625; + + float thetaI = acos( dot(viewDir, tanFrame[2]) ); + + // NOTE : The model I'm using here is actually based on the KGGX model used in + // physGlossyBSDF. This is my own variation on the original GGX which uses something + // closer to a pure Cauchy distribution in tangent space, but also supports anisotropy. + for (int i = 0; i < actualCt; ++i) + { + vec3 localDir; + + float phi = 6.28318530718 * (kernel[i] + phiShift); + float u = float(i + 1) / (step + 1.0); + float rU = cos(phi) * sigmaU; + float rV = sin(phi) * sigmaV; + float sigma = sqrt(rU * rU + rV * rV); + + float boundA = atan( ((thetaI - 1.57079632679) * 0.5) / sigma ); + float boundB = atan( ((thetaI + 1.57079632679) * 0.5) / sigma ); + float t = (1.0 - u) * boundA + u * boundB; + float thetaH = tan( t ) * sigma; + + float cosThetaH = cos( thetaH ); + float sinThetaH = sin( thetaH ); + localDir.z = cosThetaH; + localDir.y = sin(phi) * sinThetaH; + localDir.x = cos(phi) * sinThetaH; + + vec3 halfDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z; + halfDir = normalize(halfDir); + vec3 smpDir = reflect( -viewDir, halfDir ); + + vec2 scaledXY = localDir.xy / vec2(sigmaU, sigmaV); + float PDF = (sigmaU*sigmaV) / (sigmaU*sigmaV + dot(scaledXY, scaledXY)); + vec3 Haf = smpDir + viewDir; // We need the unnormalized half vecter as well as the normalized one + float HdotL = dot(halfDir, smpDir); + // normalize the PDF to compute the filter support + // This gives us the ideal miplevel at which to sample the texture map. + PDF *= dot(Haf, Haf) / (4.0 * dot(Haf, smpDir) * HdotL * sigmaU*sigmaV * (boundB-boundA)*(boundB-boundA)); + + // Again assuming that the pdf and BSDF are equivalent -- that's not generally valid, + // but it saves a lot of ALU cycles. + float lodShift = log2( 512.0 * sigma / PDF ); + + float k = sigma * 0.31830988618; // roughness / pi + float Gl = clamp( (HdotL / (HdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 ); + + vec3 smpColor = Gl * getProbeSample( smpDir, lodShift, tanFrame[2] ); + ret += smpColor; + } + ret /= float(actualCt); + return vec4(ret, 1.0); +*/ +} + +vec4 sampleGlossy( mat3 tanFrame, vec3 viewDir, float roughness ) +{ + return sampleGlossyAniso( tanFrame, viewDir, roughness, roughness ); +} + +vec4 sampleGlossyCustomMaterial( vec3 normal, vec3 worldPos, vec3 viewDir, float roughness ) +{ + mat3 tanFrame = tangentFrame( normal, worldPos ); + return sampleGlossy( tanFrame, viewDir, roughness ); +} + +#endif diff --git a/src/Runtime/res/effectlib/gles2/shadowMapping.glsllib b/src/Runtime/res/effectlib/gles2/shadowMapping.glsllib new file mode 100644 index 00000000..183ef974 --- /dev/null +++ b/src/Runtime/res/effectlib/gles2/shadowMapping.glsllib @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2014 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHADOW_MAPPING_GLSLLIB +#define SHADOW_MAPPING_GLSLLIB + +#include "depthpass.glsllib" + +float sampleParaboloid( in sampler2D shadowMap, in vec4 shadowControls, in mat4 shadowMatrix, in vec3 worldPos, in vec2 cameraProps, out vec2 smpUV ) +{ + vec4 projCoord = shadowMatrix * vec4( worldPos, 1.0 ); + vec3 smpCoord = projCoord.xyz / projCoord.w; + + float ptDepth = depthValueToLinearDistance( 1.0 - smpCoord.z, cameraProps ); + ptDepth = (ptDepth - cameraProps.x) / (cameraProps.y - cameraProps.x); + smpCoord = normalize( smpCoord.xyz ); + smpCoord.xy /= -( smpCoord.z + 1.0 ); + smpCoord.xy = vec2(1.0) - smpCoord.xy; + smpCoord.xy *= 0.5; + + smpUV = smpCoord.xy; // This is just for debug purposes to ensure what the sampled UV cooord is. + + float sampleDepth = texture( shadowMap, smpCoord.xy ).x + shadowControls.x; + sampleDepth *= sampleDepth; + ptDepth *= ptDepth; + float shadowFac = min(1.0, exp(shadowControls.y * sampleDepth * sampleDepth) / exp(shadowControls.y * ptDepth * ptDepth)); + + smpUV.xy *= shadowFac; + return shadowFac; +} + +float sampleCubemap( in samplerCube shadowCube, in vec4 shadowControls, in mat4 shadowViewMat, in vec3 lightPos, in vec3 worldPos, in vec2 cameraProps ) +{ + vec3 viewDir = worldPos - vec3(lightPos.x, lightPos.y, lightPos.z); + float ptDepth = length(viewDir.xyz); + vec4 viewCoord = shadowViewMat * vec4( viewDir.xyz, 0.0 ); + viewCoord.xyz /= ptDepth; + ptDepth = clamp((ptDepth - 1.0) / (cameraProps.y - 1.0), 0.0, 1.0); + + float smpDepth = textureCube( shadowCube, viewDir.xyz ).x + shadowControls.x; + + float shadowFac = min(1.0, exp(shadowControls.y * smpDepth) / exp(shadowControls.y * ptDepth)); + return shadowFac; +} + +float sampleOrthographic( in sampler2D shadowMap, in vec4 shadowControls, in mat4 shadowMatrix, in vec3 worldPos, in vec2 cameraProps ) +{ + vec4 projCoord = shadowMatrix * vec4( worldPos, 1.0 ); + vec3 smpCoord = projCoord.xyz / projCoord.w; + + float sampleDepth = texture( shadowMap, smpCoord.xy ).x + shadowControls.x; + + return min(1.0, exp(shadowControls.y * sampleDepth) / exp(shadowControls.y * smpCoord.z)); +} + + +struct ParaboloidMapResult +{ + vec4 m_Position; + vec4 m_WorldPos; +}; + +ParaboloidMapResult VertexParaboloidDepth(vec3 pos, mat4 inMVP) +{ + vec4 glPos = inMVP * vec4( pos, 1.0 ); + glPos /= glPos.w; + glPos.xyz = normalize( glPos.xyz ); + vec4 world_pos; + world_pos.w = glPos.z; + glPos.xy /= glPos.z + 1.0; + world_pos.xyz = pos.xyz; + + ParaboloidMapResult retval; + retval.m_Position = glPos; + retval.m_WorldPos = world_pos; + return retval; +} + +#endif diff --git a/src/Runtime/res/effectlib/gles2/tangentSpaceNormalTexture.glsllib b/src/Runtime/res/effectlib/gles2/tangentSpaceNormalTexture.glsllib new file mode 100644 index 00000000..fd0a1415 --- /dev/null +++ b/src/Runtime/res/effectlib/gles2/tangentSpaceNormalTexture.glsllib @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FILE_NORMAL_TEXTURE_GLSLLIB +#define FILE_NORMAL_TEXTURE_GLSLLIB + +#ifdef UIC_DEFINE_API + +#include "luminance.glsllib" +#include "monoChannel.glsllib" +#include "textureCoordinateInfo.glsllib" +#define wrap_clamp 0 +#define wrap_repeat 1 +#define wrap_mirrored_repeat 2 +#include "rotationTranslationScale.glsllib" +#include "transformCoordinate.glsllib" + +#endif + +int modulo(int a, int b) +{ + int k = (a / b); + return a - k*b; +} + +//interpreting the color values of a bitmap as a vector in tangent space +vec3 tangentSpaceNormalTexture( in sampler2D tex, in float factor, in bool flipTangentU, in bool flipTangentV + , in texture_coordinate_info uvw, in vec2 cropU, in vec2 cropV, in int wrapU, in int wrapV ) +{ + // if we mirror repeat a tangent space texture, tangent space needs to be flipped for every other tile + bool flipU = flipTangentU; + bool flipV = flipTangentV; + if ( wrapU == wrap_mirrored_repeat ) + { + if ( ( ( 0.0 < uvw.position.x ) && ( modulo(int( uvw.position.x ), 2) == 1 ) ) + || ( ( uvw.position.x < 0.0 ) && ( modulo(int( uvw.position.x ), 2) == 0 ) ) ) + { + flipU = !flipU; + } + if ( ( ( 0.0 < uvw.position.y ) && ( modulo(int( uvw.position.y ), 2) == 1 ) ) + || ( ( uvw.position.y < 0.0 ) && ( modulo(int( uvw.position.y ), 2) == 0 ) ) ) + { + flipV = !flipV; + } + } + + vec3 tangent = 2.0 * texture( tex, uvw.position.xy ).xyz - 1.0; + + vec3 tangentU = normalize( flipU ? -uvw.tangent_u : uvw.tangent_u ); + vec3 tangentV = normalize( flipV ? -uvw.tangent_v : uvw.tangent_v ); + vec3 normal = normalize( cross( tangentU, tangentV ) ); + + return( mix( normal, normalize( tangent.x * tangentU - tangent.y * tangentV + tangent.z * normal ), factor ) ); +} + +#include "textureCoordinateInfo.glsllib" + +//Simpler version built to run from UIC image data +//In our case, we have already generated the texture coordinate x,y position +//TODO - figure out if we need to manipulate tangent_u, tangent_v. +vec3 uicDefaultMaterialFileNormalTexture( in sampler2D sampler, in float factor, vec2 texCoord, vec3 tangent, vec3 binormal ) +{ + // factor should be in [0,1] range + return tangentSpaceNormalTexture( sampler, clamp(factor, 0.0, 1.0), false, false + , textureCoordinateInfo( vec3( texCoord.x, texCoord.y, 0.0 ), tangent, binormal ) + , vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ) + , wrap_repeat, wrap_repeat); +} + +#endif diff --git a/src/Runtime/res/effectlib/monoChannel.glsllib b/src/Runtime/res/effectlib/monoChannel.glsllib index 1ae6d529..e609e68c 100644 --- a/src/Runtime/res/effectlib/monoChannel.glsllib +++ b/src/Runtime/res/effectlib/monoChannel.glsllib @@ -45,14 +45,14 @@ float monoChannel( in vec4 t, in int monoSource ) case mono_alpha : return( t.w ); case mono_average : - return( ( t.x + t.y + t.z ) / 3.0f ); + return( ( t.x + t.y + t.z ) / 3.0 ); case mono_luminance : return( luminance( t.xyz ) ); case mono_maximum : return( max( t.x, max( t.y, t.z ) ) ); default : - return( 1.0f ); + return( 1.0 ); } } -#endif
\ No newline at end of file +#endif diff --git a/src/Runtime/res/effectlib/physGlossyBSDF.glsllib b/src/Runtime/res/effectlib/physGlossyBSDF.glsllib index d94bc26a..ad805960 100644 --- a/src/Runtime/res/effectlib/physGlossyBSDF.glsllib +++ b/src/Runtime/res/effectlib/physGlossyBSDF.glsllib @@ -53,7 +53,7 @@ float Gterm( float cosTheta, float roughness ) vec4 kggxGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, float ior, in float roughnessU, in float roughnessV, int mode ) { - vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 ); vec3 H = normalize(L + V); // NOTE : This BSDF allows roughness up to 2.0 which allows it @@ -113,7 +113,7 @@ vec4 kggxGlossyDefaultMtl( in vec3 normal, in vec3 tangent, in vec3 L, in vec3 V vec4 wardGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior, in float roughnessU, in float roughnessV, int mode ) { - vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 ); vec3 H = normalize(L + V); // specular diff --git a/src/Runtime/res/effectlib/rotationTranslationScale.glsllib b/src/Runtime/res/effectlib/rotationTranslationScale.glsllib index 8abc8c9e..78bb8dd1 100644 --- a/src/Runtime/res/effectlib/rotationTranslationScale.glsllib +++ b/src/Runtime/res/effectlib/rotationTranslationScale.glsllib @@ -33,18 +33,18 @@ mat4 rotationTranslationScale( in vec3 rotation, in vec3 translation, in vec3 scaling ) { - mat4 st = mat4( scaling.x, 0.0f, 0.0f, 0.0f - , 0.0f, scaling.y, 0.0f, 0.0f - , 0.0f, 0.0f, scaling.z, 0.0f - , translation.x - 0.5f, translation.y - 0.5f, translation.z - 0.5f, 1.0f ); + mat4 st = mat4( scaling.x, 0.0, 0.0, 0.0 + , 0.0, scaling.y, 0.0, 0.0 + , 0.0, 0.0, scaling.z, 0.0 + , translation.x - 0.5, translation.y - 0.5, translation.z - 0.5, 1.0 ); vec3 s = sin( rotation ); vec3 c = cos( rotation ); - mat4 r = mat4( c.y * c.z, -c.x * s.z + s.x * s.y * c.z, s.x * s.z + c.x * s.y * c.z, 0.0f - , c.y * s.z, c.x * c.z + s.x * s.y * s.z, -s.x * c.z + c.x * s.y * s.z, 0.0f - , -s.y , s.x * c.y , c.x * c.y , 0.0f - , 0.5f , 0.5f , 0.5f , 1.0f ); + mat4 r = mat4( c.y * c.z, -c.x * s.z + s.x * s.y * c.z, s.x * s.z + c.x * s.y * c.z, 0.0 + , c.y * s.z, c.x * c.z + s.x * s.y * s.z, -s.x * c.z + c.x * s.y * s.z, 0.0 + , -s.y , s.x * c.y , c.x * c.y , 0.0 + , 0.5 , 0.5 , 0.5 , 1.0 ); return( st * r ); } -#endif
\ No newline at end of file +#endif diff --git a/src/Runtime/res/effectlib/tangentSpaceNormalTexture.glsllib b/src/Runtime/res/effectlib/tangentSpaceNormalTexture.glsllib index 853a8601..2b7aacdc 100644 --- a/src/Runtime/res/effectlib/tangentSpaceNormalTexture.glsllib +++ b/src/Runtime/res/effectlib/tangentSpaceNormalTexture.glsllib @@ -53,19 +53,19 @@ vec3 tangentSpaceNormalTexture( in sampler2D tex, in float factor, in bool flipT bool flipV = flipTangentV; if ( wrapU == wrap_mirrored_repeat ) { - if ( ( ( 0.0f < uvw.position.x ) && ( int( uvw.position.x ) % 2 == 1 ) ) - || ( ( uvw.position.x < 0.0f ) && ( int( uvw.position.x ) % 2 == 0 ) ) ) + if ( ( ( 0.0 < uvw.position.x ) && ( int( uvw.position.x ) % 2 == 1 ) ) + || ( ( uvw.position.x < 0.0 ) && ( int( uvw.position.x ) % 2 == 0 ) ) ) { flipU = !flipU; } - if ( ( ( 0.0f < uvw.position.y ) && ( int( uvw.position.y ) % 2 == 1 ) ) - || ( ( uvw.position.y < 0.0f ) && ( int( uvw.position.y ) % 2 == 0 ) ) ) + if ( ( ( 0.0 < uvw.position.y ) && ( int( uvw.position.y ) % 2 == 1 ) ) + || ( ( uvw.position.y < 0.0 ) && ( int( uvw.position.y ) % 2 == 0 ) ) ) { flipV = !flipV; } } - vec3 tangent = 2.0f * texture( tex, uvw.position.xy ).xyz - 1.0f; + vec3 tangent = 2.0 * texture( tex, uvw.position.xy ).xyz - 1.0; vec3 tangentU = normalize( flipU ? -uvw.tangent_u : uvw.tangent_u ); vec3 tangentV = normalize( flipV ? -uvw.tangent_v : uvw.tangent_v ); diff --git a/src/Runtime/res/effectlib/transformCoordinate.glsllib b/src/Runtime/res/effectlib/transformCoordinate.glsllib index 53237d02..ccdf7d0a 100644 --- a/src/Runtime/res/effectlib/transformCoordinate.glsllib +++ b/src/Runtime/res/effectlib/transformCoordinate.glsllib @@ -34,10 +34,10 @@ texture_coordinate_info transformCoordinate( in mat4 transform, in texture_coordinate_info coordinate ) { texture_coordinate_info tci; - tci.position = ( transform * vec4( coordinate.position, 1.0f ) ).xyz; - tci.tangent_u = ( transform * vec4( coordinate.tangent_u, 0.0f ) ).xyz; - tci.tangent_v = ( transform * vec4( coordinate.tangent_v, 0.0f ) ).xyz; + tci.position = ( transform * vec4( coordinate.position, 1.0 ) ).xyz; + tci.tangent_u = ( transform * vec4( coordinate.tangent_u, 0.0 ) ).xyz; + tci.tangent_v = ( transform * vec4( coordinate.tangent_v, 0.0 ) ).xyz; return( tci ); } -#endif
\ No newline at end of file +#endif diff --git a/tests/auto/runtime/Qt3DSRenderTestBase.cpp b/tests/auto/runtime/Qt3DSRenderTestBase.cpp index 24712ec8..99748916 100644 --- a/tests/auto/runtime/Qt3DSRenderTestBase.cpp +++ b/tests/auto/runtime/Qt3DSRenderTestBase.cpp @@ -46,6 +46,32 @@ bool NVRenderTestBase::initializeUICRenderer(QSurfaceFormat format) m_rc = m_factory->GetUICRenderContext(); m_renderImpl = new uic::render::CUICRendererImpl(*m_rc); + QString versionString; + switch ((QT3DSU32)m_rc->GetRenderContext().GetRenderContextType()) { + case NVRenderContextValues::GLES2: + versionString = QLatin1Literal("gles2"); + break; + case NVRenderContextValues::GL2: + versionString = QLatin1Literal("gl2"); + break; + case NVRenderContextValues::GLES3: + versionString = QLatin1Literal("gles3"); + break; + case NVRenderContextValues::GL3: + versionString = QLatin1Literal("gl3"); + break; + case NVRenderContextValues::GLES3PLUS: + versionString = QLatin1Literal("gles3x"); + break; + case NVRenderContextValues::GL4: + versionString = QLatin1Literal("gl4"); + break; + default: + break; + } + + m_rc->GetDynamicObjectSystem().setShaderCodeLibraryVersion(versionString); + return true; } diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp index a76a2de8..6e5dcf00 100644 --- a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp +++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp @@ -224,7 +224,7 @@ struct CustomTestKey #define MAX_TEST_KEY ((1llu<<20)-1) -CustomTestKey randomizeTestKey() +static CustomTestKey randomizeTestKey() { uint64_t v = (uint64_t(qrand()))%MAX_TEST_KEY; return *reinterpret_cast<CustomTestKey*>(&v); diff --git a/tests/auto/runtime/tst_qt3dsruntime.cpp b/tests/auto/runtime/tst_qt3dsruntime.cpp index f272d7ea..32a5fb96 100644 --- a/tests/auto/runtime/tst_qt3dsruntime.cpp +++ b/tests/auto/runtime/tst_qt3dsruntime.cpp @@ -168,7 +168,9 @@ bool tst_qt3dsruntime::init(QSurfaceFormat format) bool tst_qt3dsruntime::init() { -#if defined(Q_OS_ANDROID) +#if defined(QT_OPENGL_ES_2) + return init(makeFormat(2, 0, true, false)); +#elif defined(Q_OS_ANDROID) || defined(QT_OPENGL_ES_3) return init(makeFormat(3, 2, true, false)); #else return init(makeFormat(4, 3)); @@ -459,7 +461,67 @@ void tst_qt3dsruntime::testNVRenderTestProgramPipeline() cleanup(); } -#if !defined(Q_OS_ANDROID) +#if defined(QT_OPENGL_ES_2) +void tst_qt3dsruntime::testRenderDefaultShaderGenerator_200es() +{ + if (init(makeFormat(2, 0, true, false))) { + runDefaultShaderGeneratorTest(); + cleanup(); + } +} +void tst_qt3dsruntime::testRenderCustomShaderGenerator_200es() +{ + runCustomShaderGeneratorTest(makeFormat(2, 0, true, false)); + cleanup(); +} +#endif + +#if defined(QT_OPENGL_ES_3) +void tst_qt3dsruntime::testRenderDefaultShaderGenerator_300es() +{ + if (init(makeFormat(3, 0, true, false))) { + runDefaultShaderGeneratorTest(); + cleanup(); + } +} +void tst_qt3dsruntime::testRenderCustomShaderGenerator_300es() +{ + runCustomShaderGeneratorTest(makeFormat(3, 0, true, false)); + cleanup(); +} + +#if defined(QT_FEATURE_opengles31) +void tst_qt3dsruntime::testRenderDefaultShaderGenerator_310es() +{ + if (init(makeFormat(3, 1, true, false))) { + runDefaultShaderGeneratorTest(); + cleanup(); + } +} +void tst_qt3dsruntime::testRenderCustomShaderGenerator_310es() +{ + runCustomShaderGeneratorTest(makeFormat(3, 1, true, false)); + cleanup(); +} +#endif +#if defined(QT_FEATURE_opengles32) +void tst_qt3dsruntime::testRenderDefaultShaderGenerator_320es() +{ + if (init(makeFormat(3, 1, true, false))) { + runDefaultShaderGeneratorTest(); + cleanup(); + } +} +void tst_qt3dsruntime::testRenderCustomShaderGenerator_320es() +{ + runCustomShaderGeneratorTest(makeFormat(3, 1, true, false)); + cleanup(); +} + +#endif +#endif + +#if defined(QT_OPENGL_DYNAMIC) void tst_qt3dsruntime::testRenderDefaultShaderGenerator_300() { QSKIP("OpenGL 3.0 is not supported"); @@ -566,21 +628,6 @@ void tst_qt3dsruntime::testRenderCustomShaderGenerator_430() runCustomShaderGeneratorTest(makeFormat(4, 3)); } -#else - -void tst_qt3dsruntime::testRenderDefaultShaderGenerator_320es() -{ - if (init(makeFormat(3, 2, true, false))) { - runDefaultShaderGeneratorTest(); - cleanup(); - } -} - -void tst_qt3dsruntime::testRenderCustomShaderGenerator_320es() -{ - runCustomShaderGeneratorTest(makeFormat(3, 2, true, false)); -} - #endif void tst_qt3dsruntime::runDefaultShaderGeneratorTest() diff --git a/tests/auto/runtime/tst_qt3dsruntime.h b/tests/auto/runtime/tst_qt3dsruntime.h index a6370d75..1f5b943e 100644 --- a/tests/auto/runtime/tst_qt3dsruntime.h +++ b/tests/auto/runtime/tst_qt3dsruntime.h @@ -85,7 +85,24 @@ private Q_SLOTS: void testRenderEffectGenerator(); -#if !defined(Q_OS_ANDROID) +#if defined(QT_OPENGL_ES_2) + void testRenderDefaultShaderGenerator_200es(); + void testRenderCustomShaderGenerator_200es(); +#endif +#if defined(QT_OPENGL_ES_3) + void testRenderDefaultShaderGenerator_300es(); + void testRenderCustomShaderGenerator_300es(); +#if defined(QT_FEATURE_opengles31) + void testRenderDefaultShaderGenerator_310es(); + void testRenderCustomShaderGenerator_310es(); +#endif +#if defined(QT_FEATURE_opengles32) + void testRenderDefaultShaderGenerator_320es(); + void testRenderCustomShaderGenerator_320es(); +#endif +#endif + +#if defined(QT_OPENGL_DYNAMIC) void testRenderDefaultShaderGenerator_300(); void testRenderDefaultShaderGenerator_310(); void testRenderDefaultShaderGenerator_320(); @@ -103,9 +120,6 @@ private Q_SLOTS: void testRenderCustomShaderGenerator_410(); void testRenderCustomShaderGenerator_420(); void testRenderCustomShaderGenerator_430(); -#else - void testRenderDefaultShaderGenerator_320es(); - void testRenderCustomShaderGenerator_320es(); #endif |