mirror of
https://github.com/Nexoniarz/Finch.git
synced 2026-11-03 00:44:27 +00:00
- examples/opengl.fch: OpenGL 3.3 core, shaders, VAO/VBO, a spinning triangle (checked offscreen) - examples/vulkan.fch: instance, GPUs with properties/memory/queues, logical device and queue - ptr(n) and int(p) conversions for C APIs that pass offsets as pointers - .ptr works on string literals; a comma after the last call argument is allowed - a missing header included by an imported header is now named in the error - the old .fn extension hint is gone (Finch is new, there are no old files) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
105 lines
3.3 KiB
Text
105 lines
3.3 KiB
Text
// Modern OpenGL (3.3 core): a spinning, colorful triangle drawn with shaders.
|
|
// Shows structs of numbers going to the GPU, C out-parameters with addr(), and
|
|
// pointers made from numbers with ptr(...). Needs GLFW and OpenGL (in shell.nix).
|
|
import "opengl.h"
|
|
link "glfw"
|
|
link "GL"
|
|
|
|
fn compileShader(u32 kind, str source) -> u32 {
|
|
shader := glCreateShader(kind)
|
|
src := source.ptr
|
|
glShaderSource(shader, 1, addr(src), null)
|
|
glCompileShader(shader)
|
|
i32 ok
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, addr(ok))
|
|
if ok == 0 {
|
|
log := " ".repeat(1024)
|
|
glGetShaderInfoLog(shader, 1024, null, log)
|
|
print("shader error:", str(log.ptr))
|
|
exit(1)
|
|
}
|
|
return shader
|
|
}
|
|
|
|
fn makeProgram() -> u32 {
|
|
vertex := "#version 330 core\n" +
|
|
"layout(location = 0) in vec2 pos;\n" +
|
|
"layout(location = 1) in vec3 color;\n" +
|
|
"uniform float time;\n" +
|
|
"out vec3 vColor;\n" +
|
|
"void main() {\n" +
|
|
" float c = cos(time), s = sin(time);\n" +
|
|
" gl_Position = vec4(c * pos.x - s * pos.y, s * pos.x + c * pos.y, 0.0, 1.0);\n" +
|
|
" vColor = color;\n" +
|
|
"}\n"
|
|
fragment := "#version 330 core\n" +
|
|
"in vec3 vColor;\n" +
|
|
"out vec4 outColor;\n" +
|
|
"void main() { outColor = vec4(vColor, 1.0); }\n"
|
|
|
|
vs := compileShader(GL_VERTEX_SHADER, vertex)
|
|
fs := compileShader(GL_FRAGMENT_SHADER, fragment)
|
|
program := glCreateProgram()
|
|
glAttachShader(program, vs)
|
|
glAttachShader(program, fs)
|
|
glLinkProgram(program)
|
|
glDeleteShader(vs)
|
|
glDeleteShader(fs)
|
|
return program
|
|
}
|
|
|
|
fn main() {
|
|
if glfwInit() == 0 {
|
|
print("could not start GLFW")
|
|
return
|
|
}
|
|
defer glfwTerminate()
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)
|
|
|
|
window := glfwCreateWindow(800, 600, "Finch + OpenGL", null, null)
|
|
if window == null {
|
|
print("could not open a window (does your GPU support OpenGL 3.3?)")
|
|
return
|
|
}
|
|
glfwMakeContextCurrent(window)
|
|
glfwSwapInterval(1)
|
|
print("OpenGL", str(glGetString(GL_VERSION)), "on", str(glGetString(GL_RENDERER)))
|
|
|
|
// x, y, r, g, b for each corner
|
|
[]f32 vertices = [
|
|
0.0, 0.6, 1.0, 0.48, 0.1,
|
|
-0.6, -0.4, 0.2, 0.6, 1.0,
|
|
0.6, -0.4, 0.6, 1.0, 0.4,
|
|
]
|
|
u32 vao
|
|
u32 vbo
|
|
glGenVertexArrays(1, addr(vao))
|
|
glGenBuffers(1, addr(vbo))
|
|
glBindVertexArray(vao)
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo)
|
|
glBufferData(GL_ARRAY_BUFFER, vertices.len * 4, vertices.ptr, GL_STATIC_DRAW)
|
|
i32 stride = 5 * 4
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, ptr(0))
|
|
glEnableVertexAttribArray(0)
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, ptr(2 * 4))
|
|
glEnableVertexAttribArray(1)
|
|
|
|
program := makeProgram()
|
|
timeLoc := glGetUniformLocation(program, "time")
|
|
|
|
while glfwWindowShouldClose(window) == 0 {
|
|
glClearColor(0.106, 0.122, 0.165, 1.0)
|
|
glClear(GL_COLOR_BUFFER_BIT)
|
|
glUseProgram(program)
|
|
glUniform1f(timeLoc, f32(glfwGetTime()))
|
|
glDrawArrays(GL_TRIANGLES, 0, 3)
|
|
glfwSwapBuffers(window)
|
|
glfwPollEvents()
|
|
}
|
|
|
|
glDeleteBuffers(1, addr(vbo))
|
|
glDeleteVertexArrays(1, addr(vao))
|
|
glDeleteProgram(program)
|
|
}
|