www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using OpenGL

reply Darren <darren.fielding hotmail.co.uk> writes:
I'm trying to teach myself OpenGL but I'm not sure how to set it 
up exactly.
I used "dub init" to create a project, I downloaded glew32.dll 
and glfw.dll and put them in this folder.  I added 
"derelict-gl3": "~>1.0.19" and "derelict-glfw3": "~>3.1.0" to 
dependencies, and imported them in the app.d file.  I add the 
load() and reload() functions where appropriate (I assume).

I can run a simple window program and it seems to work fine, but 
I notice that's when all the functions begin with "glfw".  If I 
try to follow a tutorial for loading a triangle, I get errors 
when trying to build.

Do I need to link an opengl.dll file, too?
Sep 02 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 2 September 2016 at 20:38:15 UTC, Darren wrote:
 I'm trying to teach myself OpenGL but I'm not sure how to set 
 it up exactly.
 I used "dub init" to create a project, I downloaded glew32.dll 
 and glfw.dll and put them in this folder.  I added 
 "derelict-gl3": "~>1.0.19" and "derelict-glfw3": "~>3.1.0" to 
 dependencies, and imported them in the app.d file.  I add the 
 load() and reload() functions where appropriate (I assume).
You don't need GLEW. It's a library for C and C++ that loads all of the OpenGL functions and extensions available in the context you create. DerelictGL3 does that for you in D. DerelictGl3.load loads the OpenGL DLL and the functions up to OGL 1.1, and DerelictGL3.reload loads all the functions and extensions available in the current context.
 I can run a simple window program and it seems to work fine, 
 but I notice that's when all the functions begin with "glfw".
Yes, GLFW is a simple windowing toolkit for creating windows & OpenGL contexts and managing window & input events in a cross-platform manner. Without it, you would need to use the system APIs yourself (such as Win32 on Windows) or another cross-platform library like SDL or SFML.
 If I try to follow a tutorial for loading a triangle, I get 
 errors when trying to build.

 Do I need to link an opengl.dll file, too?
No, you do not need to link to OpenGL. By default, Derelict loads shared libraries at runtime so you will never have a link-time dependency on the C libraries Derelict binds to. Please post the errors you are seeing.
Sep 02 2016
parent reply Darren <darren.fielding hotmail.co.uk> writes:
Thanks for the information.  The errors for the tutorial I _was_ 
trying to make work are as follows:

source\app.d(9,5): Error: undefined identifier 'Window', did you 
mean variable 'window'?
source\app.d(98,12): Error: undefined identifier 'Window', did 
you mean variable 'window'?
source\app.d(101,14): Error: undefined identifier 'GLBuffer'
source\app.d(104,14): Error: undefined identifier 'Shader'
source\app.d(107,13): Error: undefined identifier 'Program', did 
you mean variable 'program'?
source\app.d(110,15): Error: undefined identifier 'Attribute'

I thought I might have needed another package for these, and gfm 
seemed to contain what I need in the form of the opengl 
sub-package.  But even after importing that, it only gets rid of 
the GLBuffer error.

I tried to follow another tutorial.  Link to source code: 
http://www.learnopengl.com/code_viewer.php?code=getting-started/hellotriangle

I'm having more success with this one.  I pretty much hacked away 
at this and did my best to convert from C-style code to D.  The 
window gets made and it has the green-ish background, but it's 
not drawing any triangles.  Should I copy/paste the code I'm 
using in case I made a mistake?
Sep 03 2016
parent reply pineapple <meapineapple gmail.com> writes:
On Saturday, 3 September 2016 at 09:30:58 UTC, Darren wrote:
 Thanks for the information.  The errors for the tutorial I 
 _was_ trying to make work are as follows:

 source\app.d(9,5): Error: undefined identifier 'Window', did 
 you mean variable 'window'?
 source\app.d(98,12): Error: undefined identifier 'Window', did 
 you mean variable 'window'?
 source\app.d(101,14): Error: undefined identifier 'GLBuffer'
 source\app.d(104,14): Error: undefined identifier 'Shader'
 source\app.d(107,13): Error: undefined identifier 'Program', 
 did you mean variable 'program'?
 source\app.d(110,15): Error: undefined identifier 'Attribute'

 I thought I might have needed another package for these, and 
 gfm seemed to contain what I need in the form of the opengl 
 sub-package.  But even after importing that, it only gets rid 
 of the GLBuffer error.

 I tried to follow another tutorial.  Link to source code: 
 http://www.learnopengl.com/code_viewer.php?code=getting-started/hellotriangle

 I'm having more success with this one.  I pretty much hacked 
 away at this and did my best to convert from C-style code to D.
  The window gets made and it has the green-ish background, but 
 it's not drawing any triangles.  Should I copy/paste the code 
 I'm using in case I made a mistake?
