1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4  * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see http://gnu.org/licenses
18  */
19 
20 /**
21  * \file graphics/opengl/gl14device.h
22  * \brief OpenGL implementation - CGL14Device class
23  */
24 
25 #pragma once
26 
27 #include "graphics/core/device.h"
28 
29 #include "graphics/core/material.h"
30 
31 #include "graphics/opengl/glframebuffer.h"
32 #include "graphics/opengl/glutil.h"
33 
34 #include "math/matrix.h"
35 
36 #include <string>
37 #include <vector>
38 #include <set>
39 #include <map>
40 
41 
42 // Graphics module namespace
43 namespace Gfx
44 {
45 
46 enum ShadowMappingSupport
47 {
48     SMS_NONE,           //! No support for depth textures
49     SMS_ARB,            //! ARB extension
50     SMS_CORE            //! Core support
51 };
52 
53 /**
54   \class CGL14Device
55   \brief Implementation of CDevice interface in OpenGL
56 
57   Provides the concrete implementation of 3D device in OpenGL.
58 
59   This class should be initialized (by calling Initialize() ) only after
60   setting the video mode by CApplication, once the OpenGL context is defined.
61   Because of that, CGL14DeviceConfig is outside the CDevice class and must be set
62   in CApplication.
63 */
64 class CGL14Device : public CDevice
65 {
66 public:
67     CGL14Device(const DeviceConfig &config);
68     virtual ~CGL14Device();
69 
70     void DebugHook() override;
71     void DebugLights() override;
72 
73     std::string GetName() override;
74 
75     bool Create() override;
76     void Destroy() override;
77 
78     void ConfigChanged(const DeviceConfig &newConfig) override;
79 
80     void BeginScene() override;
81     void EndScene() override;
82 
83     void Clear() override;
84 
85     void SetRenderMode(RenderMode mode) override;
86 
87     void SetTransform(TransformType type, const Math::Matrix &matrix) override;
88 
89     void SetMaterial(const Material &material) override;
90 
91     int GetMaxLightCount() override;
92     void SetLight(int index, const Light &light) override;
93     void SetLightEnabled(int index, bool enabled) override;
94 
95     Texture CreateTexture(CImage *image, const TextureCreateParams &params) override;
96     Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override;
97     Texture CreateDepthTexture(int width, int height, int depth) override;
98     void UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format) override;
99     void DestroyTexture(const Texture &texture) override;
100     void DestroyAllTextures() override;
101 
102     int GetMaxTextureStageCount() override;
103     void SetTexture(int index, const Texture &texture) override;
104     void SetTexture(int index, unsigned int textureId) override;
105     void SetTextureEnabled(int index, bool enabled) override;
106 
107     void SetTextureStageParams(int index, const TextureStageParams &params) override;
108 
109     void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override;
110 
111     virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices    , int vertexCount,
112                                Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
113     virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
114                                Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
115     virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount) override;
116 
117     virtual void DrawPrimitives(PrimitiveType type, const Vertex *vertices,
118         int first[], int count[], int drawCount,
119         Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
120     virtual void DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices,
121         int first[], int count[], int drawCount,
122         Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
123     virtual void DrawPrimitives(PrimitiveType type, const VertexCol *vertices,
124         int first[], int count[], int drawCount) override;
125 
CreateStaticBuffer(PrimitiveType primitiveType,const Vertex * vertices,int vertexCount)126     unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) override
127     {
128         return CreateStaticBufferImpl(primitiveType, vertices, vertexCount);
129     }
CreateStaticBuffer(PrimitiveType primitiveType,const VertexTex2 * vertices,int vertexCount)130     unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) override
131     {
132         return CreateStaticBufferImpl(primitiveType, vertices, vertexCount);
133     }
CreateStaticBuffer(PrimitiveType primitiveType,const VertexCol * vertices,int vertexCount)134     unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) override
135     {
136         return CreateStaticBufferImpl(primitiveType, vertices, vertexCount);
137     }
UpdateStaticBuffer(unsigned int bufferId,PrimitiveType primitiveType,const Vertex * vertices,int vertexCount)138     void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) override
139     {
140         UpdateStaticBufferImpl(bufferId, primitiveType, vertices, vertexCount);
141     }
UpdateStaticBuffer(unsigned int bufferId,PrimitiveType primitiveType,const VertexTex2 * vertices,int vertexCount)142     void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) override
143     {
144         UpdateStaticBufferImpl(bufferId, primitiveType, vertices, vertexCount);
145     }
UpdateStaticBuffer(unsigned int bufferId,PrimitiveType primitiveType,const VertexCol * vertices,int vertexCount)146     void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) override
147     {
148         UpdateStaticBufferImpl(bufferId, primitiveType, vertices, vertexCount);
149     }
150 
151     void DrawStaticBuffer(unsigned int bufferId) override;
152     void DestroyStaticBuffer(unsigned int bufferId) override;
153 
154     int ComputeSphereVisibility(const Math::Vector &center, float radius) override;
155 
156     void SetViewport(int x, int y, int width, int height) override;
157 
158     void SetRenderState(RenderState state, bool enabled) override;
159 
160     void SetColorMask(bool red, bool green, bool blue, bool alpha) override;
161 
162     void SetDepthTestFunc(CompFunc func) override;
163 
164     void SetDepthBias(float factor, float units) override;
165 
166     void SetAlphaTestFunc(CompFunc func, float refValue) override;
167 
168     void SetBlendFunc(BlendFunc srcBlend, BlendFunc dstBlend) override;
169 
170     void SetClearColor(const Color &color) override;
171 
172     void SetGlobalAmbient(const Color &color) override;
173 
174     void SetFogParams(FogMode mode, const Color &color, float start, float end, float density) override;
175 
176     void SetCullMode(CullMode mode) override;
177 
178     void SetShadeModel(ShadeModel model) override;
179 
180     void SetShadowColor(float value) override;
181 
182     void SetFillMode(FillMode mode) override;
183 
184     void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height) override;
185 
186     std::unique_ptr<CFrameBufferPixels> GetFrameBufferPixels() const override;
187 
188     CFramebuffer* GetFramebuffer(std::string name) override;
189 
190     CFramebuffer* CreateFramebuffer(std::string name, const FramebufferParams& params) override;
191 
192     void DeleteFramebuffer(std::string name) override;
193 
194     bool IsAnisotropySupported() override;
195     int GetMaxAnisotropyLevel() override;
196 
197     int GetMaxSamples() override;
198 
199     bool IsShadowMappingSupported() override;
200 
201     int GetMaxTextureSize() override;
202 
203     bool IsFramebufferSupported() override;
204 
205 private:
206     //! Updates internal modelview matrix
207     void UpdateModelviewMatrix();
208     //! Updates position for given light based on transformation matrices
209     void UpdateLightPosition(int index);
210     //!  Updates position for all lights based on transformation matrices
211     void UpdateLightPositions();
212     //! Updates the texture params for given texture stage
213     void UpdateTextureParams(int index);
214 
215     //! Enables shadows
216     void EnableShadows();
217     //! Disables shadows
218     void DisableShadows();
219 
220     template <typename Vertex>
221     unsigned int CreateStaticBufferImpl(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount);
222     template <typename Vertex>
223     void UpdateStaticBufferImpl(unsigned int bufferId, PrimitiveType primitiveType, const Vertex* vertices, int vertexCount);
224 
225 private:
226     //! Current config
227     DeviceConfig m_config;
228 
229     //! Current world matrix
230     Math::Matrix m_worldMat;
231     //! Current view matrix
232     Math::Matrix m_viewMat;
233     //! OpenGL modelview matrix = world matrix * view matrix
234     Math::Matrix m_modelviewMat;
235     //! Current projection matrix
236     Math::Matrix m_projectionMat;
237     //! Combined world-view-projection matrix
238     Math::Matrix m_combinedMatrix;
239     //! Current shadow matrix
240     Math::Matrix m_shadowMatrix;
241     //! true means that combined matrix is outdated
242     bool m_combinedMatrixOutdated = true;
243 
244     //! The current material
245     Material m_material;
246 
247     //! Whether lighting is enabled
248     bool m_lighting = false;
249     //! Current lights
250     std::vector<Light> m_lights;
251     //! Current lights enable status
252     std::vector<bool> m_lightsEnabled;
253 
254     //! Current textures; \c nullptr value means unassigned
255     std::vector<Texture> m_currentTextures;
256     //! Current texture stages enable status
257     std::vector<bool> m_texturesEnabled;
258     //! Current texture params
259     std::vector<TextureStageParams> m_textureStageParams;
260     //! Texture unit remap
261     std::vector<int> m_remap;
262 
263     //! Set of all created textures
264     std::set<Texture> m_allTextures;
265     //! White texture
266     GLuint m_whiteTexture = 0;
267 
268     //! Map of framebuffers
269     std::map<std::string, std::unique_ptr<CFramebuffer>> m_framebuffers;
270 
271     //! Info about static VBO buffers
272     struct VboObjectInfo
273     {
274         PrimitiveType primitiveType = {};
275         unsigned int bufferId = 0;
276         VertexType vertexType = {};
277         int vertexCount = 0;
278     };
279 
280     //! Detected capabilities
281     //! Depth texture support
282     ShadowMappingSupport m_shadowMappingSupport = SMS_NONE;
283     //! glMultiDrawArrays() available
284     bool m_multiDrawArrays = false;
285     //! Framebuffer support
286     FramebufferSupport m_framebufferSupport = FBS_NONE;
287     //! Map of saved VBO objects
288     std::map<unsigned int, VboObjectInfo> m_vboObjects;
289     //! Last ID of VBO object
290     unsigned int m_lastVboId = 0;
291 
292     //! true means shadow mapping is enabled
293     bool m_shadowMapping = false;
294     //! true means that quality shadows are enabled
295     bool m_shadowQuality = true;
296 
297 
298     //! Pointers to OpenGL functions
299     PFNGLGENBUFFERSPROC m_glGenBuffers = nullptr;
300     PFNGLDELETEBUFFERSPROC m_glDeleteBuffers = nullptr;
301     PFNGLBINDBUFFERPROC m_glBindBuffer = nullptr;
302     PFNGLBUFFERDATAPROC m_glBufferData = nullptr;
303     PFNGLBUFFERSUBDATAPROC m_glBufferSubData = nullptr;
304 };
305 
306 
307 } // namespace Gfx
308