|
@@ -0,0 +1,196 @@
|
|
|
|
+' https://learnopengl.com/
|
|
|
|
+
|
|
|
|
+SuperStrict
|
|
|
|
+
|
|
|
|
+Framework GLFW.GLFWWindow
|
|
|
|
+
|
|
|
|
+Import GLFW.GLFW
|
|
|
|
+Import GLFW.GLFWOpenGL
|
|
|
|
+Import GLFW.GLFWSystem
|
|
|
|
+
|
|
|
|
+Import BRL.StandardIO
|
|
|
|
+
|
|
|
|
+Local app_name:String = "Hello Triangle Indexed"
|
|
|
|
+
|
|
|
|
+Const SCR_WIDTH:UInt = 800
|
|
|
|
+Const SCR_HEIGHT:UInt = 600
|
|
|
|
+
|
|
|
|
+Type TGameWindow Extends TGLFWWindow
|
|
|
|
+
|
|
|
|
+ ' glfw: whenever the window size changed (by OS or user resize) this callback method executes
|
|
|
|
+ Method OnFrameBufferSize (width:Int, height:Int)
|
|
|
|
+ ' make sure the viewport matches the new window dimensions; note that width and
|
|
|
|
+ ' height will be significantly larger than specified on retina displays.
|
|
|
|
+ glViewport (0, 0, width, height)
|
|
|
|
+ EndMethod
|
|
|
|
+
|
|
|
|
+EndType
|
|
|
|
+
|
|
|
|
+' process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
|
|
|
+Function ProcessInput (window:TGLFWWindow)
|
|
|
|
+
|
|
|
|
+ If window.IsKeyDown (GLFW_KEY_ESCAPE)
|
|
|
|
+ window.SetShouldClose (True)
|
|
|
|
+ EndIf
|
|
|
|
+
|
|
|
|
+EndFunction
|
|
|
|
+
|
|
|
|
+' glfw: initialize and configure
|
|
|
|
+TGLFWWindow.Hint (GLFW_CONTEXT_VERSION_MAJOR, 3)
|
|
|
|
+TGLFWWindow.Hint (GLFW_CONTEXT_VERSION_MINOR, 3)
|
|
|
|
+TGLFWWindow.Hint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)
|
|
|
|
+
|
|
|
|
+?MacOS ' Ewww...
|
|
|
|
+ TGLFWWindow.Hint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE)
|
|
|
|
+?
|
|
|
|
+
|
|
|
|
+' glfw window creation
|
|
|
|
+Local window:TGLFWWindow = New TGameWindow.Create (SCR_WIDTH, SCR_HEIGHT, app_name)
|
|
|
|
+
|
|
|
|
+If Not window
|
|
|
|
+ Print "Failed to create GLFW window!"
|
|
|
|
+ End
|
|
|
|
+EndIf
|
|
|
|
+
|
|
|
|
+window.MakeContextCurrent ()
|
|
|
|
+
|
|
|
|
+' glad: load all OpenGL function pointers
|
|
|
|
+gladLoadGL (glfwGetProcAddress)
|
|
|
|
+
|
|
|
|
+Local vertexShaderSource:String
|
|
|
|
+
|
|
|
|
+vertexShaderSource :+ "#version 330 core~n"
|
|
|
|
+vertexShaderSource :+ "layout (location = 0) in vec3 aPos;~n"
|
|
|
|
+vertexShaderSource :+ "void main()~n"
|
|
|
|
+vertexShaderSource :+ "{~n"
|
|
|
|
+vertexShaderSource :+ " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);~n"
|
|
|
|
+vertexShaderSource :+ "}~n"
|
|
|
|
+
|
|
|
|
+Local fragmentShaderSource:String
|
|
|
|
+
|
|
|
|
+fragmentShaderSource :+ "#version 330 core~n"
|
|
|
|
+fragmentShaderSource :+ "out vec4 FragColor;~n"
|
|
|
|
+fragmentShaderSource :+ "void main()~n"
|
|
|
|
+fragmentShaderSource :+ "{~n"
|
|
|
|
+fragmentShaderSource :+ " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);~n"
|
|
|
|
+fragmentShaderSource :+ "}~n"
|
|
|
|
+
|
|
|
|
+' build and compile our shader program
|
|
|
|
+' ------------------------------------
|
|
|
|
+
|
|
|
|
+' vertex shader
|
|
|
|
+Local vertexShader:Int = glCreateShader (GL_VERTEX_SHADER)
|
|
|
|
+
|
|
|
|
+glShaderSource (vertexShader, 1, vertexShaderSource)
|
|
|
|
+glCompileShader (vertexShader)
|
|
|
|
+
|
|
|
|
+Local success:Int
|
|
|
|
+Local infoLog:Byte [512]
|
|
|
|
+
|
|
|
|
+' check for shader compile errors
|
|
|
|
+glGetShaderiv (vertexShader, GL_COMPILE_STATUS, Varptr success)
|
|
|
|
+
|
|
|
|
+If Not success
|
|
|
|
+ glGetShaderInfoLog (vertexShader, 512, Null, infoLog)
|
|
|
|
+ Print "Vertex shader compilation failed: " + String.FromCString (infoLog)
|
|
|
|
+EndIf
|
|
|
|
+
|
|
|
|
+' fragment shader
|
|
|
|
+Local fragmentShader:Int = glCreateShader (GL_FRAGMENT_SHADER)
|
|
|
|
+
|
|
|
|
+glShaderSource (fragmentShader, 1, fragmentShaderSource)
|
|
|
|
+glCompileShader (fragmentShader)
|
|
|
|
+
|
|
|
|
+' check for shader compile errors
|
|
|
|
+glGetShaderiv (fragmentShader, GL_COMPILE_STATUS, Varptr success)
|
|
|
|
+
|
|
|
|
+If Not success
|
|
|
|
+ glGetShaderInfoLog (fragmentShader, 512, Null, infoLog)
|
|
|
|
+ Print "Fragment shader compilation failed: " + String.FromCString (infoLog)
|
|
|
|
+EndIf
|
|
|
|
+
|
|
|
|
+' link shaders
|
|
|
|
+Local shaderProgram:Int = glCreateProgram ()
|
|
|
|
+
|
|
|
|
+glAttachShader (shaderProgram, vertexShader)
|
|
|
|
+glAttachShader (shaderProgram, fragmentShader)
|
|
|
|
+glLinkProgram (shaderProgram)
|
|
|
|
+
|
|
|
|
+glGetProgramiv (shaderProgram, GL_LINK_STATUS, Varptr success)
|
|
|
|
+
|
|
|
|
+If Not success
|
|
|
|
+ glGetProgramInfoLog (shaderProgram, 512, Null, infoLog)
|
|
|
|
+ Print "Shader program linking failed: " + String.FromCString (infoLog)
|
|
|
|
+EndIf
|
|
|
|
+
|
|
|
|
+glDeleteShader (vertexShader)
|
|
|
|
+glDeleteShader (fragmentShader)
|
|
|
|
+
|
|
|
|
+' set up vertex data (and buffer(s)) and configure vertex attributes
|
|
|
|
+Local vertices:Float [] = [..
|
|
|
|
+ 0.5, 0.5, 0.0, ..
|
|
|
|
+ 0.5, -0.5, 0.0, ..
|
|
|
|
+ -0.5, -0.5, 0.0, ..
|
|
|
|
+ -0.5, 0.5, 0.0]
|
|
|
|
+
|
|
|
|
+Local indices:UInt [] = [..
|
|
|
|
+ 0, 1, 3, ..
|
|
|
|
+ 1, 2, 3]
|
|
|
|
+
|
|
|
|
+Local VBO:UInt
|
|
|
|
+Local VAO:UInt
|
|
|
|
+Local EBO:UInt
|
|
|
|
+
|
|
|
|
+glGenVertexArrays (1, Varptr VAO)
|
|
|
|
+glGenBuffers (1, Varptr VBO)
|
|
|
|
+glGenBuffers (1, Varptr EBO)
|
|
|
|
+
|
|
|
|
+' bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
|
|
|
|
+glBindVertexArray (VAO)
|
|
|
|
+
|
|
|
|
+glBindBuffer (GL_ARRAY_BUFFER, VBO)
|
|
|
|
+glBufferData (GL_ARRAY_BUFFER, vertices.length * SizeOf (0:Float), vertices, GL_STATIC_DRAW)
|
|
|
|
+
|
|
|
|
+glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, EBO)
|
|
|
|
+glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.length * SizeOf (0:Float), indices, GL_STATIC_DRAW)
|
|
|
|
+
|
|
|
|
+glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 3 * SizeOf (0:Float), 0:Byte Ptr)
|
|
|
|
+glEnableVertexAttribArray (0)
|
|
|
|
+
|
|
|
|
+' note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
|
|
|
|
+glBindBuffer (GL_ARRAY_BUFFER, 0)
|
|
|
|
+
|
|
|
|
+' You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
|
|
|
|
+' VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
|
|
|
|
+glBindVertexArray (0)
|
|
|
|
+
|
|
|
|
+' render loop
|
|
|
|
+' -----------
|
|
|
|
+While Not window.ShouldClose ()
|
|
|
|
+
|
|
|
|
+ ' input
|
|
|
|
+ ' -----
|
|
|
|
+ ProcessInput (window)
|
|
|
|
+
|
|
|
|
+ ' render
|
|
|
|
+ ' ------
|
|
|
|
+ glClearColor (0.2, 0.3, 0.3, 1.0)
|
|
|
|
+ glClear (GL_COLOR_BUFFER_BIT)
|
|
|
|
+
|
|
|
|
+ ' draw our first triangle
|
|
|
|
+ glUseProgram (shaderProgram)
|
|
|
|
+ glBindVertexArray (VAO) ' seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
|
|
|
|
+ glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
|
|
|
|
+
|
|
|
|
+ ' swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
|
|
|
+ window.SwapBuffers ()
|
|
|
|
+ PollSystem ()
|
|
|
|
+
|
|
|
|
+Wend
|
|
|
|
+
|
|
|
|
+' optional: de-allocate all resources once they've outlived their purpose
|
|
|
|
+glDeleteVertexArrays (1, Varptr VAO)
|
|
|
|
+glDeleteBuffers (1, Varptr VBO)
|
|
|
|
+glDeleteBuffers (1, Varptr EBO)
|
|
|
|
+
|
|
|
|
+End
|