It's not quite in a practically-usable state yet, but the SDL2 & OpenGL wrapper I'm working on may interest you as an example implementation if nothing else. https://github.com/pineapplemachine/mach.d/tree/master/mach/sdl Here's an example of a functioning program using the package. At the moment I'm working on exposing SDL2's event and other input systems. import std.datetime; import mach.math.vector2; import mach.sdl.window; import mach.sdl.texture; import mach.sdl.color; import mach.sdl.primitives; void main(){ // Create a window auto win = new Window(300, 300); win.position = Vector2!int(200, 200); // Load a texture auto tex = Texture("pineapple.png"); // Loop for 5 seconds StopWatch sw; sw.start(); auto maxms = 5000f; while(true){ auto ms = sw.peek().msecs; if(ms >= maxms) break; // Fill with green win.clear(0, ms / maxms / 2, 0); // Draw centered image tex.draw((win.size - tex.size) / 2); // Draw red lines at top and bottom lines(Color!ubyte.Red, Vector2!int(8, 8), Vector2!int(292, 8), Vector2!int(292, 292), Vector2!int(8, 292) ); // Display changes win.swap(); } }
Sep 03 2016
parent reply Darren <darren.fielding hotmail.co.uk> writes:
 It's not quite in a practically-usable state yet, but the SDL2 
 & OpenGL wrapper I'm working on may interest you as an example 
 implementation if nothing else. 
 https://github.com/pineapplemachine/mach.d/tree/master/mach/sdl
I'm going to take a look at this, once I get my bearings, on the merits of the name alone! I'm sure there are a few tutorials that make use of SDL2 that I can use. My hope is that once I know how to set up, learning OpenGL will be more a matter of D-ifying the C-code. I'll post the modified code I'm trying to get work in full below. Some code is commented out because I couldn't make it work. Also any tips for making the code nicer would be welcome (e.g. would I change the const GLunit into enums?). ##### import derelict.glfw3.glfw3; import derelict.opengl3.gl3; import std.stdio; void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); } const GLuint WIDTH = 800, HEIGHT = 600; const GLchar* vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 position;\n" "void main()\n" "{\n" "gl_Position = vec4(position.x, position.y, position.z, 1.0);\n" "}\0"; const GLchar* fragmentShaderSource = "#version 330 core\n" "out vec4 color;\n" "void main()\n" "{\n" "color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" "}\n\0"; void main() { DerelictGLFW3.load(); DerelictGL3.load(); glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", null, null); glfwMakeContextCurrent(window); DerelictGL3.reload(); //glfwSetKeyCallback(window, key_callback); int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, null); glCompileShader(vertexShader); GLint success; GLchar[512] infoLog; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { //glGetShaderInfoLog(vertexShader, 512, null, infoLog); writeln("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n", infoLog); } GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, null); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { //glGetShaderInfoLog(fragmentShader, 512, null, infoLog); writeln("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n", infoLog); } GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { //glGetProgramInfoLog(shaderProgram, 512, null, infoLog); writeln("ERROR::SHADER::PROGRAM::LINKING_FAILED\n", infoLog); } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); GLfloat[] vertices = [ -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f ]; GLuint VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, vertices.sizeof, cast(void*)vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * GLfloat.sizeof, cast(GLvoid*)0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); glfwSwapBuffers(window); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glfwTerminate(); }
Sep 03 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Saturday, 3 September 2016 at 10:30:13 UTC, Darren wrote:
 [...]
