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 | |