Files
game/main.sx
2026-02-23 11:09:44 +02:00

244 lines
7.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#import "modules/std.sx";
#import "modules/sdl3.sx";
#import "modules/opengl.sx";
#import "modules/math";
stb :: #import "modules/stb.sx";
WIDTH :f32: 800;
HEIGHT :f32: 600;
main :: () {
print("init video: \n");
SDL_Init(SDL_INIT_VIDEO);
print("init opengl: \n");
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
print("init opengl profile: \n");
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
print("create window: \n");
window := SDL_CreateWindow("SX Game", xx WIDTH, xx HEIGHT, SDL_WINDOW_OPENGL);
gl_ctx := SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_ctx);
SDL_GL_SetSwapInterval(1);
print("load gl: \n");
load_gl(SDL_GL_GetProcAddress);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
program := create_program(VERT_SHADER_SRC, FRAG_SHADER_SRC);
glUseProgram(program);
print("uniform locations: \n");
mvp_loc := glGetUniformLocation(program, "uMVP");
light_loc := glGetUniformLocation(program, "uLightDir");
wire_loc := glGetUniformLocation(program, "uWire");
print("vertices\n");
// Cube vertices: pos(vec4 w=1) + normal(vec4 w=0), 36 vertices × 2 vec4s = 72
vertices : []Vector(4, f32) = .[
// Front face (z = +0.5)
.[-0.5, -0.5, 0.5, 1.0], .[ 0.0, 0.0, 1.0, 0.0],
.[ 0.5, -0.5, 0.5, 1.0], .[ 0.0, 0.0, 1.0, 0.0],
.[ 0.5, 0.5, 0.5, 1.0], .[ 0.0, 0.0, 1.0, 0.0],
.[-0.5, -0.5, 0.5, 1.0], .[ 0.0, 0.0, 1.0, 0.0],
.[ 0.5, 0.5, 0.5, 1.0], .[ 0.0, 0.0, 1.0, 0.0],
.[-0.5, 0.5, 0.5, 1.0], .[ 0.0, 0.0, 1.0, 0.0],
// Back face (z = -0.5)
.[ 0.5, -0.5, -0.5, 1.0], .[ 0.0, 0.0, -1.0, 0.0],
.[-0.5, -0.5, -0.5, 1.0], .[ 0.0, 0.0, -1.0, 0.0],
.[-0.5, 0.5, -0.5, 1.0], .[ 0.0, 0.0, -1.0, 0.0],
.[ 0.5, -0.5, -0.5, 1.0], .[ 0.0, 0.0, -1.0, 0.0],
.[-0.5, 0.5, -0.5, 1.0], .[ 0.0, 0.0, -1.0, 0.0],
.[ 0.5, 0.5, -0.5, 1.0], .[ 0.0, 0.0, -1.0, 0.0],
// Top face (y = +0.5)
.[-0.5, 0.5, 0.5, 1.0], .[ 0.0, 1.0, 0.0, 0.0],
.[ 0.5, 0.5, 0.5, 1.0], .[ 0.0, 1.0, 0.0, 0.0],
.[ 0.5, 0.5, -0.5, 1.0], .[ 0.0, 1.0, 0.0, 0.0],
.[-0.5, 0.5, 0.5, 1.0], .[ 0.0, 1.0, 0.0, 0.0],
.[ 0.5, 0.5, -0.5, 1.0], .[ 0.0, 1.0, 0.0, 0.0],
.[-0.5, 0.5, -0.5, 1.0], .[ 0.0, 1.0, 0.0, 0.0],
// Bottom face (y = -0.5)
.[-0.5, -0.5, -0.5, 1.0], .[0.0, -1.0, 0.0, 0.0],
.[ 0.5, -0.5, -0.5, 1.0], .[0.0, -1.0, 0.0, 0.0],
.[ 0.5, -0.5, 0.5, 1.0], .[0.0, -1.0, 0.0, 0.0],
.[-0.5, -0.5, -0.5, 1.0], .[0.0, -1.0, 0.0, 0.0],
.[ 0.5, -0.5, 0.5, 1.0], .[0.0, -1.0, 0.0, 0.0],
.[-0.5, -0.5, 0.5, 1.0], .[0.0, -1.0, 0.0, 0.0],
// Right face (x = +0.5)
.[ 0.5, -0.5, 0.5, 1.0], .[1.0, 0.0, 0.0, 0.0],
.[ 0.5, -0.5, -0.5, 1.0], .[1.0, 0.0, 0.0, 0.0],
.[ 0.5, 0.5, -0.5, 1.0], .[1.0, 0.0, 0.0, 0.0],
.[ 0.5, -0.5, 0.5, 1.0], .[1.0, 0.0, 0.0, 0.0],
.[ 0.5, 0.5, -0.5, 1.0], .[1.0, 0.0, 0.0, 0.0],
.[ 0.5, 0.5, 0.5, 1.0], .[1.0, 0.0, 0.0, 0.0],
// Left face (x = -0.5)
.[-0.5, -0.5, -0.5, 1.0], .[-1.0, 0.0, 0.0, 0.0],
.[-0.5, -0.5, 0.5, 1.0], .[-1.0, 0.0, 0.0, 0.0],
.[-0.5, 0.5, 0.5, 1.0], .[-1.0, 0.0, 0.0, 0.0],
.[-0.5, -0.5, -0.5, 1.0], .[-1.0, 0.0, 0.0, 0.0],
.[-0.5, 0.5, 0.5, 1.0], .[-1.0, 0.0, 0.0, 0.0],
.[-0.5, 0.5, -0.5, 1.0], .[-1.0, 0.0, 0.0, 0.0]
];
print("cube buffer: \n");
vao : u32 = 0;
vbo : u32 = 0;
glGenVertexArrays(1, @vao);
glGenBuffers(1, @vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 1152, xx vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, 0, 32, xx 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, 0, 32, xx 16);
glEnableVertexAttribArray(1);
glUniform3f(light_loc, 0.5, 0.7, 1.0);
glUniform1f(wire_loc, 0.0);
running := true;
event : SDL_Event = .none;
print("loop: \n");
while running {
while SDL_PollEvent(event) {
if event == {
case .quit: running = false;
case .key_up: (e) {
if e.key == {
case .escape: running = false;
}
}
}
}
ticks := SDL_GetTicks();
ms : f32 = xx ticks;
angle := ms * 0.001;
proj := mat4_perspective(PI/ 4.0, WIDTH / HEIGHT, 0.1, 100.0);
view := mat4_translate(0.0, 0.0, -3.0);
rot_y := mat4_rotate_y(angle);
rot_x := mat4_rotate_x(angle * 0.7);
model := mat4_multiply(rot_y, rot_x);
vm := mat4_multiply(view, model);
mvp := mat4_multiply(proj, vm);
glUniformMatrix4fv(mvp_loc, 1, 0, mvp.data);
glClearColor(0.1, 0.1, 0.15, 1.0);
glClear(GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT);
glUniform1f(wire_loc, 0.0);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 36);
glDepthFunc(GL_LEQUAL);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(2.0);
glUniform1f(wire_loc, 1.0);
glDrawArrays(GL_TRIANGLES, 0, 36);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDepthFunc(GL_LESS);
glUniform1f(wire_loc, 0.0);
print("{}\n", ms);
SDL_GL_SwapWindow(window);
}
SDL_GL_DestroyContext(gl_ctx);
SDL_DestroyWindow(window);
SDL_Quit();
}
create_program :: (vert_src: [:0]u8, frag_src: [:0]u8) -> u32 {
vs := compile_shader(GL_VERTEX_SHADER, vert_src);
fs := compile_shader(GL_FRAGMENT_SHADER, frag_src);
prog := glCreateProgram();
glAttachShader(prog, vs);
glAttachShader(prog, fs);
glLinkProgram(prog);
status : s32 = 0;
glGetProgramiv(prog, GL_LINK_STATUS, @status);
if status == GL_FALSE {
log_buf: [512]u8 = ---;
glGetProgramInfoLog(prog, 512, null, log_buf);
print("error program link\n");
}
glDeleteShader(vs);
glDeleteShader(fs);
return prog;
}
compile_shader :: (shader_type : u32, source: [:0]u8) -> u32 {
shader := glCreateShader(shader_type);
glShaderSource(shader, 1, source, null);
glCompileShader(shader);
status : s32 = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, @status);
if status == GL_FALSE {
log_buf : [512]u8 = ---;
glGetShaderInfoLog(shader, 512, null, log_buf);
print("error compile shader\n");
}
return shader;
}
VERT_SHADER_SRC : [:0]u8 = #string GLSL
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
uniform mat4 uMVP;
out vec3 vNormal;
out vec3 vPos;
void main() {
gl_Position = uMVP * vec4(aPos, 1.0);
vNormal = aNormal;
vPos = aPos;
}
GLSL;
FRAG_SHADER_SRC : [:0]u8 = #string GLSL
#version 330 core
in vec3 vNormal;
in vec3 vPos;
out vec4 FragColor;
uniform vec3 uLightDir;
uniform float uWire;
void main() {
if (uWire > 0.5) {
FragColor = vec4(0.05, 0.05, 0.05, 1.0);
return;
}
vec3 n = normalize(vNormal);
vec3 l = normalize(uLightDir);
float diff = max(dot(n, l), 0.15);
float cx = floor(vPos.x * 2.0 + 0.001);
float cy = floor(vPos.y * 2.0 + 0.001);
float cz = floor(vPos.z * 2.0 + 0.001);
float check = mod(cx + cy + cz, 2.0);
vec3 col1 = vec3(0.9, 0.5, 0.2);
vec3 col2 = vec3(0.2, 0.6, 0.9);
vec3 base = mix(col1, col2, check);
FragColor = vec4(base * diff, 1.0);
}
GLSL;