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