I never used OpenGL in D, but from a quick glance at your code, I'll suggest trying the following changes:
         //glGetShaderInfoLog(vertexShader, 512, null, infoLog);
glGetShaderInfoLog(vertexShader, 512, null, &infoLog[0]);
     //glfwSetKeyCallback(window, key_callback);
glfwSetKeyCallback(window, &key_callback);
Sep 03 2016
next sibling parent reply Darren <darren.fielding hotmail.co.uk> writes:
On Saturday, 3 September 2016 at 11:02:11 UTC, Lodovico Giaretta 
wrote:
//glGetShaderInfoLog(vertexShader, 512, null, infoLog);
glGetShaderInfoLog(vertexShader, 512, null, &infoLog[0]);
Thank you, I knew I had to do something like this!
//glfwSetKeyCallback(window, key_callback);
glfwSetKeyCallback(window, &key_callback);
I actually tried this before but it doesn't work. I get the following error: Error: function pointer glfwSetKeyCallback (GLFWwindow*, extern (C) void function(GLFWwindow*, int, int, int, int) nothrow) is not callable using argument types (GLFWwindow*, void function(GLFWwindow* window, int key, int scancode, int action, int mode))
Sep 03 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Saturday, 3 September 2016 at 11:10:00 UTC, Darren wrote:
 On Saturday, 3 September 2016 at 11:02:11 UTC, Lodovico 
 Giaretta wrote:
//glfwSetKeyCallback(window, key_callback);
glfwSetKeyCallback(window, &key_callback);
I actually tried this before but it doesn't work. I get the following error: Error: function pointer glfwSetKeyCallback (GLFWwindow*, extern (C) void function(GLFWwindow*, int, int, int, int) nothrow) is not callable using argument types (GLFWwindow*, void function(GLFWwindow* window, int key, int scancode, int action, int mode))
Ah! Well, providing error messages is always useful. Now I see your issue: your callback has D linkage, but OpenGL expects a function with C linkage. So you have to put `extern(C)` on your callback declaration.
Sep 03 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Saturday, 3 September 2016 at 11:13:30 UTC, Lodovico Giaretta 
wrote:
 
 Ah! Well, providing error messages is always useful. Now I see 
 your issue: your callback has D linkage, but OpenGL expects a 
 function with C linkage. So you have to put `extern(C)` on your 
 callback declaration.
Well, it's GLFW, not OpenGL, but yes they do need to be extern (C) and also nothrow, as that is how the callback types are declared in Derrlict: ``` extern(C) nothrow void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); } ```
Sep 03 2016
parent Darren <darren.fielding hotmail.co.uk> writes:
On Saturday, 3 September 2016 at 11:27:09 UTC, Mike Parker wrote:
 On Saturday, 3 September 2016 at 11:13:30 UTC, Lodovico 
 Giaretta wrote:
 
 Ah! Well, providing error messages is always useful. Now I see 
 your issue: your callback has D linkage, but OpenGL expects a 
 function with C linkage. So you have to put `extern(C)` on 
 your callback declaration.
Well, it's GLFW, not OpenGL, but yes they do need to be extern (C) and also nothrow, as that is how the callback types are declared in Derrlict: ``` extern(C) nothrow void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); } ```
Hey, it worked! Thanks a lot, I know what to do in the future now. Just need to figure out why this triangle isn't showing up and I should be well on my way.
Sep 03 2016
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Saturday, 3 September 2016 at 11:02:11 UTC, Lodovico Giaretta 
wrote:

 glGetShaderInfoLog(vertexShader, 512, null, &infoLog[0]);
I prefer: glGetShaderInfoLog(vertexShader, 512, null, infoLog.ptr);
Sep 03 2016
parent reply Darren <darren.fielding hotmail.co.uk> writes:
On Saturday, 3 September 2016 at 11:33:10 UTC, Mike Parker wrote:
 On Saturday, 3 September 2016 at 11:02:11 UTC, Lodovico 
 Giaretta wrote:

 glGetShaderInfoLog(vertexShader, 512, null, &infoLog[0]);
