From f9ad6fa902c1167d7622ee7af2617d14b62bee21 Mon Sep 17 00:00:00 2001
From: pryazha <pryadeiniv@mail.ru>
Date: Wed, 19 Feb 2025 22:26:48 +0500
Subject: quite a lot of changes that I, of course, are not going to describe;)

---
 .../10.antialiasing/anti_aliasing_offscreen.c      | 453 +++++++++------------
 1 file changed, 189 insertions(+), 264 deletions(-)

(limited to 'advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c')

diff --git a/advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c b/advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c
index 5c6debb..31f3cae 100644
--- a/advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c
+++ b/advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c
@@ -2,275 +2,200 @@
 #include "GLFW/glfw3.h"
 
 #include "pwyazh.h"
-
 #include "pwyazh_GL.h"
 
 #include "common.h"
 
-#include <unistd.h>
+int main(void)
+{
+	GLFWwindow *window;
+	Arena *arena = 0;
+	Mesh *cube;
+	F32 target_fps, target_spf, last_time;
+	MAT4 proj, view, model;
+	U32 fbo, intermediate_fbo, color_tex,
+	    screen_texture, rbo,
+	    quad_vao, vbo, color_shader,
+	    screen_shader;
+	S32 width, height;
+	State state;
+	Input input;
 
-#define WIDTH 1024
-#define HEIGHT 768
-static Input global_input;
+	if (glfwInit() == GLFW_FALSE) {
+		fprintf(stderr, "[ERROR] Failed to initialize glfw.\n");
+		return(1);
+	}
 
-void
-key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
-{
-    switch (action)
-    {
-        case GLFW_PRESS: {
-            switch (key)
-            {
-                case GLFW_KEY_D: {
-                    global_input.move_right.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_W: {
-                    global_input.move_forward.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_A: {
-                    global_input.move_left.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_S: {
-                    global_input.move_backward.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_E: {
-                    global_input.move_up.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_Q: {
-                    global_input.move_down.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_SPACE: {
-                    global_input.jump.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_RIGHT: {
-                    global_input.action_right.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_LEFT: {
-                    global_input.action_left.state = KeyState_PRESS;
-                } break;
-                case GLFW_KEY_ESCAPE: {
-                    global_input.exit.state = KeyState_PRESS;
-                } break;
-            }
-        } break;
-        
-        case GLFW_RELEASE: {
-            switch (key)
-            {
-                case GLFW_KEY_D: {
-                    global_input.move_right.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_W: {
-                    global_input.move_forward.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_A: {
-                    global_input.move_left.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_S: {
-                    global_input.move_backward.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_E: {
-                    global_input.move_up.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_Q: {
-                    global_input.move_down.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_SPACE: {
-                    global_input.jump.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_RIGHT: {
-                    global_input.action_right.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_LEFT: {
-                    global_input.action_left.state = KeyState_RELEASE;
-                } break;
-                case GLFW_KEY_ESCAPE: {
-                    global_input.exit.state = KeyState_RELEASE;
-                } break;
-            }
-        } break;
-    }
-}
+	width = 1024;
+	height = 768;
 
-int
-main(void)
-{
-    GLFWwindow *window;
-    Arena *arena = 0;
-    F32 target_fps, target_spf,
-    last_time, dt;
-    MAT4 projection, view, model;
-    V3F camera_pos;
-    F32 camera_speed, fovx, near, far;
-    U32 fbo, intermediate_fbo, color_tex,
-    screen_texture, rbo,
-    quad_vao, vbo,
-    color_shader, screen_shader;
-    
-    if (glfwInit() == GLFW_FALSE)
-    {
-        fprintf(stderr, "[ERROR] Failed to initialize glfw.\n");
-        return(1);
-    }
-    
-    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-    window = glfwCreateWindow(WIDTH, HEIGHT, "Anti Aliasing (Off-screen)", 0, 0);
-    if (!window)
-    {
-        fprintf(stderr, "[ERROR] Failed to create window.\n");
-        glfwTerminate();
-        return(1);
-    }
-    
-    glfwMakeContextCurrent(window);
-    
-    glfwSetKeyCallback(window, key_callback);
-    
-    if (glewInit() != GLEW_OK)
-    {
-        fprintf(stderr, "[ERROR] Failed to initialize glew.\n");
-        glfwTerminate();
-        return(1);
-    }
-    
-    arena = arena_alloc(Megabytes(64));
-    
-    Mesh *cube_mesh = mesh_load_obj(arena, "../../data/models/cube.obj");
-    color_shader = create_shader_program("shaders/color.vs",
-                                         "shaders/color.fs");
-    screen_shader = create_shader_program("shaders/screen.vs",
-                                          "shaders/screen.fs");
-    glGenFramebuffers(1, &fbo);
-    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-    glGenTextures(1, &color_tex);
-    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color_tex);
-    glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB,
-                            WIDTH, HEIGHT, GL_TRUE);
-    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                           GL_TEXTURE_2D_MULTISAMPLE, color_tex, 0);
-    glGenRenderbuffers(1, &rbo);
-    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
-    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8,
-                                     WIDTH, HEIGHT);
-    glBindRenderbuffer(GL_RENDERBUFFER, 0);
-    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
-                              GL_RENDERBUFFER, rbo);
-    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-        fprintf(stderr, "[ERROR]: Framebuffer is not complete.\n");
-    fprintf(stdout, "[INFO]: Multisample fbo complete.\n");
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    
-    glGenFramebuffers(1, &intermediate_fbo);
-    glBindFramebuffer(GL_FRAMEBUFFER, intermediate_fbo);
-    glGenTextures(1, &screen_texture);
-    glBindTexture(GL_TEXTURE_2D, screen_texture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT,
-                 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                           GL_TEXTURE_2D, screen_texture, 0);
-    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-        fprintf(stderr, "[ERROR]: Framebuffer is not complete.\n");
-    fprintf(stdout, "[INFO]: Intermediate fbo complete.\n");
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    
-    F32 quad_vertices[] = {
-        -1.0f, -1.0f, 0.0f,  0.0f, 0.0f,
-        1.0f, -1.0f, 0.0f,  1.0f, 0.0f,
-        1.0f,  1.0f, 0.0f,  1.0f, 1.0f,
-        -1.0f, -1.0f, 0.0f,  0.0f, 0.0f,
-        1.0f,  1.0f, 0.0f,  1.0f, 1.0f,
-        -1.0f,  1.0f, 0.0f,  0.0f, 1.0f
-    };
-    
-    glGenVertexArrays(1, &quad_vao);
-    glBindVertexArray(quad_vao);
-    glGenBuffers(1, &vbo);
-    glBindBuffer(GL_ARRAY_BUFFER, vbo);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW);
-    glEnableVertexAttribArray(0);
-    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0);
-    glEnableVertexAttribArray(1);
-    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32)));
-    glBindVertexArray(0);
-    
-    target_fps = 60.0f;
-    target_spf = 1.0f/target_fps;
-    
-    camera_pos = v3f(0.0f, 0.0f, 3.0f);
-    camera_speed = 2.0f;
-    fovx = 90.0f;
-    near = 0.1f;
-    far = 1000.0f;
-    
-    last_time = glfwGetTime();
-    
-    while (!glfwWindowShouldClose(window))
-    {
-        glfwPollEvents();
-        
-        /* NOTE(pryazha): Update */
-        if (key_is_pressed(global_input.exit))
-            glfwSetWindowShouldClose(window, GLFW_TRUE);
-        
-        V3F camera_dv = get_dv_camera_orbital(&global_input, camera_pos,
-                                              v3f_zero(), dt, camera_speed);
-        camera_pos = v3f_add(camera_pos, camera_dv);
-        
-        projection = perspective(fovx, (F32)WIDTH/(F32)HEIGHT, near, far);
-        view = look_at(camera_pos, v3f_zero(), v3f(0.0f, 1.0f, 0.0f));
-        model = mat4_identity();
-        
-        input_update_last_state(&global_input);
-        
-        /* NOTE(pryazha): Render */
-        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-        glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
-        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-        glEnable(GL_DEPTH_TEST);
-        glUseProgram(color_shader);
-        shader_set_mat4fv(color_shader, "projection", projection);
-        shader_set_mat4fv(color_shader, "view", view);
-        shader_set_mat4fv(color_shader, "model", model);
-        mesh_draw(cube_mesh);
-        
-        glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
-        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediate_fbo);
-        /* TODO(pryazha): Update width and height */
-        glBlitFramebuffer(0, 0, WIDTH, HEIGHT,
-                          0, 0, WIDTH, HEIGHT,
-                          GL_COLOR_BUFFER_BIT, GL_NEAREST);
-        
-        glBindFramebuffer(GL_FRAMEBUFFER, 0);
-        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
-        glClear(GL_COLOR_BUFFER_BIT);
-        glUseProgram(screen_shader);
-        glDisable(GL_DEPTH_TEST);
-        glBindTexture(GL_TEXTURE_2D, screen_texture);
-        glBindVertexArray(quad_vao);
-        glDrawArrays(GL_TRIANGLES, 0, 6);
-        glBindVertexArray(0);
-        
-        glfwSwapBuffers(window);
-        
-        F32 elapsed = glfwGetTime()-last_time;
-        if (elapsed < target_spf)
-        {
-            U32 sleep_time = (U32)(target_spf-elapsed);
-            if (sleep_time > 0)
-                sleep(sleep_time);
-        }
-        F32 current_time = glfwGetTime();
-        dt = current_time-last_time;
-        last_time = current_time;
-    }
-    
-    arena_release(arena);
-    glfwTerminate();
-    return(0);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+	window = glfwCreateWindow(width, height, "Anti Aliasing (Off-screen)", 0, 0);
+	if (!window) {
+		fprintf(stderr, "[ERROR] Failed to create window.\n");
+		glfwTerminate();
+		return(1);
+	}
+
+	glfwMakeContextCurrent(window);
+
+	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+
+	if (glewInit() != GLEW_OK) {
+		fprintf(stderr, "[ERROR] Failed to initialize glew.\n");
+		glfwTerminate();
+		return(1);
+	}
+
+	arena = arena_alloc(Kilobytes(4));
+
+	cube = mesh_load_obj(arena, "../../data/models/cube.obj");
+	color_shader = create_shader_program("shaders/color.vert",
+					     "shaders/color.frag");
+	screen_shader = create_shader_program("shaders/screen.vert",
+					      "shaders/screen.frag");
+	glGenFramebuffers(1, &fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+	glGenTextures(1, &color_tex);
+	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color_tex);
+	glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB,
+				width, height, GL_TRUE);
+	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+			       GL_TEXTURE_2D_MULTISAMPLE, color_tex, 0);
+	glGenRenderbuffers(1, &rbo);
+	glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+	glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8,
+					 width, height);
+	glBindRenderbuffer(GL_RENDERBUFFER, 0);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+				  GL_RENDERBUFFER, rbo);
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+		fprintf(stderr, "[ERROR]: Framebuffer is not complete.\n");
+	fprintf(stdout, "[INFO]: Multisample fbo complete.\n");
+	glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+	glGenFramebuffers(1, &intermediate_fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, intermediate_fbo);
+	glGenTextures(1, &screen_texture);
+	glBindTexture(GL_TEXTURE_2D, screen_texture);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
+		     0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+			       GL_TEXTURE_2D, screen_texture, 0);
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+		fprintf(stderr, "[ERROR]: Framebuffer is not complete.\n");
+	fprintf(stdout, "[INFO]: Intermediate fbo complete.\n");
+	glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+	F32 quad_vertices[] = {
+		-1.0f, -1.0f, 0.0f,  0.0f, 0.0f,
+		 1.0f, -1.0f, 0.0f,  1.0f, 0.0f,
+		 1.0f,  1.0f, 0.0f,  1.0f, 1.0f,
+		-1.0f, -1.0f, 0.0f,  0.0f, 0.0f,
+		 1.0f,  1.0f, 0.0f,  1.0f, 1.0f,
+		-1.0f,  1.0f, 0.0f,  0.0f, 1.0f
+	};
+
+	glGenVertexArrays(1, &quad_vao);
+	glBindVertexArray(quad_vao);
+	glGenBuffers(1, &vbo);
+	glBindBuffer(GL_ARRAY_BUFFER, vbo);
+	glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW);
+	glEnableVertexAttribArray(0);
+	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0);
+	glEnableVertexAttribArray(1);
+	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32)));
+	glBindVertexArray(0);
+
+	state.camera = (Camera) {
+		v3f(0.0f, 0.0f, 3.0f),
+			90.0f, 0.1f, 1000.0f,
+			0.0f, 0.0f
+	};
+	input = input_init();
+
+	target_fps = 60.0f;
+	target_spf = 1.0f/target_fps;
+	last_time = glfwGetTime();
+
+	while (!glfwWindowShouldClose(window))
+	{
+		glfwPollEvents();
+
+		/* NOTE(pryazha): Update */
+		glfwGetFramebufferSize(window, &width, &height);
+		process_glfw_keyboard(window, &input);
+		process_glfw_mouse_pos(window, &input);
+
+		if (key_first_press(input.exit))
+			glfwSetWindowShouldClose(window, GLFW_TRUE);
+
+		V3F dv = get_dv_camera_first_person(&input, &state.camera,
+						    4.0f, state.dt);
+		state.camera.pos = v3f_add(state.camera.pos, dv);
+
+		F32 sensitivity = 0.1f;
+		input.mouse_offset = v2f_scalef(input.mouse_offset, sensitivity);
+		state.camera.yaw += input.mouse_offset.x;
+		state.camera.pitch += input.mouse_offset.y;
+		if (state.camera.pitch > 89.0f)
+			state.camera.pitch = 89.0f;
+		if (state.camera.pitch < -89.0f)
+			state.camera.pitch = -89.0f;
+
+		input_update_last_state(&input);
+
+		view = get_view_matrix(&state.camera);
+		proj = perspective(state.camera.fovx, (F32)width/(F32)height,
+				   state.camera.near, state.camera.far);
+		model = mat4_identity();
+
+		/* NOTE(pryazha): Render */
+		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+		glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		glEnable(GL_DEPTH_TEST);
+		glUseProgram(color_shader);
+		shader_set_mat4fv(color_shader, "proj", proj);
+		shader_set_mat4fv(color_shader, "view", view);
+		shader_set_mat4fv(color_shader, "model", model);
+		mesh_draw(cube);
+
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediate_fbo);
+		glBlitFramebuffer(0, 0, width, height,
+				  0, 0, width, height,
+				  GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+		glClear(GL_COLOR_BUFFER_BIT);
+		glUseProgram(screen_shader);
+		glDisable(GL_DEPTH_TEST);
+		glBindTexture(GL_TEXTURE_2D, screen_texture);
+		glBindVertexArray(quad_vao);
+		glDrawArrays(GL_TRIANGLES, 0, 6);
+		glBindVertexArray(0);
+
+		glfwSwapBuffers(window);
+
+		F32 elapsed = glfwGetTime()-last_time;
+		if (elapsed < target_spf) {
+			U32 sleep_time = (U32)(target_spf-elapsed);
+			if (sleep_time > 0)
+				sleep(sleep_time);
+		}
+		F32 current_time = glfwGetTime();
+		state.dt = current_time-last_time;
+		last_time = current_time;
+	}
+
+	arena_release(arena);
+	glfwTerminate();
+	return(0);
 }
-- 
cgit v1.2.3