1 module prova.graphics.screen;
2 
3 import derelict.sdl2.sdl;
4 import prova.assets;
5 import prova.core;
6 import prova.entities;
7 import prova.graphics;
8 import prova.math;
9 import std.conv;
10 import std.math;
11 
12 ///
13 final class Screen : RenderTarget
14 {
15   private Game game;
16   private Mesh quad;
17   private Matrix quadProjectionMatrix;
18   private Color clearColor;
19 
20   package(prova) this(Game game, GraphicsContext context, int width, int height)
21   {
22     this.game = game;
23 
24     super(context, width, height);
25     disableVSync();
26 
27     quad = new SpriteMesh();
28     quadProjectionMatrix = createQuadProjectionMatrix();
29     clearColor.set(0, 0, 0, 0);
30   }
31 
32   private Matrix createQuadProjectionMatrix()
33   {
34     Matrix quadProjectionMatrix = Matrix.identity;
35     quadProjectionMatrix = quadProjectionMatrix.scale(2, 2, 1);
36     quadProjectionMatrix = quadProjectionMatrix.translate(-1, -1);
37 
38     return quadProjectionMatrix;
39   }
40 
41   // Forward of the active scene's camera
42   private @property Camera camera()
43   {
44     return game.activeScene.camera;
45   }
46 
47   /// Resizes the window
48   override void resize(int width, int height)
49   {
50     SDL_SetWindowSize(game.window, width, height);
51     updateResolution(width, height);
52   }
53 
54   package(prova) void updateResolution(int width, int height)
55   {
56     super.resize(width, height);
57   }
58 
59   ///
60   void enableVSync()
61   {
62     if(SDL_GL_SetSwapInterval(1) < 0)
63       throw new Exception("VSync Error: " ~ to!string(SDL_GetError()));
64   }
65 
66   ///
67   void disableVSync()
68   {
69     if(SDL_GL_SetSwapInterval(0) < 0)
70       throw new Exception("VSync Error: " ~ to!string(SDL_GetError()));
71   }
72 
73   ///
74   void setClearColor(float r, float g, float b)
75   {
76     clearColor.r = r;
77     clearColor.g = g;
78     clearColor.b = b;
79   }
80 
81   ///
82   void setClearColor(Color color)
83   {
84     clearColor = color;
85   }
86 
87   ///
88   override void clear()
89   {
90     bindFrameBuffer(0);
91 
92     glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
93     glClearDepth(1);
94     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
95 
96     super.clear();
97   }
98 
99   package(prova) void prepare()
100   {
101     clear();
102 
103     if(camera.useDepthBuffer)
104       glEnable(GL_DEPTH_TEST);
105     else
106       glDisable(GL_DEPTH_TEST);
107 
108     if(camera.resolutionDependent) {
109       camera.width = width;
110       camera.height = height;
111     }
112   }
113 
114   package(prova) void prepareDynamic()
115   {
116     Matrix projection = camera.getScreenMatrix();
117 
118     begin(projection);
119   }
120 
121   package(prova) void endDynamic()
122   {
123     end();
124   }
125 
126   package(prova) void prepareStatic()
127   {
128     Matrix projection = camera.getUIMatrix();
129 
130     begin(projection);
131   }
132 
133   package(prova) void endStatic()
134   {
135     end();
136   }
137 
138   package(prova) void swapBuffer()
139   {
140     // render the FBO
141     context.spriteShader.setMatrix("transform", quadProjectionMatrix);
142     context.spriteShader.setTexture(0, texture.id);
143     context.spriteShader.setVector4("clip", Rect(0, 0, 1, 1));
144     context.spriteShader.setVector4("tint", Color(1, 1, 1));
145     context.spriteShader.drawMesh(quad, 0, DrawMode.TRIANGLE_FAN);
146 
147     SDL_GL_SwapWindow(game.window);
148   }
149 }