I prefer: glGetShaderInfoLog(vertexShader, 512, null, infoLog.ptr);
That is a good tip to know. I went through another tutorial. Changed the source code and left out the shaders. I get another coloured background but still no triangle. I have a feeling that glBufferData(GL_ARRAY_BUFFER, cast(int)g_vertex_buffer_data.sizeof, cast(void*)g_vertex_buffer_data, GL_STATIC_DRAW); in one example, or glBufferData(GL_ARRAY_BUFFER, vertices.sizeof, cast(void*)vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * GLfloat.sizeof, cast(GLvoid*)0); in the other might be responsible, since they seem to be related to drawing the triangle and I'm casting arguments in order to get the program to compile. (In the first line, glBufferData wants an int, and .sizeof returns a uint, apparently.) I'm sure there's something simple I'm missing but I just don't have the experience to recognise it.
Sep 03 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Saturday, 3 September 2016 at 12:40:58 UTC, Darren wrote:

 I went through another tutorial. Changed the source code and 
 left out the shaders.  I get another coloured background but 
 still no triangle.  I have a feeling that

     glBufferData(GL_ARRAY_BUFFER, 
 cast(int)g_vertex_buffer_data.sizeof,
                  cast(void*)g_vertex_buffer_data, 
 GL_STATIC_DRAW);
Your vertices array is declared as a dynamic array. That means vertices.sizeof gives you the size of the *array reference*, not the data it contains. For a static array, you get the cumulative size of the data. See my changes in the code below.
 (In the first line, glBufferData wants an int, and .sizeof 
 returns a uint, apparently.)
That's irrelevant in this case. But sizeof is size_t, which is uint on 32-bit systems and long on 64-bit systems.
 I'm sure there's something simple I'm missing but I just don't 
 have the experience to recognise it.
