Renderer.h
1 /*
2 
3 Copyright (c) 2018, Johnathan Corkery. (jcorkery@umich.edu)
4 All rights reserved.
5 
6 This file is part of the Dynacoe project (https://github.com/jcorks/Dynacoe)
7 Dynacoe was released under the MIT License, as detailed below.
8 
9 
10 
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is furnished
16 to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall
19 be included in all copies or substantial portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
25 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
28 
29 
30 
31 */
32 
33 #ifndef DC_Renderer_INTERFACE_H_INCLUDED
34 #define DC_Renderer_INTERFACE_H_INCLUDED
35 
36 
37 
38 /* Renderer,
39  A light renderer interface for Dynacoe's rendering layer.
40  In this renderer abstraction, lighting and shaders are extensions
41  and, while typically implemented in GPU-oriented backends, is not
42  core functionality and may not be provided. In such a case, the
43  extension functions can be called, but should not affect the renderer state.
44 
45 
46  Johnathan Corkery, 2015
47 
48 */
49 #include <Dynacoe/Util/Table.h>
50 #include <Dynacoe/Backends/Display/Display.h>
51 #include <string>
52 #include <unordered_map>
53 #include <cstdint>
54 
55 
56 namespace Dynacoe {
57 class Color;
58 class Display;
59 class StaticState;
60 struct RendererImpl;
61 
62 using RenderBufferID = Dynacoe::LookupID;
63 using ProgramID = Dynacoe::LookupID;
64 using LightID = Dynacoe::LookupID;
65 using DynamicTransformID = int;
66 
67 
68 class Renderer : public Backend {
69  public:
70  static const int MINIMUM_LIGHT_COUNT = 128;
71  static const int MINIMUM_TEXTURE_BINDING_COUNT = 64;
72 
73  // Struct representing a dynamic vertex state.
74  // Dynamic vertices do not support lighting.
75  struct Vertex2D {
76  Vertex2D(){}
77  Vertex2D(float x_, float y_,
78  float r_, float g_, float b_, float a_,
79  float tex, float tx, float ty)
80  : x(x_), y(y_),
81  r(r_), g(g_), b(b_), a(a_), useTex(tex), texX(tx), texY(ty) {}
82  Vertex2D(float x_, float y_,
83  float r_, float g_, float b_, float a_)
84  : x(x_), y(y_),
85  r(r_), g(g_), b(b_), a(a_), useTex(-1) {}
86 
87  Vertex2D(float x_, float y_,
88  float tex, float tx, float ty)
89  : x(x_), y(y_),
90  r(1.f), g(1.f), b(1.f), a(1.f),
91  useTex(tex), texX(tx), texY(ty) {}
92  float x, y; // vertex position
93  float r, g, b, a; // color, scale from 0.f to 1.f (red, green, blue, and alpha)
94  float texX, texY; // texture coordinates (0, 0 is topleft)
95  float useTex; // if not used, set to -1, else float form of texture id
96  float object; // the transform reference object
97  };
98 
99  // For use with StaticState. See StaticState.h
100  struct StaticVertex {
101  StaticVertex(){}
102  StaticVertex(float x_, float y_, float z_) :
103  x(x_), y(y_), z(z_),
104  normalX(0), normalY(0), normalZ(0),
105  texX(0), texY(0),
106  userDefinedData{0, 0, 0, 0}
107  {}
108 
109  StaticVertex(
110  float x_, float y_, float z_,
111  float normalX_, float normalY_, float normalZ_,
112  float texX_, float texY_,
113  float userdata0,
114  float userdata1,
115  float userdata2,
116  float userdata3
117  ) :
118  x(x_), y(y_), z(z_),
119  normalX(normalX_), normalY(normalY_), normalZ(normalZ_),
120  texX(texX_), texY(texY_),
121  userDefinedData{
122  userdata0,
123  userdata1,
124  userdata2,
125  userdata3
126  }
127  {}
128 
129 
130  float x, y, z;
131  float normalX, normalY, normalZ;
132  float texX, texY;
133  float userDefinedData[4];
134  };
135 
136  enum class TexFilter {
137  Linear,
138  NoFilter,
139  };
140 
141  enum class Polygon {
142  Triangle,
143  Line
144  };
145 
146 
147  enum class Dimension {
148  D_2D,
149  D_3D
150  };
151 
152 
153  enum class AlphaRule {
154  Allow,
155  PassThrough,
156  Opaque,
157  Translucent
158  };
159 
160  enum class Capability {
161  Lighting,
162  UserShaders
163 
164  };
165 
166  enum class BuiltInShaderMode {
167  // MaterialIDs for render objects should be only 4 floats
168  // Each float represents a color, all 4 corresponding to RGBA.
169  // No lighting is enabled
170  BasicShader,
171 
172  // The objects output color is determined by
173  // a phong shading-like algorithm that utilizes any Light objects
174  // and set material for the object
175  LightMaterial,
176 
177 
178  };
179 
180 
181  enum class LightType {
182  Point,
183  Directional,
184  Spot
185  };
186 
187 
188  struct Render2DStaticParameters {
189  float contextWidth;
190  float contextHeight;
191 
192  float * contextTransform;
193  };
194 
195  struct Render2DObjectParameters {
196 
197  // transform
198  float data[16];
199 
200  };
201 
202 
203 
204 
205 
206 
207 
208 
209 
210 
211 
212  /* Requesting Geometry */
213 
214  // The general use case for 2D geometry is we will draw many
215  // small objects with unique tranform properties. Thus, a stati crendering
216  // approach is less favorable as that would lead to more frequent draws.
217  // Render2DVertices, using user-maintained global vertices, is a more
218  // performant option for drawing specifically 2D vertices.
219  virtual void Queue2DVertices(
220  const uint32_t * indices,
221  uint32_t count
222  ) = 0;
223 
224  virtual uint32_t Add2DObject() = 0;
225 
226  virtual void Remove2DObject(uint32_t) = 0;
227 
228  virtual uint32_t Add2DVertex() = 0;
229 
230  virtual void Remove2DVertex(uint32_t object) = 0;
231 
232  virtual void Set2DVertex(uint32_t vertex, Vertex2D) = 0;
233 
234  virtual Vertex2D Get2DVertex(uint32_t vertex) = 0;
235 
236  virtual void Set2DObjectParameters(uint32_t object, Render2DObjectParameters) = 0;
237 
238  virtual void Render2DVertices(const Render2DStaticParameters &) = 0;
239 
240  // Clears all requests queued before the last RenderDynamicQueue
241  virtual void Clear2DQueue() = 0;
242 
243 
244 
245 
246 
247 
248 
249 
250  // Unlike Dynamic requests, RenderStatic render execution times are entirely up
251  // to the renderer and backend. The only guarantee is that the object will render
252  // on the committed display. The benefit of this mode is utilizing advanced shaders
253  // and the ability to utilize specialized renderer storage, which will almost always
254  // yield better performance for static rendering over dynamic rendering. Vertices
255  // here are transformed by the renderer.
256  virtual void RenderStatic(StaticState *) = 0;
257 
258  // Resets the renderer's render space to an initial state.
259  virtual void ClearRenderedData() = 0;
260 
261  // Returns the transformation matrix buffer IDs for static rendering.
262  // All RenderStatic positional vertices are multiplied by the Viewing and
263  // projection matrices respectively. Once determined by the renderer,
264  // these ID's values will not change per instance.
265  virtual RenderBufferID GetStaticViewingMatrixID() = 0;
266  virtual RenderBufferID GetStaticProjectionMatrixID() = 0;
267 
268 
269 
270 
271 
272 
273 
274  /* Texture Management */
275 
276  // Stores texture data so that it may be accessed in the drawing structure.
277  // Returns the textureIndex. Passing a nullptr as the rgbaTextureData
278  // will allocate space for the texture, keep its contents as undefined
279  virtual int AddTexture(int w, int h, const uint8_t * rgbaTextureData) = 0;
280 
281  // redefines the contents of an existing image without
282  // deleting it and re-adding it. The image is expected to be the
283  // same dimensions as the original.
284  virtual void UpdateTexture(int tex, const uint8_t * newData) = 0;
285 
286  // Flags a texture for deletion. Deletion is not guaranteed to be immediate, nor does it guarantee
287  // freeing of GPU memory; however, it does guarantee the possibility of adding one or more
288  // textures of its size or less.
289  virtual void RemoveTexture(int tex) = 0;
290 
291  // Populates the given array with the texture data.
292  // THe input buffer should be allocated to GetTextureWidth()*GetTextureHeight()*4
293  // As with input buffered data, the format is RGBA with no padding.
294  virtual void GetTexture(int tex, uint8_t *) = 0;
295 
296 
297  // sets/ gets the stretching filter to be used during the next request resolution
298  virtual void SetTextureFilter(TexFilter) = 0;
299  virtual TexFilter GetTextureFilter() = 0;
300 
301 
302  virtual int GetTextureWidth(int tex) = 0;
303  virtual int GetTextureHeight(int tex) = 0;
304 
305  // Returns the maximum number of textures that can be referred to
306  // by a StaticObject when rendering.
307  virtual int MaxSimultaneousTextures() = 0;
308 
309 
310 
311 
312 
313  /* RenderBuffer storage */
314 
315  // Allocates a new data store. It is not guaranteed where this data store is kept,
316  // but if you are using a backend with hardware support, it is likely in VRAM.
317  // If the allocation fails in some way, the id returned will be invalid
318  virtual RenderBufferID AddBuffer(float * data, int numElements) = 0;
319 
320  // Updates numElements elements of the buffer starting at the offset'th element
321  // No check is made to see if this oversteps the original buffer size. If
322  // overstepping occurs, the result is undefined.
323  virtual void UpdateBuffer(RenderBufferID bufferID, float * newData, int offset, int numElements) = 0;
324 
325 
326  // Populates outputData with the relevant data contained in the buffer. On most implementations
327  // this will require expensive communication, so use with caution.
328  virtual void ReadBuffer(RenderBufferID bufferID, float * ouputData, int offset, int numELements) = 0;
329 
330  // Returns the number of elements of the buffer.
331  virtual int BufferSize(RenderBufferID bufferID) = 0;
332 
333  // Frees the buffer store.
334  virtual void RemoveBuffer(RenderBufferID bufferID) = 0;
335 
336 
337 
338 
339 
340 
341  /* Shader Programs */
342 
343 
344  // Returns a string denoting the name of the shading language supported.
345  // If shaders are not supported, an empty string is returned.
346  virtual std::string ProgramGetLanguage() = 0;
347 
348  // Compiles and enacts a shader for use with Static Rendering. If the shader fails
349  // to compile or is invalid in some way, the id returned is invalid. See StaticState.
350  // In any case, log will be populated with information on the building process status.
351  virtual ProgramID ProgramAdd(const std::string & vertexSrc, const std::string & fragSrc, std::string & log) = 0;
352 
353  // Returns the id referring to a builtin shader.
354  virtual ProgramID ProgramGetBuiltIn(BuiltInShaderMode) = 0;
355 
356 
357 
358 
359 
360 
361  /* Lighting */
362 
363 
364  // Creates a new light. When the light is first created, the state of the light
365  // is undefined. (It is expected that you will update the lights attributes
366  // before drawing);
367  virtual LightID AddLight(LightType) = 0;
368 
369  // As the default, the attributes requred are
370  // Position (3-components)
371  // Color (3-components)
372  // Intensity (1 component)
373  // Thus, the renderer expects the array passed to have at least 7 components.
374 
375  virtual void UpdateLightAttributes(LightID, float *) = 0;
376 
377 
378  // Enables or diables the light by default, once added, the light is enabled by default
379  virtual void EnableLight(LightID, bool doIt) = 0;
380 
381  // Removes all resources associated with the light ID.
382  virtual void RemoveLight(LightID) = 0;
383 
384  // returns the maximum number of lights supported by the renderer.
385  virtual int MaxEnabledLights() = 0;
386 
387  // returns the number of lightx currently in use.
388  virtual int NumLights() = 0;
389 
390 
391 
392 
393 
394 
395 
396 
397 
398 
399 
400  /* Extension management */
401 
402  // Returns whether or not the capability is supported on this backend
403  // For the Renderer, capabilities are close to "standardized extensions":
404  // functionality that isnt necessarily supported by a renderer's backend to
405  // function properly, but is usually supported by most modern, complete backends.
406  virtual bool IsSupported(Capability) = 0;
407 
408 
409  /* Display management */
410 
411  // Modifes how all following drawn geometry is handled.
412  virtual void SetDrawingMode (
413  Polygon,
414  Dimension,
415  AlphaRule
416  ) = 0;
417 
418  // Retrieves how all the geometry will be drawn
419  virtual void GetDrawingMode (
420  Polygon * polygon,
421  Dimension * dimension,
422  AlphaRule * alhaRule
423  ) = 0;
424 
425 
426  // The passed framebuffer becomes the destination for all future renderings
427  // until a different valid framebuffer is given. If the Type of the given
428  // Framebuffer is not one of the types from SupportedFramebuffers, no
429  // action is taken. If nullptr is passed, rendering will have no effect.
430  virtual void AttachTarget(Framebuffer *) = 0;
431 
432 
433  // Returns the current target for renderings. The default is
434  // nullptr.
435  virtual Dynacoe::Framebuffer * GetTarget() = 0;
436 
437 
438  // Returns the framebuffer types that this renderer supports.
439  // Should the framebuffer not match one of the given types, the framebuffer
440  // attachment will fail
441  virtual std::vector<Dynacoe::Framebuffer::Type> SupportedFramebuffers() = 0;
442 };
443 
444 
445 
446 }
447 
448 
449 #endif
Contains a visual state.
Definition: Framebuffer.h:49
Definition: AssetID.h:37