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 gio.Application : GioApplication = Application; 28 import gtk.Application; 29 import gtk.ApplicationWindow; 30 import gdk.GLContext; 31 import gtk.DrawingArea; 32 import gtk.GLArea; 33 import gtk.Widget; 34 35 import glcore; 36 37 int main(string[] args) 38 { 39 Application application; 40 41 void activateCoreGL(GioApplication app) 42 { 43 auto mainWnd = new ApplicationWindow(application); 44 mainWnd.setTitle("Simplest GLArea + CoreGL Example"); 45 46 auto wnd = new CoreGL; 47 mainWnd.add(wnd); 48 mainWnd.showAll(); 49 } 50 51 application = new Application("org.gtkd.demo.gl.core", GApplicationFlags.FLAGS_NONE); 52 application.addOnActivate(&activateCoreGL); 53 return application.run(args); 54 } 55 56 /** 57 * A really simple Demo illustrating OpenGL core profile with GtkD 58 * This example is provided under the terms of the GPL License. 59 * 60 * @author sebastien.alaiwan@gmail.com 61 */ 62 class CoreGL : GLArea 63 { 64 public: 65 this() 66 { 67 setAutoRender(true); 68 69 addEvents(GdkEventMask.BUTTON_PRESS_MASK); 70 addEvents(GdkEventMask.SCROLL_MASK); 71 72 addOnRender(&render); 73 addOnRealize(&realize); 74 addOnUnrealize(&unrealize); 75 76 showAll(); 77 } 78 79 GLuint m_Vao; 80 GLuint m_Program; 81 GLuint m_Mvp; 82 83 void realize(Widget) 84 { 85 makeCurrent(); 86 GLuint position_index; 87 GLuint color_index; 88 initShaders(&m_Program, &m_Mvp, &position_index, &color_index); 89 initBuffers(position_index, color_index); 90 } 91 92 void unrealize(Widget) 93 { 94 makeCurrent(); 95 glDeleteBuffers(1, &m_Vao); 96 glDeleteProgram(m_Program); 97 } 98 99 bool render(GLContext c, GLArea a) 100 { 101 makeCurrent(); 102 103 glClearColor(0.3, 0.3, 0.3, 1); 104 glClear(GL_COLOR_BUFFER_BIT); 105 106 drawTriangle(); 107 108 glFlush(); 109 110 return true; 111 } 112 113 void drawTriangle() 114 { 115 immutable mvp = getIdentityMatrix(); 116 117 glUseProgram(m_Program); 118 119 // update the "mvp" matrix we use in the shader 120 glUniformMatrix4fv(m_Mvp, 1, GL_FALSE, mvp.ptr); 121 122 glBindBuffer(GL_ARRAY_BUFFER, m_Vao); 123 glEnableVertexAttribArray(0); 124 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null); 125 126 // draw the three vertices as a triangle 127 glDrawArrays(GL_TRIANGLES, 0, 3); 128 129 glDisableVertexAttribArray(0); 130 glBindBuffer(GL_ARRAY_BUFFER, 0); 131 glUseProgram(0); 132 } 133 134 void initBuffers(uint position_index, uint color_index) 135 { 136 static immutable GLfloat[] vertex_data = 137 [ 138 0.0f, 0.5f, 0.0f, 1.0f, 139 0.5f, -0.366f, 0.0f, 1.0f, 140 -0.5f, -0.366f, 0.0f, 1.0f, 141 ]; 142 143 // we need to create a VAO to store the other buffers 144 glGenVertexArrays(1, &m_Vao); 145 glBindVertexArray(m_Vao); 146 147 // this is the VBO that holds the vertex data 148 GLuint buffer; 149 glGenBuffers(1, &buffer); 150 glBindBuffer(GL_ARRAY_BUFFER, buffer); 151 glBufferData(GL_ARRAY_BUFFER, vertex_data.length * float.sizeof, vertex_data.ptr, GL_STATIC_DRAW); 152 153 // reset the state; we will re-enable the VAO when needed 154 glBindBuffer(GL_ARRAY_BUFFER, 0); 155 } 156 } 157 158 void initShaders(uint* program_out, uint* mvp_location_out, uint* position_location_out, uint* color_location_out) 159 { 160 const vertex = compileShader(GL_VERTEX_SHADER, VertShaderCode ~ "\0"); 161 scope(exit) glDeleteShader(vertex); 162 163 const fragment = compileShader(GL_FRAGMENT_SHADER, FragShaderCode ~ "\0"); 164 scope(exit) glDeleteShader(fragment); 165 166 const program = glCreateProgram(); 167 168 glAttachShader(program, vertex); 169 scope(exit) glDetachShader(program, vertex); 170 171 glAttachShader(program, fragment); 172 scope(exit) glDetachShader(program, fragment); 173 174 glLinkProgram(program); 175 176 int status = 0; 177 glGetProgramiv(program, GL_LINK_STATUS, &status); 178 179 if(status == GL_FALSE) 180 { 181 int len = 0; 182 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 183 184 char[] buffer; 185 buffer.length = len + 1; 186 glGetProgramInfoLog(program, len, null, buffer.ptr); 187 188 glDeleteProgram(program); 189 190 throw new Exception(format("Linking failure in program: %s", buffer)); 191 } 192 193 *program_out = program; 194 *mvp_location_out = glGetUniformLocation(program, "mvp"); 195 *position_location_out = glGetAttribLocation(program, "position"); 196 *color_location_out = glGetAttribLocation(program, "color"); 197 } 198 199 uint compileShader(int type, string source) 200 { 201 const shader = glCreateShader(type); 202 scope(failure) glDeleteShader(shader); 203 const(char)*srcPtr = source.ptr; 204 glShaderSource(shader, 1, &srcPtr, null); 205 glCompileShader(shader); 206 207 int status; 208 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 209 210 if(status == GL_FALSE) 211 { 212 int len; 213 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 214 215 char[] buffer; 216 buffer.length = len + 1; 217 glGetShaderInfoLog(shader, len, null, buffer.ptr); 218 219 const sType = type == GL_VERTEX_SHADER ? "vertex" : "fragment"; 220 221 throw new Exception(format("Compilation failure in %s shader: %s", sType, buffer)); 222 } 223 224 return shader; 225 } 226 227 float[16] getIdentityMatrix() pure 228 { 229 float[4 * 4] mat; 230 231 // identity matrix 232 for(int x=0;x < 4;++x) 233 for(int y=0;y < 4;++y) 234 mat[x+y*4] = x==y ? 1 : 0; 235 236 return mat; 237 } 238 239 immutable FragShaderCode = ` 240 #version 130 241 242 smooth in vec4 vertexColor; 243 244 out vec4 outputColor; 245 246 void main() { 247 outputColor = vertexColor; 248 }`; 249 250 immutable VertShaderCode = ` 251 #version 130 252 253 in vec3 position; 254 in vec3 color; 255 256 uniform mat4 mvp; 257 258 smooth out vec4 vertexColor; 259 260 void main() { 261 gl_Position = mvp * vec4(position, 1.0); 262 vertexColor = vec4(color, 1.0); 263 }`; 264