The following compiles, runs, and shows the triangle. It's the code you posted above with the corrected call to glBufferData along with more D style (as I would write it anyway) and less C. Comments are inline. Probably best if you copy and paste it into an editor. ``` import std.stdio, std.format; import derelict.glfw3.glfw3; import derelict.opengl3.gl3; // Match the Derelict decleration of GLFW callbacks // https://github.com/DerelictOrg/DerelictGLFW3/blob/master/source/derelict/glfw3/types.d#L319 extern(C) nothrow { // Setting an error handler will let you get better error messages from GLFW // when something fails. // http://www.glfw.org/docs/latest/intro_guide.html#error_handling void onError(int error, const(char)* msg) { import std.conv : to; try { // The callback is nothrow, but format is not, so the // try...catch errMsg = format("GLFW Error #%s: %s", error, to!string(msg)); } catch(Exception e) {} } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); } } // This will save the error message from the callback private auto errMsg = "No Error"; // Use manifest constants rather than const // https://dlang.org/spec/enum.html#manifest_constants enum WIDTH = 800; enum HEIGHT = 600; // Rather than using multiple string literals with manual newlines, use // WYSIWYG strings as manifest constants. Looks cleaner (but requires an // extra step when calling glShaderSource). enum vertexShaderSource = `#version 330 core layout (location = 0) in vec3 position; void main() { gl_Position = vec4(position.x, position.y, position.z, 1.0); }`; enum fragmentShaderSource = `#version 330 core out vec4 color; void main() { color = vec4(1.0f, 0.5f, 0.2f, 1.0f); }`; void main() { DerelictGLFW3.load(); DerelictGL3.load(); // Set the error callback before calling glfwInit so that a useful message // can be reported on failure glfwSetErrorCallback(&onError); // Always check for failure if(!glfwInit()) throw new Exception("Failed to init GLFW: " ~ errMsg); // Ensure that glfwTerminate is called even when an exception is thrown scope(exit) glfwTerminate(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Optonal: Remove deprecated functionality glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, 1); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Always check for failure GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", null, null); if(!window) throw new Exception("Failed to create window"); glfwMakeContextCurrent(window); DerelictGL3.reload(); glfwSetKeyCallback(window, &key_callback); int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); // Because I switched the shader source to D strings, a slight adjustment // is needed here: const(char)* srcPtr = vertexShaderSource.ptr; glShaderSource(vertexShader, 1, &srcPtr, null); glCompileShader(vertexShader); GLint result; // Use dynamic arrays for the info logs so that you can always // ensure you have enough room. And throw exceptions on failure. glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &result); if (!result) { glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &result); auto infoLog = new char[](result); glGetShaderInfoLog(vertexShader, 512, null, infoLog.ptr); throw new Exception(format("Failed to compile vertex shader:\n\t%s", infoLog)); } GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); srcPtr = fragmentShaderSource.ptr; glShaderSource(fragmentShader, 1, &srcPtr, null); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &result); if (!result) { glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &result); auto infoLog = new char[](result); glGetShaderInfoLog(vertexShader, 512, null, infoLog.ptr); throw new Exception(format("Failed to compile fragment shader:\n\t%s", infoLog)); } GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &result); if (!result) { glGetProgramiv(shaderProgram, GL_LINK_STATUS, &result); auto infoLog = new char[](result); glGetProgramInfoLog(shaderProgram, 512, null, infoLog.ptr); throw new Exception(format("Failed to link shader program:\n\t%s", infoLog)); } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); GLfloat[] vertices = [ -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f ]; GLuint VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // Ensure these objects are always deleted on exit scope(exit) { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); } glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); // You've declared vertices as a dynamic array, not a static array, so // vertices.sizeof is *not* going to give you the result you want -- it's // giving you the size of an array reference. To get the size of the data, // you need to use vertices.length * float.sizeof (which is always 4, so you // could use that instead). glBufferData(GL_ARRAY_BUFFER, vertices.length * float.sizeof, vertices.ptr, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * GLfloat.sizeof, cast(GLvoid*)0); glEnableVertexAttribArray(0); // No need for this in this simple program, where you only have one VAO and // one VBO. Just leave them bound. You only need to reset when you are using // multiple buffers. /* glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); */ while (!glfwWindowShouldClose(window)) { glfwPollEvents(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shaderProgram); //glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); //glBindVertexArray(0); glfwSwapBuffers(window); } } ```
Sep 03 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Saturday, 3 September 2016 at 16:01:34 UTC, Mike Parker wrote:

 The following compiles, runs, and shows the triangle. It's the 
 code you posted above with the corrected call to glBufferData 
 along with more D style (as I would write it anyway) and less C.
One thing I overlooked. In lines where a variable is both declared and initialized, like this one: GLFWwindow* window = glfwCreateWindow(...); I normally let the compiler use type inference as I did in the manifest constant declarations: auto window = glfwCreateWindow(...); IMO, when you're dealing with long or ugly type names, it makes the code look cleaner.
Sep 03 2016
parent reply Darren <darren.fielding hotmail.co.uk> writes:
On Saturday, 3 September 2016 at 16:07:52 UTC, Mike Parker wrote:
 On Saturday, 3 September 2016 at 16:01:34 UTC, Mike Parker 
 wrote:

 The following compiles, runs, and shows the triangle. It's the 
 code you posted above with the corrected call to glBufferData 
 along with more D style (as I would write it anyway) and less 
 C.
The dynamic array! Thank you so much, I changed that on another file and it finally drew the triangle. And I ran your code and it works brilliantly. I should now be in a comfortable position to digest all this information now. Can't thank you enough.
 One thing I overlooked. In lines where a variable is both 
 declared and initialized, like this one:
 GLFWwindow* window = glfwCreateWindow(...);

 I normally let the compiler use type inference as I did in the 
 manifest constant declarations:
 auto window = glfwCreateWindow(...);

 IMO, when you're dealing with long or ugly type names, it makes 
 the code look cleaner.
Yeah, it is nicer to read. Now I wonder if I can load shaders from separate files (à la http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/).
Sep 03 2016
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Saturday, 3 September 2016 at 17:13:49 UTC, Darren wrote:
 On Saturday, 3 September 2016 at 16:07:52 UTC, Mike Parker 
 wrote:
