1 /**
2  * Copyright:   Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved
3  * Authors:     $(Gabriel Gheorghe)
4  * License:     $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007)
5  * Source:      $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/graphics/renderer.d, _renderer.d)
6  * Documentation:
7  * Coverage:
8  */
9 module liberty.graphics.renderer;
10 import liberty.math.vector : Vector2F, Vector3F;
11 import liberty.graphics.util : RenderUtil;
12 import liberty.graphics.video.vertex : VertexSpec;
13 import liberty.graphics.video.vao : VertexArray;
14 import liberty.graphics.video.buffer : VideoBuffer, BufferTarget;
15 import liberty.graphics.video.shader : ShaderProgram;
16 import derelict.opengl;
17 import liberty.core.imaging;
18 import liberty.core.engine;
19 import liberty.math;
20 import liberty.core.time;
21 import liberty.math.vector;
22 import derelict.sdl2.sdl : SDL_GL_SetSwapInterval;
23 import liberty.graphics.video.backend : VideoBackend;
24 import liberty.core.engine;
25 import liberty.core.model;
26 import liberty.graphics.material;
27 import liberty.core.utils : Singleton, IService;
28 //import sunshine.graphics.video.vao : VertexArrayObject;
29 version (__OpenGL__) {
30 	import liberty.graphics.opengl.backend : GLBackend;
31 	import liberty.graphics.opengl.buffer : GLBuffer;
32 	//import sunshine.graphics.opengl.vao : GLVertexArrayObject;
33 	import derelict.opengl : glPolygonMode, GL_FRONT_AND_BACK, GL_LINE, GL_FILL;
34 } else version (__Vulkan__) {
35 	import liberty.graphics.vulkan.backend : VKBackend;
36 	import liberty.graphics.vulkan.buffer : VKBuffer;
37 } else version (__WASM__) {
38 		import liberty.graphics.wasm.backend : WASMBackend;
39 	}
40 ///
41 class GraphicsEngine : Singleton!GraphicsEngine, IService {
42 	private {
43 		private bool _serviceRunning;
44 		VideoBackend _backend;
45 		bool _vsyncEnabled = false;
46 		bool _wireframe = false;
47 		Vector4F _color = Vector4F(1.0, 1.0, 1.0, 1.0);
48 	}
49 	/// Start GraphicsEngine service.
50 	void startService() @trusted {
51 		version (__OpenGL__) {
52 			_backend = new GLBackend();
53 		} else version (__Vulkan__) {
54 			_backend = new VKBackend();
55 		} else version (__WASM__) {
56 			_backend = new WASMBackend();
57 		}
58 		_serviceRunning = true;
59 	}
60 	/// Stop GraphicsEngine service.
61 	void stopService() @trusted {
62 		if (_backend !is null) {
63 			_backend.destroy();
64 			_backend = null;
65 		}
66 		_serviceRunning = false;
67 	}
68 	///  Restart GraphicsEngine service.
69 	void restartService() @trusted {
70 		stopService();
71 		startService();
72 	}
73 	/// Returns true if GraphicsEngine service is running.
74 	bool isServiceRunning() pure nothrow const @safe @nogc {
75 		return _serviceRunning;
76 	}
77 	///
78 	VideoBackend backend() {
79 		return _backend;
80 	}
81 	///
82 	void render() {
83 		import derelict.opengl;
84 		glEnable(GL_DEPTH_TEST);
85 		glEnable(GL_CULL_FACE);
86 		glFrontFace(GL_CW);
87 		_backend.resizeViewport();
88 		_backend.clear();
89 		//_backend.enableDepthTest(); // TODO. + culling.
90 		_backend.clearColor(_color.r, _color.g, _color.b, _color.a);
91 		CoreEngine.get.activeScene.render();
92 		_backend.swapBuffers();
93 	}
94 	///
95 	void vSyncEnabled(bool enabled = true) {
96 		SDL_GL_SetSwapInterval(enabled); // TODO: VULKAN?
97 		_vsyncEnabled = enabled;
98 	}
99 	///
100 	bool isVSyncEnabled() nothrow {
101 		return _vsyncEnabled;
102 	}
103 	///
104 	void windowBackgroundColor(float r, float g, float b, float a = 1.0f) {
105 		_color = Vector4F(r, g, b, a);
106 	}
107 	///
108 	void windowBackgroundColor(Vector3F color, float a = 1.0f) {
109 		_color = Vector4F(color, a);
110 	}
111 	///
112 	void windowBackgroundColor(Vector4F color) {
113 		_color = color;
114 	}
115 	///
116 	void toggleWireframe() { // TODO: Vulkan.
117 		version (__OpenGL__) {
118 			if (!_wireframe) {
119 				glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
120 			} else {
121 				glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
122 			}
123 		}
124 		_wireframe = !_wireframe;
125 	}
126 }
127 ///
128 static struct Vertex {
129 	Vector3F position;
130 	Vector2F texCoords;
131 }
132 ///
133 enum Vendor : byte {
134 	///
135 	Amd = 0x00,
136 	///
137 	Intel = 0x01,
138 	///
139 	Nvidia = 0x02,
140 	///
141 	Mesa = 0x03,
142 	/// For Software rendering, no driver
143 	Apple = 0x04,
144 	/// For GDI Generic, no driver
145 	Microsoft = 0x05,
146 	///
147 	Other = -0x01
148 }
149 ///
150 enum Blending : byte {
151 	///
152 	Opaque = 0x00,
153 	///
154 	AlphaBlend = 0x01,
155 	///
156 	NonPremultiplied = 0x02,
157 	///
158 	Additive = 0x03
159 }
160 ///
161 enum Sampling : byte {
162 	///
163 	AnisotropicClamp = 0x00,
164 	///
165 	AnisotropicWrap = 0x01,
166 	///
167 	LinearClamp = 0x02,
168 	///
169 	LinearWrap = 0x03,
170 	///
171 	PointClamp = 0x04,
172 	///
173 	PointWrap = 0x05
174 }
175 ///
176 enum VSyncState : byte {
177 	///
178 	Immediate = 0x00,
179 	///
180 	Default = 0x01,
181 	///
182 	LateTearing = -0x01
183 	// TODO: GSync / FreeSync ?
184 }
185 ///
186 enum DataUsage : byte {
187 	///
188 	StreamDraw = 0x00,
189 	///
190 	StreamRead = 0x01,
191 	///
192 	StreamCopy = 0x02,
193 	///
194 	StaticDraw = 0x03,
195 	///
196 	StaticRead = 0x04,
197 	///
198 	StaticCopy = 0x05,
199 	///
200 	DynamicDraw = 0x06,
201 	///
202 	DynamicRead = 0x07,
203 	///
204 	DynamicCopy = 0x08
205 }
206 ///
207 enum DrawMode : byte {
208 	///
209 	Triangles = 0x00
210 }
211 ///
212 enum VectorType : byte {
213 	///
214 	UnsignedInt = 0x00
215 }
216 ///
217 interface Renderable {
218 	///
219 	void render();
220 }