tl;dr
This is where I'm going to write about what I'm playing around with at the moment. Initially, it is going to cover me learning D and OpenGL, but who knows where it'll go from there.
Why?
I let my Internet presence disappear when the web server behind my site died several years ago.
I've tried to start writing again a few times since then - a more "serious" technology/industry-focused blog named "TechGeneral" that I initially built using my TurboGears-based blogging software, gibe. Since then, I've rebuilt it on a number of static website generators, but committing to content was unexpectedly hard.
Anyway, this is my low-pressure alternative to that, where I'll post some updates of me learning D and OpenGL. I jokingly told a colleague at work I hope to build a Minecraft clone in seven-to-ten years.
Technology?
During a rare bit of downtime in my recent vacation in Portland, my "Hello World" D program ended up being a port of the GLFW quickstart. Unfortunately I didn't keep track of what I wrote then, since it morphed into a different project, but here's something I wrote around that time, which gets information about the OpenGL context.
module app; import std.stdio, std.conv; import derelict.glfw3.glfw3; import derelict.opengl3.gl3; string programName = "glfw3Test"; int width = 640; int height = 480; void main() { DerelictGL3.load(); DerelictGLFW3.load(); if(!glfwInit()) { glfwTerminate(); throw new Exception("Failed to create glcontext"); } writefln("GLFW: %s", to!string(glfwGetVersionString())); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); auto window = glfwCreateWindow(width, height, programName.ptr, null, null); if(!window) { glfwTerminate(); throw new Exception("Failed to create window"); } glfwMakeContextCurrent(window); DerelictGL3.reload(); writefln("Vendor: %s", to!string(glGetString(GL_VENDOR))); writefln("Renderer: %s", to!string(glGetString(GL_RENDERER))); writefln("Version: %s", to!string(glGetString(GL_VERSION))); writefln("GLSL: %s", to!string(glGetString(GL_SHADING_LANGUAGE_VERSION))); }
This is what it returns on my MacBookPro:
GLFW: 3.0.4 Cocoa NSGL chdir menubar dynamic Vendor: Intel Inc. Renderer: Intel HD Graphics 4000 OpenGL Engine Version: 4.1 INTEL-8.18.26 GLSL: 4.10
Almost all of that is GLFW or Derelict boilerplate except the last 4 lines where I inspect the OpenGL context to get some information about the implementation in use.
Porting the quickstart was pretty painless - I just generally just copy the C
code, and then fix the warnings. Instead of printf
, I used writefln
.
Instead of (float)x
, I used cast(float)x
. I needed to convert D strings to
C char *
using stringVar.ptr
.
If I needed to pass a C function as a handler, I needed to put it in extern
C
, and indicate it to be nothrow
, and of course not throw, like so:
extern(C) { void mouse_callback(GLFWwindow* window, double x, double y) nothrow { try { writeln("x: ", x, ", y: ", y); } catch(Exception e) { } cameraAngleX -= (x - lastCursorX); lastCursorX = x; cameraAngleY -= (y - lastCursorY); lastCursorY = y; } } glfwSetCursorPosCallback(window, &mouse_callback);
The nice thing about all this was that the D compiler just wouldn't let me get it wrong - I couldn't forget nothrow, and I couldn't not catch the exception of a function that did throw.
One key piece of the D ecosystem for me has been dub, the D package and build manager. My D source code may be a single file now, but it does require various D packages (Derelict, in particular) be installed. It's as simple as:
{ "name": "glfwquick", "description": "Port of glfw quickstart to d.", "homepage": "none", "copyright": "Copyright © 2013 Neil Blakey-Milner", "authors": [ "Neil Blakey-Milner" ], "targetPath": "bin", "dependencies": { "derelict-glfw3": "~master", "derelict-gl3": "~master" } }
I built and installed dub to a user folder, and just run dub build &&
bin/glfwquick
over and over as I iterate. As I add/change dependencies, it
goes off and fetches them from code.dlang.org.
After a few hours, spread over two weeks since then, I've made a bit of progress. Here's one of my example programs:
Next
Unfortunately I've been learning bad habits using OpenGL's "direct mode", so I'll need to start over. Hopefully that means I will be able to build this new code base in a public repository and post here as I make progress.