[...]
The dynamic array! Thank you so much, I changed that on another file and it finally drew the triangle. And I ran your code and it works brilliantly. I should now be in a comfortable position to digest all this information now. Can't thank you enough.
 [...]
Yeah, it is nicer to read. Now I wonder if I can load shaders from separate files (à la http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/).
see: https://p0nce.github.io/d-idioms/#Embed-a-dynamic-library-in-an-executable for `import`ing external files at compile time.
Sep 04 2016
parent Guillaume Piolat <first.last gmail.com> writes:
On Monday, 5 September 2016 at 05:14:56 UTC, Nicholas Wilson 
wrote:
 On Saturday, 3 September 2016 at 17:13:49 UTC, Darren wrote:
 Now I wonder if I can load shaders from separate files (à la 
 http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/).
see: https://p0nce.github.io/d-idioms/#Embed-a-dynamic-library-in-an-executable for `import`ing external files at compile time.
It's often useful to be able to reload shaders at runtime.
Sep 05 2016
prev sibling parent reply Darren <darren.fielding hotmail.co.uk> writes:
Kind of resurrecting this thread; hope that's okay.

I'm working through this tutorial: 
http://www.learnopengl.com/#!Getting-started/Textures

It uses SOIL to load images, but I haven't seen any SOIL bindings 
in dub.  I tried using SDL and SDL_Image but when the program ran 
it just crashed.  I guess I was doing something wrong.

While googling, the idea seemed to be to create and SDL_Surface* 
and pass that (or surface.pixels) as the last argument for 
glTexImage2D.  Didn't work for me, however.

Does anyone have any tips?
Sep 14 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Wednesday, 14 September 2016 at 16:49:51 UTC, Darren wrote:

 While googling, the idea seemed to be to create and 
 SDL_Surface* and pass that (or surface.pixels) as the last 
 argument for glTexImage2D.  Didn't work for me, however.

 Does anyone have any tips?
I'm driving blind here without any of your code to see, but here's some general advice. The last three arguments to glTexImage2D [1] are what you use to describe the image data you are sending to it (aside from 'width' & 'height', which also set the size of the texture being created). `format` needs to match the format of your image. For most simple things you do with OpenGL, that's going to be GL_RGB or GL_RGBA. If you don't know the format of your image, you can get it from the SDL_PixelFormatEnum value [2] in surface.format.format. Then you'll just need to send the corresponding GL enum to glTexImage2D. Though, be aware that the way SDL and OGL treat color formats may not always correspond in the way you think they should [3]. `type` is almost always going to be GL_UNSIGNED_BYTE. I don't know that SDL_image supports anything else, like floating point formats, anyway. `data` needs to be a pointer to the pixel data and nothing else (never SDL_Surface!), so in this case surface.pixels is correct. If you are getting a crash, check the return of any of the image loading functions you call to make sure the load was successful. That's the first place I'd check. [1] https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml [2] https://wiki.libsdl.org/SDL_PixelFormatEnum [3] https://bugzilla.libsdl.org/show_bug.cgi?id=2111
Sep 14 2016
parent reply Darren <darren.fielding hotmail.co.uk> writes:
On Thursday, 15 September 2016 at 02:11:03 UTC, Mike Parker wrote:
 //snip
Okay the crashing was my fault, more or less a copy-paste error. The program now runs but has a black rectangle where a texture should be. This is the code I'm using: https://dfcode.wordpress.com/2016/09/15/texcodewip/ (The code for the shaders is at the bottom) For comparison, this is the code I'm trying to make work: http://www.learnopengl.com/code_viewer.php?code=getting-started/textures
Sep 15 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 15 September 2016 at 19:03:22 UTC, Darren wrote:

 This is the code I'm using: 
 https://dfcode.wordpress.com/2016/09/15/texcodewip/
 (The code for the shaders is at the bottom)

 For comparison, this is the code I'm trying to make work:
 http://www.learnopengl.com/code_viewer.php?code=getting-started/textures
