1 module example;
2 
3 import std..string;
4 import std.conv;
5 import std.stdio;
6 
7 import derelict.opengl3.gl3;
8 import derelict.sdl2.sdl;
9 
10 import glamour.vao: VAO;
11 import glamour.shader: Shader;
12 import glamour.vbo: Buffer, ElementBuffer;
13 
14 class Renderer
15 {
16 private:
17     uint width_, height_;
18 
19     float[] vertices;
20     ushort[] indices;
21     GLint position_;
22 
23     VAO vao_;
24     Shader program_;
25     Buffer vbo_;
26     ElementBuffer ibo_;
27 
28     /// ATTENTION! All shaders are placed in the single source.
29     /// Source contains up to three shaders: vertex shader,
30     /// geometry shader and fragment shader.
31     /// Every shader are prefixed by tag to separate from the others.
32     /// Tags are:
33     ///     "vertex:"
34     ///     "geometry:"
35     ///     "fragment:"
36     /// Tag shall be the first token in the line and the rest of the line is ignored.
37     /// Shaders may be ordered in any way. But a shader will be replaced
38     /// by the next shader with the same tag - so there is only one shader with
39     /// the specific tag at the moment.
40     /// Directives are placed in the beginning of the source, not every shader and
41     /// effect on the total source consequently.
42     static immutable string example_program_src_ = `
43         #version 120
44         vertex:
45         attribute vec2 position;
46         void main(void)
47         {
48             gl_Position = vec4(position, 0, 1);
49         }
50         fragment:
51         void main(void)
52         {
53             gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
54         }
55         `;
56 
57 public:
58     this()
59     {
60         vertices = [ -0.3, -0.3,  0.3, -0.3,  -0.3, 0.3,  0.3, 0.3];
61         indices = [0, 1, 2, 3];
62 
63         vao_ = new VAO();
64         vao_.bind();
65 
66         // Create VBO
67         vbo_ = new Buffer(vertices);
68 
69         // Create IBO
70         ibo_ = new ElementBuffer(indices);
71 
72         // Create program
73         program_ = new Shader("example_program", example_program_src_);
74         program_.bind();
75         position_ = program_.get_attrib_location("position");
76     }
77 
78     void draw()
79     {
80         glClearColor(1, 0.9, 0.8, 1);
81         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
82         
83         vbo_.bind();
84         glEnableVertexAttribArray(position_);
85      
86         glVertexAttribPointer(position_, 2, GL_FLOAT, GL_FALSE, 0, null);
87      
88         ibo_.bind();
89      
90         glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, null);
91      
92         glDisableVertexAttribArray(position_);
93     }
94 
95     void close()
96     {
97         // free resources
98         ibo_.remove();
99         vbo_.remove();
100         program_.remove();
101         vao_.remove();
102     }
103 }
104 
105 class SDLApplication
106 {
107     private SDL_Window* sdlwindow_;
108     private OnDraw on_draw_;
109     
110     alias void delegate() OnDraw;
111     
112     @property
113     onDraw(OnDraw on_draw) 
114     { 
115         assert(on_draw);
116         on_draw_ = on_draw; 
117     }
118 
119     this()
120     {
121         DerelictSDL2.load();
122         DerelictGL3.load();
123 
124         if (SDL_Init(SDL_INIT_VIDEO) < 0) {
125             throw new Exception("Failed to initialize SDL: " ~ to!string(SDL_GetError()));
126         }
127 
128         // Set OpenGL version
129         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
130         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
131 
132         // Set OpenGL attributes
133         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
134         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
135 
136         sdlwindow_ = SDL_CreateWindow("Glamour example application",
137             SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
138             640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
139 
140         if (!sdlwindow_)
141             throw new Exception("Failed to create a SDL window: " ~ to!string(SDL_GetError()));
142 
143         SDL_GL_CreateContext(sdlwindow_);
144         DerelictGL3.reload();
145     }
146 
147     void run()
148     {
149         assert(on_draw_);
150         auto run = true;
151         while (run) {
152             SDL_Event event;
153             while (SDL_PollEvent(&event)) {
154                 switch (event.type) {
155                     case SDL_QUIT:
156                         run = false;
157                     break;
158                     default:
159                     break;
160                 }
161             }
162 
163             on_draw_();
164 
165             SDL_GL_SwapWindow(sdlwindow_);
166         }
167     }
168 }
169 
170 void main() {
171     
172     auto app = new SDLApplication();
173 
174     auto renderer = new Renderer();
175     scope(exit)
176         renderer.close();
177 
178     app.onDraw = &renderer.draw;
179     app.run();
180 }