...
This commit is contained in:
@@ -131,49 +131,8 @@ main :: () {
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
// Shaders
|
print("create program: {}\n{}\n", VERT_SHADER_SRC, FRAG_SHADER_SRC);
|
||||||
vert_src : [:0]u8 = #string glsl
|
program := create_program(VERT_SHADER_SRC, FRAG_SHADER_SRC);
|
||||||
#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_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;
|
|
||||||
|
|
||||||
program := create_program(vert_src, frag_src);
|
|
||||||
glUseProgram(program);
|
glUseProgram(program);
|
||||||
|
|
||||||
mvp_loc : s32 = glGetUniformLocation(program, "uMVP");
|
mvp_loc : s32 = glGetUniformLocation(program, "uMVP");
|
||||||
@@ -317,3 +276,44 @@ GLSL;
|
|||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VERT_SHADER_SRC : string = #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 : string = #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;
|
||||||
@@ -2349,10 +2349,47 @@ pub const CodeGen = struct {
|
|||||||
.bool_literal => |lit| {
|
.bool_literal => |lit| {
|
||||||
return c.LLVMConstInt(llvm_ty, if (lit.value) 1 else 0, 0);
|
return c.LLVMConstInt(llvm_ty, if (lit.value) 1 else 0, 0);
|
||||||
},
|
},
|
||||||
|
.string_literal => |sl| {
|
||||||
|
const content = if (sl.is_raw) sl.raw else (unescape.unescapeString(self.allocator, sl.raw) catch return null);
|
||||||
|
return self.buildConstStrGlobal(content);
|
||||||
|
},
|
||||||
|
.struct_literal => |sl| {
|
||||||
|
return self.evalConstantStruct(sl, target_ty);
|
||||||
|
},
|
||||||
else => return null,
|
else => return null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a struct literal as a constant (for global initializers).
|
||||||
|
fn evalConstantStruct(self: *CodeGen, sl: ast.StructLiteral, target_ty: Type) ?c.LLVMValueRef {
|
||||||
|
const struct_name = sl.struct_name orelse target_ty.struct_type;
|
||||||
|
const info = self.lookupStructInfo(struct_name) orelse return null;
|
||||||
|
|
||||||
|
if (info.field_names.len > 32) return null;
|
||||||
|
var field_vals: [32]c.LLVMValueRef = undefined;
|
||||||
|
const n = info.field_names.len;
|
||||||
|
|
||||||
|
// Initialize with undef for each field
|
||||||
|
for (0..n) |i| {
|
||||||
|
field_vals[i] = c.LLVMGetUndef(self.typeToLLVM(info.field_types[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in provided field values
|
||||||
|
for (sl.field_inits) |fi| {
|
||||||
|
const field_name = fi.name orelse continue; // skip positional for now
|
||||||
|
const idx = blk: {
|
||||||
|
for (info.field_names, 0..) |fn_name, j| {
|
||||||
|
if (std.mem.eql(u8, fn_name, field_name)) break :blk j;
|
||||||
|
}
|
||||||
|
return null; // unknown field
|
||||||
|
};
|
||||||
|
const val = self.evalConstant(fi.value, info.field_types[idx]) orelse return null;
|
||||||
|
field_vals[idx] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.LLVMConstNamedStruct(info.llvm_type, @ptrCast(&field_vals), @intCast(n));
|
||||||
|
}
|
||||||
|
|
||||||
/// Register a top-level value constant (e.g., `SPECIAL_VALUE :u8: 42;`) as an LLVM global.
|
/// Register a top-level value constant (e.g., `SPECIAL_VALUE :u8: 42;`) as an LLVM global.
|
||||||
fn registerTopLevelConstant(self: *CodeGen, cd: ast.ConstDecl) !void {
|
fn registerTopLevelConstant(self: *CodeGen, cd: ast.ConstDecl) !void {
|
||||||
const ta = cd.type_annotation orelse return; // need explicit type for top-level constants
|
const ta = cd.type_annotation orelse return; // need explicit type for top-level constants
|
||||||
@@ -2382,9 +2419,24 @@ pub const CodeGen = struct {
|
|||||||
const llvm_ty = self.typeToLLVM(sx_ty);
|
const llvm_ty = self.typeToLLVM(sx_ty);
|
||||||
const name_z = try self.allocator.dupeZ(u8, vd.name);
|
const name_z = try self.allocator.dupeZ(u8, vd.name);
|
||||||
const global = c.LLVMAddGlobal(self.module, llvm_ty, name_z.ptr);
|
const global = c.LLVMAddGlobal(self.module, llvm_ty, name_z.ptr);
|
||||||
// Initialize with undef (will be set at runtime, e.g. by load_gl)
|
|
||||||
|
// Try constant-evaluable initializer → register as comptime_global for JIT compatibility
|
||||||
|
if (vd.value) |val_node| {
|
||||||
|
if (self.evalConstant(val_node, sx_ty)) |const_val| {
|
||||||
|
c.LLVMSetInitializer(global, const_val);
|
||||||
|
c.LLVMSetGlobalConstant(global, 1);
|
||||||
|
try self.comptime_globals.put(vd.name, .{
|
||||||
|
.global = global,
|
||||||
|
.ty = sx_ty,
|
||||||
|
.expr = val_node,
|
||||||
|
.is_resolved = true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-constant globals: mutable, initialized with undef (set at runtime, e.g. by load_gl)
|
||||||
c.LLVMSetInitializer(global, self.getUndef(llvm_ty));
|
c.LLVMSetInitializer(global, self.getUndef(llvm_ty));
|
||||||
// NOT constant — this is a mutable global
|
|
||||||
c.LLVMSetGlobalConstant(global, 0);
|
c.LLVMSetGlobalConstant(global, 0);
|
||||||
|
|
||||||
try self.global_mutable_vars.put(vd.name, .{ .ptr = global, .ty = sx_ty });
|
try self.global_mutable_vars.put(vd.name, .{ .ptr = global, .ty = sx_ty });
|
||||||
|
|||||||
Reference in New Issue
Block a user