1 /* 2 * This file is part of gtkD. 3 * 4 * dui is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published by 6 * the Free Software Foundation; either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * dui is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public License 15 * along with dui; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 17 */ 18 19 // To compile: 20 // [gdc] gdc CoreGL.d `pkg-config gtkd-3 gl --cflags --libs` 21 // [dmd] rdmd `pkg-config gtkd-3 --cflags` -L-lGL -L-ldl CoreGL.d 22 23 module coreGL.CoreGL; 24 25 import std.string; 26 27 import gdk.GLContext; 28 import gtk.DrawingArea; 29 import gtk.GLArea; 30 import gtk.Main; 31 import gtk.MainWindow; 32 import gtk.Widget; 33 34 import glcore; 35 36 void main(string[] args) 37 { 38 Main.init(args); 39 40 auto mainWnd = new MainWindow("Simplest GLArea + CoreGL Example"); 41 42 auto wnd = new CoreGL; 43 mainWnd.add(wnd); 44 mainWnd.showAll(); 45 46 Main.run(); 47 } 48 49 /** 50 * A really simple Demo illustrating OpenGL core profile with GtkD 51 * This example is provided under the terms of the GPL License. 52 * 53 * @author sebastien.alaiwan@gmail.com 54 */ 55 class CoreGL : GLArea 56 { 57 public: 58 this() 59 { 60 setAutoRender(true); 61 62 addEvents(GdkEventMask.BUTTON_PRESS_MASK); 63 addEvents(GdkEventMask.SCROLL_MASK); 64 65 addOnRender(&render); 66 addOnRealize(&realize); 67 addOnUnrealize(&unrealize); 68 69 showAll(); 70 } 71 72 GLuint m_Vao; 73 GLuint m_Program; 74 GLuint m_Mvp; 75 76 void realize(Widget) 77 { 78 makeCurrent(); 79 GLuint position_index; 80 GLuint color_index; 81 initShaders(&m_Program, &m_Mvp, &position_index, &color_index); 82 initBuffers(position_index, color_index); 83 } 84 85 void unrealize(Widget) 86 { 87 makeCurrent(); 88 glDeleteBuffers(1, &m_Vao); 89 glDeleteProgram(m_Program); 90 } 91 92 bool render(GLContext c, GLArea a) 93 { 94 makeCurrent(); 95 96 glClearColor(0.3, 0.3, 0.3, 1); 97 glClear(GL_COLOR_BUFFER_BIT); 98 99 drawTriangle(); 100 101 glFlush(); 102 103 return true; 104 } 105 106 void drawTriangle() 107 { 108 immutable mvp = getIdentityMatrix(); 109 110 glUseProgram(m_Program); 111 112 // update the "mvp" matrix we use in the shader 113 glUniformMatrix4fv(m_Mvp, 1, GL_FALSE, mvp.ptr); 114 115 glBindBuffer(GL_ARRAY_BUFFER, m_Vao); 116 glEnableVertexAttribArray(0); 117 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null); 118 119 // draw the three vertices as a triangle 120 glDrawArrays(GL_TRIANGLES, 0, 3); 121 122 glDisableVertexAttribArray(0); 123 glBindBuffer(GL_ARRAY_BUFFER, 0); 124 glUseProgram(0); 125 } 126 127 void initBuffers(uint position_index, uint color_index) 128 { 129 static immutable GLfloat[] vertex_data = 130 [ 131 0.0f, 0.5f, 0.0f, 1.0f, 132 0.5f, -0.366f, 0.0f, 1.0f, 133 -0.5f, -0.366f, 0.0f, 1.0f, 134 ]; 135 136 // we need to create a VAO to store the other buffers 137 glGenVertexArrays(1, &m_Vao); 138 glBindVertexArray(m_Vao); 139 140 // this is the VBO that holds the vertex data 141 GLuint buffer; 142 glGenBuffers(1, &buffer); 143 glBindBuffer(GL_ARRAY_BUFFER, buffer); 144 glBufferData(GL_ARRAY_BUFFER, vertex_data.length * float.sizeof, vertex_data.ptr, GL_STATIC_DRAW); 145 146 // reset the state; we will re-enable the VAO when needed 147 glBindBuffer(GL_ARRAY_BUFFER, 0); 148 } 149 } 150 151 void initShaders(uint* program_out, uint* mvp_location_out, uint* position_location_out, uint* color_location_out) 152 { 153 const vertex = compileShader(GL_VERTEX_SHADER, VertShaderCode ~ "\0"); 154 scope(exit) glDeleteShader(vertex); 155 156 const fragment = compileShader(GL_FRAGMENT_SHADER, FragShaderCode ~ "\0"); 157 scope(exit) glDeleteShader(fragment); 158 159 const program = glCreateProgram(); 160 161 glAttachShader(program, vertex); 162 scope(exit) glDetachShader(program, vertex); 163 164 glAttachShader(program, fragment); 165 scope(exit) glDetachShader(program, fragment); 166 167 glLinkProgram(program); 168 169 int status = 0; 170 glGetProgramiv(program, GL_LINK_STATUS, &status); 171 172 if(status == GL_FALSE) 173 { 174 int len = 0; 175 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 176 177 char[] buffer; 178 buffer.length = len + 1; 179 glGetProgramInfoLog(program, len, null, buffer.ptr); 180 181 glDeleteProgram(program); 182 183 throw new Exception(format("Linking failure in program: %s", buffer)); 184 } 185 186 *program_out = program; 187 *mvp_location_out = glGetUniformLocation(program, "mvp"); 188 *position_location_out = glGetAttribLocation(program, "position"); 189 *color_location_out = glGetAttribLocation(program, "color"); 190 } 191 192 uint compileShader(int type, string source) 193 { 194 const shader = glCreateShader(type); 195 scope(failure) glDeleteShader(shader); 196 const(char)*srcPtr = source.ptr; 197 glShaderSource(shader, 1, &srcPtr, null); 198 glCompileShader(shader); 199 200 int status; 201 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 202 203 if(status == GL_FALSE) 204 { 205 int len; 206 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 207 208 char[] buffer; 209 buffer.length = len + 1; 210 glGetShaderInfoLog(shader, len, null, buffer.ptr); 211 212 const sType = type == GL_VERTEX_SHADER ? "vertex" : "fragment"; 213 214 throw new Exception(format("Compilation failure in %s shader: %s", sType, buffer)); 215 } 216 217 return shader; 218 } 219 220 float[16] getIdentityMatrix() pure 221 { 222 float mat[4 * 4]; 223 224 // identity matrix 225 for(int x=0;x < 4;++x) 226 for(int y=0;y < 4;++y) 227 mat[x+y*4] = x==y ? 1 : 0; 228 229 return mat; 230 } 231 232 immutable FragShaderCode = ` 233 #version 130 234 235 smooth in vec4 vertexColor; 236 237 out vec4 outputColor; 238 239 void main() { 240 outputColor = vertexColor; 241 }`; 242 243 immutable VertShaderCode = ` 244 #version 130 245 246 in vec3 position; 247 in vec3 color; 248 249 uniform mat4 mvp; 250 251 smooth out vec4 vertexColor; 252 253 void main() { 254 gl_Position = mvp * vec4(position, 1.0); 255 vertexColor = vec4(color, 1.0); 256 }`; 257