| 1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
| 2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
| 3 | #pragma once |
| 4 | |
| 5 | #include "BsGLPrerequisites.h" |
| 6 | #include "RenderAPI/BsRenderAPI.h" |
| 7 | #include "BsGLHardwareBufferManager.h" |
| 8 | #include "GLSL/BsGLSLProgramFactory.h" |
| 9 | #include "Math/BsMatrix4.h" |
| 10 | |
| 11 | namespace bs { namespace ct |
| 12 | { |
| 13 | /** @addtogroup GL |
| 14 | * @{ |
| 15 | */ |
| 16 | |
| 17 | /** Implementation of a render system using OpenGL. Provides abstracted access to various low level OpenGL methods. */ |
| 18 | class GLRenderAPI : public RenderAPI |
| 19 | { |
| 20 | public: |
| 21 | GLRenderAPI(); |
| 22 | ~GLRenderAPI() = default; |
| 23 | |
| 24 | /** @copydoc RenderAPI::getName() */ |
| 25 | const StringID& getName() const override; |
| 26 | |
| 27 | /** @copydoc RenderAPI::setGraphicsPipeline */ |
| 28 | void setGraphicsPipeline(const SPtr<GraphicsPipelineState>& pipelineState, |
| 29 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 30 | |
| 31 | /** @copydoc RenderAPI::setComputePipeline */ |
| 32 | void setComputePipeline(const SPtr<ComputePipelineState>& pipelineState, |
| 33 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 34 | |
| 35 | /** @copydoc RenderAPI::setGpuParams() */ |
| 36 | void setGpuParams(const SPtr<GpuParams>& gpuParams, |
| 37 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 38 | |
| 39 | /** @copydoc RenderAPI::setViewport() */ |
| 40 | void setViewport(const Rect2& area, const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 41 | |
| 42 | /** @copydoc RenderAPI::setScissorRect() */ |
| 43 | void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom, |
| 44 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 45 | |
| 46 | /** @copydoc RenderAPI::setStencilRef */ |
| 47 | void setStencilRef(UINT32 value, const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 48 | |
| 49 | /** @copydoc RenderAPI::setVertexBuffers() */ |
| 50 | void setVertexBuffers(UINT32 index, SPtr<VertexBuffer>* buffers, UINT32 numBuffers, |
| 51 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 52 | |
| 53 | /** @copydoc RenderAPI::setIndexBuffer() */ |
| 54 | void setIndexBuffer(const SPtr<IndexBuffer>& buffer, |
| 55 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 56 | |
| 57 | /** @copydoc RenderAPI::setVertexDeclaration() */ |
| 58 | void setVertexDeclaration(const SPtr<VertexDeclaration>& vertexDeclaration, |
| 59 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 60 | |
| 61 | /** @copydoc RenderAPI::setDrawOperation() */ |
| 62 | void setDrawOperation(DrawOperationType op, const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 63 | |
| 64 | /** @copydoc RenderAPI::draw() */ |
| 65 | void draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0, |
| 66 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 67 | |
| 68 | /** @copydoc RenderAPI::drawIndexed() */ |
| 69 | void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount |
| 70 | , UINT32 instanceCount = 0, const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 71 | |
| 72 | /** @copydoc RenderAPI::dispatchCompute() */ |
| 73 | void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1, |
| 74 | const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 75 | |
| 76 | /** @copydoc RenderAPI::swapBuffers() */ |
| 77 | void swapBuffers(const SPtr<RenderTarget>& target, UINT32 syncMask = 0xFFFFFFFF) override; |
| 78 | |
| 79 | /** @copydoc RenderAPI::setRenderTarget() */ |
| 80 | void setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags = 0, |
| 81 | RenderSurfaceMask loadMask = RT_NONE, const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 82 | |
| 83 | /** @copydoc RenderAPI::clearRenderTarget() */ |
| 84 | void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, |
| 85 | UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 86 | |
| 87 | /** @copydoc RenderAPI::clearViewport() */ |
| 88 | void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, |
| 89 | UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = nullptr) override; |
| 90 | |
| 91 | /** @copydoc RenderAPI::addCommands() */ |
| 92 | void addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary) override; |
| 93 | |
| 94 | /** @copydoc RenderAPI::submitCommandBuffer() */ |
| 95 | void submitCommandBuffer(const SPtr<CommandBuffer>& commandBuffer, UINT32 syncMask = 0xFFFFFFFF) override; |
| 96 | |
| 97 | /** @copydoc RenderAPI::convertProjectionMatrix() */ |
| 98 | void convertProjectionMatrix(const Matrix4& matrix, Matrix4& dest) override; |
| 99 | |
| 100 | /** @copydoc RenderAPI::generateParamBlockDesc() */ |
| 101 | GpuParamBlockDesc generateParamBlockDesc(const String& name, Vector<GpuParamDataDesc>& params) override; |
| 102 | |
| 103 | /************************************************************************/ |
| 104 | /* Internal use by OpenGL RenderSystem only */ |
| 105 | /************************************************************************/ |
| 106 | |
| 107 | /** Query has the main context been initialized. */ |
| 108 | bool _isContextInitialized() const { return mGLInitialised; } |
| 109 | |
| 110 | /** Returns main context. Caller must ensure the context has been initialized. */ |
| 111 | SPtr<GLContext> _getMainContext() const { return mMainContext; } |
| 112 | |
| 113 | /** Returns a support object you may use for creating */ |
| 114 | GLSupport* getGLSupport() const { return mGLSupport; } |
| 115 | |
| 116 | protected: |
| 117 | /** @copydoc RenderAPI::initialize */ |
| 118 | void initialize() override; |
| 119 | |
| 120 | /** @copydoc RenderAPI::initializeWithWindow */ |
| 121 | void initializeWithWindow(const SPtr<RenderWindow>& primaryWindow) override; |
| 122 | |
| 123 | /** @copydoc RenderAPI::destroyCore */ |
| 124 | void destroyCore() override; |
| 125 | |
| 126 | /** Call before doing a draw operation, this method sets everything up. */ |
| 127 | void beginDraw(); |
| 128 | |
| 129 | /** Needs to accompany every beginDraw after you are done with a single draw operation. */ |
| 130 | void endDraw(); |
| 131 | |
| 132 | /** Clear a part of a render target. */ |
| 133 | void clearArea(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, |
| 134 | const Rect2I& clearArea = Rect2I::EMPTY, UINT8 targetMask = 0xFF); |
| 135 | |
| 136 | /** |
| 137 | * Changes the currently active texture unit. Any texture related operations will then be performed on this unit. |
| 138 | */ |
| 139 | bool activateGLTextureUnit(UINT16 unit); |
| 140 | |
| 141 | /** Retrieves the active GPU program of the specified type. */ |
| 142 | SPtr<GLSLGpuProgram> getActiveProgram(GpuProgramType gptype) const; |
| 143 | |
| 144 | /** Converts framework's blend mode to OpenGL blend mode. */ |
| 145 | GLint getBlendMode(BlendFactor blendMode) const; |
| 146 | |
| 147 | /** Converts framework's texture addressing mode to OpenGL texture addressing mode. */ |
| 148 | GLint getTextureAddressingMode(TextureAddressingMode tam) const; |
| 149 | |
| 150 | /** Gets a combined min/mip filter value usable by OpenGL from the currently set min and mip filters. */ |
| 151 | GLuint getCombinedMinMipFilter() const; |
| 152 | |
| 153 | /** Returns the OpenGL specific mode used for drawing, depending on the currently set draw operation. */ |
| 154 | GLint getGLDrawMode() const; |
| 155 | |
| 156 | /** Creates render system capabilities that specify which features are or aren't supported. */ |
| 157 | void initCapabilities(RenderAPICapabilities& caps) const; |
| 158 | |
| 159 | /** Finish initialization by setting up any systems dependant on render systemcapabilities. */ |
| 160 | void initFromCaps(RenderAPICapabilities* caps); |
| 161 | |
| 162 | /** |
| 163 | * Switch the currently used OpenGL context. You will need to re-bind any previously bound values manually |
| 164 | * (for example textures, gpu programs and such). |
| 165 | */ |
| 166 | void switchContext(const SPtr<GLContext>& context, const RenderWindow& window); |
| 167 | |
| 168 | /************************************************************************/ |
| 169 | /* Sampler states */ |
| 170 | /************************************************************************/ |
| 171 | |
| 172 | /** |
| 173 | * Sets the texture addressing mode for a texture unit. This determines how are UV address values outside of [0, 1] |
| 174 | * range handled when sampling from texture. |
| 175 | */ |
| 176 | void setTextureAddressingMode(UINT16 unit, const UVWAddressingMode& uvw); |
| 177 | |
| 178 | /** |
| 179 | * Sets the texture border color for a texture unit. Border color determines color returned by the texture sampler |
| 180 | * when border addressing mode is used and texture address is outside of [0, 1] range. |
| 181 | */ |
| 182 | void setTextureBorderColor(UINT16 unit, const Color& color); |
| 183 | |
| 184 | /** |
| 185 | * Sets the mipmap bias value for a given texture unit. Bias allows you to adjust the mipmap selection calculation. |
| 186 | * Negative values force a larger mipmap to be used, and positive values smaller. Units are in values of mip levels, |
| 187 | * so -1 means use a mipmap one level higher than default. |
| 188 | */ |
| 189 | void setTextureMipmapBias(UINT16 unit, float bias); |
| 190 | |
| 191 | /** |
| 192 | * Sets a valid range for mipmaps (LOD) for a given texture unit. @p min limits the selection of the highest |
| 193 | * resolution mipmap (lowest level), and @p max limits the selection of the lowest resolution mipmap (highest |
| 194 | * level). |
| 195 | */ |
| 196 | void setTextureMipmapRange(UINT16 unit, float min, float max); |
| 197 | |
| 198 | /** |
| 199 | * Allows you to specify how is the texture bound to the specified texture unit filtered. Different filter types are |
| 200 | * used for different situations like magnifying or minifying a texture. |
| 201 | */ |
| 202 | void setTextureFiltering(UINT16 unit, FilterType ftype, FilterOptions filter); |
| 203 | |
| 204 | /** Sets anisotropy value for the specified texture unit. */ |
| 205 | void setTextureAnisotropy(UINT16 unit, UINT32 maxAnisotropy); |
| 206 | |
| 207 | /** |
| 208 | * Sets the compare mode to use when sampling the texture (anything but "always" implies the use of a shadow |
| 209 | * sampler. |
| 210 | */ |
| 211 | void setTextureCompareMode(UINT16 unit, CompareFunction compare); |
| 212 | |
| 213 | /** Gets anisotropy value for the specified texture unit. */ |
| 214 | GLfloat getCurrentAnisotropy(UINT16 unit); |
| 215 | |
| 216 | /************************************************************************/ |
| 217 | /* Blend states */ |
| 218 | /************************************************************************/ |
| 219 | |
| 220 | /** |
| 221 | * Sets up blending mode that allows you to combine new pixels with pixels already in the render target. |
| 222 | * Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor). |
| 223 | */ |
| 224 | void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op); |
| 225 | |
| 226 | /** |
| 227 | * Sets up blending mode that allows you to combine new pixels with pixels already in the render target. |
| 228 | * Allows you to set up separate blend operations for alpha values. |
| 229 | * |
| 230 | * Final pixel value = (renderTargetPixel * sourceFactor) op (pixel * destFactor). (And the same for alpha) |
| 231 | */ |
| 232 | void setSceneBlending(BlendFactor sourceFactor, BlendFactor destFactor, BlendFactor sourceFactorAlpha, |
| 233 | BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp); |
| 234 | |
| 235 | /** |
| 236 | * Enable alpha to coverage. Alpha to coverage allows you to perform blending without needing to worry about order |
| 237 | * of rendering like regular blending does. It requires multi-sampling to be active in order to work, and you need |
| 238 | * to supply an alpha texture that determines object transparency. |
| 239 | */ |
| 240 | void setAlphaToCoverage(bool enabled); |
| 241 | |
| 242 | /** Enables or disables writing to certain color channels of the render target. */ |
| 243 | void setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha); |
| 244 | |
| 245 | /************************************************************************/ |
| 246 | /* Rasterizer states */ |
| 247 | /************************************************************************/ |
| 248 | |
| 249 | /** Sets vertex winding order. Normally you would use this to cull back facing polygons. */ |
| 250 | void setCullingMode(CullingMode mode); |
| 251 | |
| 252 | /** Sets the polygon rasterization mode. Determines how are polygons interpreted. */ |
| 253 | void setPolygonMode(PolygonMode level); |
| 254 | |
| 255 | /** |
| 256 | * Sets a depth bias that will offset the depth values of new pixels by the specified amount. Final depth bias value |
| 257 | * is a combination of the constant depth bias and slope depth bias. Slope depth bias has more effect the higher |
| 258 | * the slope of the rendered polygon. |
| 259 | * |
| 260 | * @note This is useful if you want to avoid z fighting for objects at the same or similar depth. |
| 261 | */ |
| 262 | void setDepthBias(float constantBias, float slopeScaleBias); |
| 263 | |
| 264 | /** |
| 265 | * Scissor test allows you to mask off rendering in all but a given rectangular area identified by the rectangle |
| 266 | * set by setScissorRect(). |
| 267 | */ |
| 268 | void setScissorTestEnable(bool enable); |
| 269 | |
| 270 | /** Enables or disables multisample antialiasing. */ |
| 271 | void setMultisamplingEnable(bool enable); |
| 272 | |
| 273 | /** Enables or disables depth clipping (near/fear plane clipping). */ |
| 274 | void setDepthClipEnable(bool enable); |
| 275 | |
| 276 | /** Enables or disables antialiased line rendering. */ |
| 277 | void setAntialiasedLineEnable(bool enable); |
| 278 | |
| 279 | /************************************************************************/ |
| 280 | /* Depth stencil state */ |
| 281 | /************************************************************************/ |
| 282 | |
| 283 | /** Should new pixels perform depth testing using the set depth comparison function before being written. */ |
| 284 | void setDepthBufferCheckEnabled(bool enabled = true); |
| 285 | |
| 286 | /** Should new pixels write to the depth buffer. */ |
| 287 | void setDepthBufferWriteEnabled(bool enabled = true); |
| 288 | |
| 289 | /** |
| 290 | * Sets comparison function used for depth testing. Determines how are new and existing pixel values compared - if |
| 291 | * comparison function returns true the new pixel is written. |
| 292 | */ |
| 293 | void setDepthBufferFunction(CompareFunction func = CMPF_LESS_EQUAL); |
| 294 | |
| 295 | /** |
| 296 | * Turns stencil tests on or off. By default this is disabled. Stencil testing allow you to mask out a part of the |
| 297 | * rendered image by using various stencil operations provided. |
| 298 | */ |
| 299 | void setStencilCheckEnabled(bool enabled); |
| 300 | |
| 301 | /** |
| 302 | * Allows you to set stencil operations that are performed when stencil test passes or fails. |
| 303 | * |
| 304 | * @param[in] stencilFailOp Operation executed when stencil test fails. |
| 305 | * @param[in] depthFailOp Operation executed when stencil test succeeds but depth test fails. |
| 306 | * @param[in] passOp Operation executed when stencil test succeeds and depth test succeeds. |
| 307 | * @param[in] front Should the stencil operations be applied to front or back facing polygons. |
| 308 | */ |
| 309 | void setStencilBufferOperations(StencilOperation stencilFailOp = SOP_KEEP, |
| 310 | StencilOperation depthFailOp = SOP_KEEP, StencilOperation passOp = SOP_KEEP, |
| 311 | bool front = true); |
| 312 | |
| 313 | /** |
| 314 | * Sets a stencil buffer comparison function. The result of this will cause one of 3 actions depending on whether |
| 315 | * the test fails, succeeds but with the depth buffer check still failing, or succeeds with the depth buffer check |
| 316 | * passing too. |
| 317 | * |
| 318 | * @param[in] func Comparison function that determines whether a stencil test fails or passes. Reference value |
| 319 | * gets compared to the value already in the buffer using this function. |
| 320 | * @param[in] mask The bitmask applied to both the stencil value and the reference value |
| 321 | * before comparison |
| 322 | * @param[in] ccw If set to true, the stencil operations will be applied to counterclockwise |
| 323 | * faces. Otherwise they will be applied to clockwise faces. |
| 324 | */ |
| 325 | void setStencilBufferFunc(CompareFunction func = CMPF_ALWAYS_PASS, UINT32 mask = 0xFFFFFFFF, bool ccw = true); |
| 326 | |
| 327 | /** The bitmask applied to the stencil value before writing it to the stencil buffer. */ |
| 328 | void setStencilBufferWriteMask(UINT32 mask = 0xFFFFFFFF); |
| 329 | |
| 330 | /** |
| 331 | * Sets a reference values used for stencil buffer comparisons. Actual comparison function and stencil operations |
| 332 | * are set by setting the DepthStencilState. |
| 333 | */ |
| 334 | void setStencilRefValue(UINT32 refValue); |
| 335 | |
| 336 | /************************************************************************/ |
| 337 | /* UTILITY METHODS */ |
| 338 | /************************************************************************/ |
| 339 | |
| 340 | /** |
| 341 | * Recalculates actual viewport dimensions based on currently set viewport normalized dimensions and render target |
| 342 | * and applies them for further rendering. |
| 343 | */ |
| 344 | void applyViewport(); |
| 345 | |
| 346 | /** Converts the provided matrix m into a representation usable by OpenGL. */ |
| 347 | void makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m); |
| 348 | |
| 349 | /** Converts the engine depth/stencil compare function into OpenGL representation. */ |
| 350 | GLint convertCompareFunction(CompareFunction func) const; |
| 351 | |
| 352 | /** Convers the engine stencil operation in OpenGL representation. */ |
| 353 | GLint convertStencilOp(StencilOperation op) const; |
| 354 | |
| 355 | private: |
| 356 | /** Information about a currently bound texture. */ |
| 357 | struct TextureInfo |
| 358 | { |
| 359 | GLenum type = GL_TEXTURE_2D; |
| 360 | }; |
| 361 | |
| 362 | static const UINT32 MAX_VB_COUNT = 32; |
| 363 | |
| 364 | Rect2 mViewportNorm = Rect2(0.0f, 0.0f, 1.0f, 1.0f); |
| 365 | UINT32 mScissorTop = 0; |
| 366 | UINT32 mScissorBottom = 720; |
| 367 | UINT32 mScissorLeft = 0; |
| 368 | UINT32 mScissorRight = 1280; |
| 369 | UINT32 mViewportLeft = 0; |
| 370 | UINT32 mViewportTop = 0; |
| 371 | UINT32 mViewportWidth = 0; |
| 372 | UINT32 mViewportHeight = 0; |
| 373 | bool mScissorEnabled = false; |
| 374 | |
| 375 | UINT32 mStencilReadMask = 0xFFFFFFFF; |
| 376 | UINT32 mStencilWriteMask = 0xFFFFFFFF; |
| 377 | UINT32 mStencilRefValue = 0; |
| 378 | CompareFunction mStencilCompareFront = CMPF_ALWAYS_PASS; |
| 379 | CompareFunction mStencilCompareBack = CMPF_ALWAYS_PASS; |
| 380 | |
| 381 | // Last min & mip filtering options, so we can combine them |
| 382 | FilterOptions mMinFilter; |
| 383 | FilterOptions mMipFilter; |
| 384 | |
| 385 | // Holds texture type settings for every stage |
| 386 | UINT32 mNumTextureUnits = 0; |
| 387 | TextureInfo* mTextureInfos = nullptr; |
| 388 | bool mDepthWrite = true; |
| 389 | bool mColorWrite[4]; |
| 390 | |
| 391 | GLSupport* mGLSupport; |
| 392 | bool mGLInitialised; |
| 393 | |
| 394 | GLSLProgramFactory* mGLSLProgramFactory = nullptr; |
| 395 | GLSLProgramPipelineManager* mProgramPipelineManager = nullptr; |
| 396 | |
| 397 | SPtr<GLSLGpuProgram> mCurrentVertexProgram; |
| 398 | SPtr<GLSLGpuProgram> mCurrentFragmentProgram; |
| 399 | SPtr<GLSLGpuProgram> mCurrentGeometryProgram; |
| 400 | SPtr<GLSLGpuProgram> mCurrentHullProgram; |
| 401 | SPtr<GLSLGpuProgram> mCurrentDomainProgram; |
| 402 | SPtr<GLSLGpuProgram> mCurrentComputeProgram; |
| 403 | |
| 404 | const GLSLProgramPipeline* mActivePipeline = nullptr; |
| 405 | |
| 406 | std::array<SPtr<VertexBuffer>, MAX_VB_COUNT> mBoundVertexBuffers; |
| 407 | SPtr<VertexDeclaration> mBoundVertexDeclaration; |
| 408 | SPtr<IndexBuffer> mBoundIndexBuffer; |
| 409 | DrawOperationType mCurrentDrawOperation = DOT_TRIANGLE_LIST; |
| 410 | |
| 411 | SPtr<GLContext> mMainContext; |
| 412 | SPtr<GLContext> mCurrentContext; |
| 413 | |
| 414 | bool mDrawCallInProgress = false; |
| 415 | |
| 416 | UINT16 mActiveTextureUnit = -1; |
| 417 | }; |
| 418 | |
| 419 | /** @} */ |
| 420 | }} |
| 421 | |