I don't have time to try and test this myself, but this looks like a potential problem here: ``` auto textureFormat = surface.format.format; glTexImage2D(GL_TEXTURE_2D, 0, surface.format.BytesPerPixel, surface.w, surface.h, 0, textureFormat, GL_UNSIGNED_BYTE, surface.pixels); ``` You're passing an SDL enum value to OpenGL, which knows absolutely nothing about SDL enum values. Rather than passing surface.format.format directly to OGL, you need to first match it to the appropriate OGL format enum and pass *that*, which is what I tried to explain in my previous post. This is easily done by making a function which contains a switch statement iterating all of the SDL_PIXELFORMAT_* values and returning the equivalent GL_* value. At any rate, if you're using the same image as the example, you don't need to do that in this specific case. You can safely ignore surface.format.format and simply pass GL_RGB, which is what the example uses. You only need to do the SDL->GL conversion for a texture loader that is intended to load multiple pixel formats.
Sep 15 2016
parent reply Darren <darren.fielding hotmail.co.uk> writes:
On Friday, 16 September 2016 at 01:54:50 UTC, Mike Parker wrote:
snip
Okay,I actually had GL_RGB for those two fields and it didn't work, but I guess I didn't try them again after I fixed the crash issue because now it works fine. Thanks again for the guidance!
Sep 16 2016
parent reply Darren <darren.fielding hotmail.co.uk> writes:
Back again with another little problem that isn't specifically 
OpenGL related, but is a result of getting such code to work.

Code I'm working on: 
https://dfcode.wordpress.com/2016/10/04/linker-problem/
What I'm learning from: 
http://www.learnopengl.com/#!Getting-started/Camera, 
http://www.learnopengl.com/code_viewer.php?type=header&code=camera

The problem is I'm trying to move camera code into a module and 
import it, but when I try to build I'm getting the following 
error messages:

source\app.d(256,30): Error: function 
'fpscamera.fpsCamera.processMouseMovement' is not nothrow
source\app.d(243,7): Error: function 'app.mouse_callback' is 
nothrow yet may throw

If I add nothrow to processMouseMovement, like I did for some 
other functions, I get the following:

.dub\build\application-debug-windows-x86-dmd_2071-3EF635850CA47CC4E927BFC9336E0233\ogl.obj(ogl)
  Error 42: Symbol Undefined 
_D9fpscamera9fpsCamera13getViewMatrixMxFNdZS4gl3n6linalg21__T6MatrixTfVii4Vii4Z6Matrix
.dub\build\application-debug-windows-x86-dmd_2071-3EF635850CA47CC4E927BFC9336E0233\ogl.obj(ogl)
  Error 42: Symbol Undefined 
_D9fpscamera9fpsCamera20processMouseMovementMFNbffhZv
.dub\build\application-debug-windows-x86-dmd_2071-3EF635850CA47CC4E927BFC9336E0233\ogl.obj(ogl)
  Error 42: Symbol Undefined 
_D9fpscamera9fpsCamera18processMouseScrollMFNbfZv
.dub\build\application-debug-windows-x86-dmd_2071-3EF635850CA47CC4E927BFC9336E0233\ogl.obj(ogl)
  Error 42: Symbol Undefined 
_D9fpscamera9fpsCamera15processKeyboardMFE9fpscamera14CameraMovementfZv
.dub\build\application-debug-windows-x86-dmd_2071-3EF635850CA47CC4E927BFC9336E0233\ogl.obj(ogl)
  Error 42: Symbol Undefined _D9fpscamera12__ModuleInfoZ
--- errorlevel 5

It seems to happen if I make both processMouseMovement and 
processMouseScroll nothrow to get rid of the error messages.  If 
one or the other is nothrow, I get the nothrow message for that 
function.
Oct 04 2016
parent Darren <darren.fielding hotmail.co.uk> writes:
On Tuesday, 4 October 2016 at 16:09:34 UTC, Darren wrote:
 Back again with another little problem that isn't specifically 
 OpenGL related, but is a result of getting such code to work.
I actually figured it out; my own mistakes.
Oct 05 2016