208 lines
7.3 KiB
Zig
208 lines
7.3 KiB
Zig
const Self = @This();
|
|
|
|
const rl = @import("raylib");
|
|
const gl = @import("opengl");
|
|
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
const ShaderCode = @import("./shader-code.zig");
|
|
const Light = @import("./light.zig");
|
|
const assert = std.debug.assert;
|
|
|
|
const max_lights = 1;
|
|
|
|
const SHADER_LOC_VECTOR_VIEW = @intFromEnum(rl.ShaderLocationIndex.SHADER_LOC_VECTOR_VIEW);
|
|
|
|
shader: rl.Shader,
|
|
bloom_shader: rl.Shader,
|
|
frame_buffer: rl.RenderTexture2D,
|
|
bloom_texture: rl.Texture2D,
|
|
camera: rl.Camera3D,
|
|
lights: [max_lights]Light,
|
|
|
|
rect: OpenglRect,
|
|
cube: rl.Model,
|
|
|
|
|
|
const OpenglRect = struct {
|
|
vbo: u32,
|
|
vao: u32,
|
|
|
|
fn init() OpenglRect {
|
|
var rect: OpenglRect = undefined;
|
|
|
|
const vertices = [_]f32{
|
|
// Coords // texCoords
|
|
1.0, -1.0, 1.0, 0.0,
|
|
-1.0, 1.0, 0.0, 1.0,
|
|
-1.0, -1.0, 0.0, 0.0,
|
|
|
|
1.0, 1.0, 1.0, 1.0,
|
|
-1.0, 1.0, 0.0, 1.0,
|
|
1.0, -1.0, 1.0, 0.0,
|
|
};
|
|
|
|
gl.genVertexArrays(1, &rect.vao);
|
|
gl.genBuffers(1, &rect.vbo);
|
|
gl.bindVertexArray(rect.vao);
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, rect.vbo);
|
|
gl.bufferData(gl.ARRAY_BUFFER, vertices.len * @sizeOf(f32), @ptrCast(&vertices), gl.STATIC_DRAW);
|
|
gl.enableVertexAttribArray(0);
|
|
gl.vertexAttribPointer(0, 2, gl.FLOAT, gl.FALSE, 4 * @sizeOf(f32), @ptrFromInt(0));
|
|
gl.enableVertexAttribArray(1);
|
|
gl.vertexAttribPointer(1, 2, gl.FLOAT, gl.FALSE, 4 * @sizeOf(f32), @ptrFromInt(2 * @sizeOf(f32)));
|
|
|
|
return rect;
|
|
}
|
|
|
|
fn draw(self: OpenglRect) void {
|
|
gl.bindVertexArray(self.vao);
|
|
gl.disable(gl.DEPTH_TEST);
|
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
}
|
|
};
|
|
|
|
fn loadEmptyTexture(width: i32, height: i32, format: rl.PixelFormat) rl.Texture2D {
|
|
var target: rl.Texture2D = undefined;
|
|
target.id = rl.rlLoadTexture(null, width, height, format, 1);
|
|
target.width = width;
|
|
target.height = height;
|
|
target.format = format;
|
|
target.mipmaps = 1;
|
|
return target;
|
|
}
|
|
|
|
pub fn init(allocator: Allocator) !Self {
|
|
const main_shader_code = try ShaderCode.init(allocator, max_lights);
|
|
defer main_shader_code.deinit();
|
|
const shader = rl.LoadShaderFromMemory(main_shader_code.vertex, main_shader_code.fragment);
|
|
errdefer rl.UnloadShader(shader);
|
|
|
|
if (shader.id == rl.rlGetShaderIdDefault()) {
|
|
return error.CompileShader;
|
|
}
|
|
|
|
const bloom_shader = rl.LoadShaderFromMemory(@embedFile("shaders/bloom_vs.glsl"), @embedFile("shaders/bloom_fs.glsl"));
|
|
errdefer rl.UnloadShader(bloom_shader);
|
|
if (bloom_shader.id == rl.rlGetShaderIdDefault()) {
|
|
return error.CompileShader;
|
|
}
|
|
|
|
const screen_width = rl.GetScreenWidth();
|
|
const screen_height = rl.GetScreenHeight();
|
|
const frame_buffer = rl.LoadRenderTexture(screen_width, screen_height);
|
|
errdefer rl.UnloadRenderTexture(frame_buffer);
|
|
|
|
var bloom_texture = loadEmptyTexture(screen_width, screen_height, .PIXELFORMAT_UNCOMPRESSED_R8G8B8);
|
|
rl.rlFramebufferAttach(frame_buffer.id, bloom_texture.id, .RL_ATTACHMENT_COLOR_CHANNEL1, .RL_ATTACHMENT_TEXTURE2D, 0);
|
|
if (rl.rlFramebufferComplete(frame_buffer.id)) std.debug.print("INFO: Successfully attached bloom texture", .{});
|
|
|
|
rl.rlActiveDrawBuffers(2);
|
|
|
|
var lights: [max_lights]Light = undefined;
|
|
for (0..max_lights) |i| {
|
|
lights[i] = Light.init(shader, i);
|
|
}
|
|
Light.init(shader, 0).set_point(rl.RED, rl.Vector3{ .x = 1, .y = 1, .z = 0.5 }, 2.0);
|
|
|
|
shader.locs.?[SHADER_LOC_VECTOR_VIEW] = rl.GetShaderLocation(shader, "viewPos");
|
|
|
|
const ambientLoc = rl.GetShaderLocation(shader, "ambient");
|
|
rl.SetShaderValue(shader, ambientLoc, &[4]f32{ 0.6, 0.6, 1, 1.0 }, .SHADER_UNIFORM_VEC4);
|
|
|
|
const rect = OpenglRect.init();
|
|
|
|
return Self{
|
|
.shader = shader,
|
|
.bloom_shader = bloom_shader,
|
|
.rect = rect,
|
|
.frame_buffer = frame_buffer,
|
|
.bloom_texture = bloom_texture,
|
|
.camera = rl.Camera3D{
|
|
.position = rl.Vector3.new(0, 0, -10),
|
|
.target = rl.Vector3.new(0.0, 0.0, 0.0),
|
|
.up = rl.Vector3.new(0.0, 1.0, 0.0),
|
|
.fovy = 45.0,
|
|
.projection = rl.CameraProjection.CAMERA_PERSPECTIVE,
|
|
},
|
|
.lights = lights,
|
|
.cube = rl.LoadModelFromMesh(rl.GenMeshCube(1.0, 1.0, 1.0))
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: Self) void {
|
|
rl.UnloadShader(self.shader);
|
|
rl.UnloadRenderTexture(self.frame_buffer);
|
|
}
|
|
|
|
pub fn update(self: *Self, dt: f32) void {
|
|
const screen_width = rl.GetScreenWidth();
|
|
const screen_height = rl.GetScreenHeight();
|
|
if (self.frame_buffer.texture.width != screen_width or self.frame_buffer.texture.height != screen_height) {
|
|
rl.UnloadRenderTexture(self.frame_buffer);
|
|
rl.UnloadTexture(self.bloom_texture);
|
|
self.frame_buffer = rl.LoadRenderTexture(screen_width, screen_height);
|
|
|
|
self.bloom_texture = loadEmptyTexture(screen_width, screen_height, .PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
|
|
rl.rlFramebufferAttach(self.frame_buffer.id, self.bloom_texture.id, .RL_ATTACHMENT_COLOR_CHANNEL1, .RL_ATTACHMENT_TEXTURE2D, 0);
|
|
if (rl.rlFramebufferComplete(self.frame_buffer.id)) std.debug.print("INFO: Successfully attached bloom texture", .{});
|
|
}
|
|
|
|
rl.UpdateCamera(&self.camera, .CAMERA_THIRD_PERSON);
|
|
|
|
const cameraPos = [3]f32{ self.camera.position.x, self.camera.position.y, self.camera.position.z };
|
|
rl.SetShaderValue(self.shader, self.shader.locs.?[SHADER_LOC_VECTOR_VIEW], @ptrCast(&cameraPos), .SHADER_UNIFORM_VEC3);
|
|
_ = dt;
|
|
}
|
|
|
|
pub fn draw(self: *Self) void {
|
|
|
|
rl.BeginTextureMode(self.frame_buffer);
|
|
{
|
|
rl.rlActiveDrawBuffers(2);
|
|
|
|
const bg_color = [_]f32{ 33.0 / 255.0, 33.0 / 255.0, 33.0 / 255.0, 1.0 };
|
|
gl.clearBufferfv(gl.COLOR, 0, &bg_color);
|
|
|
|
const transparent_color = [_]f32{ 0.0, 0.0, 0.0, 0.0 };
|
|
gl.clearBufferfv(gl.COLOR, 1, &transparent_color);
|
|
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
|
|
rl.BeginMode3D(self.camera);
|
|
rl.BeginShaderMode(self.shader);
|
|
|
|
self.cube.materials.?[0].shader = self.shader;
|
|
rl.DrawModel(self.cube, rl.Vector3Zero(), 1.0, rl.WHITE);
|
|
|
|
rl.EndShaderMode();
|
|
rl.EndMode3D();
|
|
}
|
|
rl.EndTextureMode();
|
|
|
|
const screen_width = rl.GetScreenWidth();
|
|
const screen_height = rl.GetScreenHeight();
|
|
// const screen_rect = rl.Rectangle{ .x = 0, .y = 0, .width = @floatFromInt(screen_width), .height = @floatFromInt(screen_height) };
|
|
|
|
rl.BeginDrawing();
|
|
|
|
gl.useProgram(self.bloom_shader.id);
|
|
|
|
rl.rlDisableDepthTest();
|
|
|
|
const renderSize = [_]f32{ @floatFromInt(screen_width), @floatFromInt(screen_height) };
|
|
rl.rlSetUniform(rl.rlGetLocationUniform(self.bloom_shader.id, "renderSize"), &renderSize, @intFromEnum(rl.ShaderUniformDataType.SHADER_UNIFORM_VEC2), 1);
|
|
rl.rlSetUniformSampler(rl.rlGetLocationUniform(self.bloom_shader.id, "screenTexture"), self.frame_buffer.texture.id);
|
|
rl.rlSetUniformSampler(rl.rlGetLocationUniform(self.bloom_shader.id, "bloomTexture"), self.bloom_texture.id);
|
|
|
|
gl.bindVertexArray(self.rect.vao);
|
|
|
|
rl.rlActiveTextureSlot(1);
|
|
rl.rlEnableTexture(self.frame_buffer.texture.id);
|
|
|
|
rl.rlActiveTextureSlot(2);
|
|
rl.rlEnableTexture(self.bloom_texture.id);
|
|
|
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
|
|
rl.EndDrawing();
|
|
}
|