diff options
author | pryazha <pryadeiniv@mail.ru> | 2025-03-18 11:31:31 +0500 |
---|---|---|
committer | pryazha <pryadeiniv@mail.ru> | 2025-03-18 11:31:31 +0500 |
commit | d65ddd07a43d5ffdcf2ddf90d6f86626cf9b92d8 (patch) | |
tree | 672efce6089ec9c1103be0c1b70a28ec415eeeab /advanced_lighting/5.parallax_mapping/parallax_mapping.c | |
parent | d64a159d05a45e75870f61c37f0defa94f03793e (diff) |
Diffstat (limited to 'advanced_lighting/5.parallax_mapping/parallax_mapping.c')
-rw-r--r-- | advanced_lighting/5.parallax_mapping/parallax_mapping.c | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/advanced_lighting/5.parallax_mapping/parallax_mapping.c b/advanced_lighting/5.parallax_mapping/parallax_mapping.c new file mode 100644 index 0000000..35859d2 --- /dev/null +++ b/advanced_lighting/5.parallax_mapping/parallax_mapping.c @@ -0,0 +1,253 @@ +#include "GL/glew.h" +#include "GLFW/glfw3.h" + +#include "pwyazh.h" +#include "pwyazh_GL.h" + +#include "common.h" + +U32 gen_quad_with_tan() +{ + /* Positions */ + V3F p1 = v3f(-1.0f, 1.0f, 0.0f); + V3F p2 = v3f(-1.0f, -1.0f, 0.0f); + V3F p3 = v3f(1.0f, -1.0f, 0.0f); + V3F p4 = v3f(1.0f, 1.0f, 0.0f); + /* Texture ccoordinates */ + V2F uv1 = v2f(0.0f, 1.0f); + V2F uv2 = v2f(0.0f, 0.0f); + V2F uv3 = v2f(1.0f, 0.0f); + V2F uv4 = v2f(1.0f, 1.0f); + /* Normal vector */ + V3F nm = v3f(0.0f, 0.0f, 1.0f); + + V3F edge1, edge2; + V2F duv1, duv2; + F32 f; + V3F t1, bit1, t2, bit2; + + edge1 = v3f_sub(p2, p1); + edge2 = v3f_sub(p3, p1); + duv1 = v2f_sub(uv2, uv1); + duv2 = v2f_sub(uv3, uv1); + + f = 1.0f/(duv1.x*duv2.y-duv2.x*duv1.y); + + t1.x = f*(duv2.y*edge1.x-duv1.y*edge2.x); + t1.y = f*(duv2.y*edge1.y-duv1.y*edge2.y); + t1.z = f*(duv2.y*edge1.z-duv1.y*edge2.z); + + bit1.x = f*(-duv2.x*edge1.x+duv1.x*edge2.x); + bit1.y = f*(-duv2.x*edge1.y+duv1.x*edge2.y); + bit1.z = f*(-duv2.x*edge1.z+duv1.x*edge2.z); + + edge1 = v3f_sub(p3, p1); + edge2 = v3f_sub(p4, p1); + duv1 = v2f_sub(uv3, uv1); + duv2 = v2f_sub(uv4, uv1); + + f = 1.0f/(duv1.x*duv2.y-duv2.x*duv1.y); + + t2.x = f*(duv2.y*edge1.x-duv1.y*edge2.x); + t2.y = f*(duv2.y*edge1.y-duv1.y*edge2.y); + t2.z = f*(duv2.y*edge1.z-duv1.y*edge2.z); + + bit2.x = f*(-duv2.x*edge1.x+duv1.x*edge2.x); + bit2.y = f*(-duv2.x*edge1.y+duv1.x*edge2.y); + bit2.z = f*(-duv2.x*edge1.z+duv1.x*edge2.z); + + F32 quad_vertices[] = { + p1.x, p1.y, p1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, t1.x, t1.y, t1.z, bit1.x, bit1.y, bit1.z, + p2.x, p2.y, p2.z, nm.x, nm.y, nm.z, uv2.x, uv2.y, t1.x, t1.y, t1.z, bit1.x, bit1.y, bit1.z, + p3.x, p3.y, p3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, t1.x, t1.y, t1.z, bit1.x, bit1.y, bit1.z, + + p1.x, p1.y, p1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, t2.x, t2.y, t2.z, bit2.x, bit2.y, bit2.z, + p3.x, p3.y, p3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, t2.x, t2.y, t2.z, bit2.x, bit2.y, bit2.z, + p4.x, p4.y, p4.z, nm.x, nm.y, nm.z, uv4.x, uv4.y, t2.x, t2.y, t2.z, bit2.x, bit2.y, bit2.z + }; + U32 quad_vao, vbo; + 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, 14*sizeof(F32), (void *)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)(3*sizeof(F32))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)(6*sizeof(F32))); + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)(8*sizeof(F32))); + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)(11*sizeof(F32))); + glBindVertexArray(0); + + return quad_vao; +} + +int main(void) +{ + GLFWwindow *window; + State state; + Input input = {0}; + F64 time, last_time; + V3F camera_dp; + Arena *arena = 0; + S32 width, height; + + U32 vao, parallax_shader, normals_debug_shader; + U32 diffuse_texture, normal_texture, depth_texture; + + V3F light_pos; + + width = 800; + height = 600; + + /* NOTE(pryazha): GLFW init */ + glfwSetErrorCallback(error_callback); + + if (glfwInit() == GLFW_FALSE) + return(1); + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + window = glfwCreateWindow(width, height, "Point shadows", 0, 0); + if (!window) + goto error; + + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + glfwMakeContextCurrent(window); + + if (glewInit() != GLEW_OK) + goto error; + + /* NOTE(pryazha): Program init */ + arena = arena_alloc(Kilobytes(4)); + + input.first_mouse = 1; + + state.camera = (Camera){ v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 100.0f, 0.0f, 0.0f }; + camera_dp = v3f_zero(); + + light_pos = v3f(1.0f, 2.0f, 1.0f); + + + /* NOTE(pryazha): Meshes */ + vao = gen_quad_with_tan(); + + diffuse_texture = load_texture("../../data/textures/bricks2.jpg"); + normal_texture = load_texture("../../data/textures/bricks2_normal.jpg"); + depth_texture = load_texture("../../data/textures/bricks2_disp.jpg"); + + /* NOTE(pryazha): Shaders */ + parallax_shader = create_shader_program("shaders/parallax.vert", "shaders/parallax.frag"); + normals_debug_shader = create_shader_program_geom("shaders/normals_debug.vert", + "shaders/normals_debug.frag", + "shaders/normals_debug.geom"); + + glUseProgram(parallax_shader); + shader_set_1i(parallax_shader, "diffuse_texture", 0); + shader_set_1i(parallax_shader, "normal_map", 1); + shader_set_1i(parallax_shader, "depth_map", 2); + glUseProgram(0); + + last_time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + /* NOTE(pryazha): Update */ + F32 speed, sensitivity; + V3F dv; + + 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); + + speed = 2.0f; + dv = get_dv_camera_first_person(&input, &state.camera, speed, state.dt); + if (key_is_pressed(input.action_up)) + dv = v3f_scalef(dv, 3.0f); + camera_dp = v3f_add(camera_dp, dv); + camera_dp = v3f_scalef(camera_dp, 0.8f); + state.camera.pos = v3f_add(state.camera.pos, camera_dp); + + 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); + + /* NOTE(pryazha): Render */ + F32 ar; + MAT4 proj, view, model; + + ar = (F32)width/(F32)height; + proj = camera_persp(state.camera, ar); + view = get_view_matrix(&state.camera); + model = mat4_identity(); + + glViewport(0, 0, width, height); + glClearColor(0.15f, 0.15f, 0.15f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* NOTE(pryazha): Draw the quad */ + glUseProgram(parallax_shader); + shader_set_mat4fv(parallax_shader, "proj", proj); + shader_set_mat4fv(parallax_shader, "view", view); + shader_set_mat4fv(parallax_shader, "model", model); + shader_set_3fv(parallax_shader, "light_pos", light_pos); + shader_set_3fv(parallax_shader, "view_pos", state.camera.pos); + shader_set_1f(parallax_shader, "hscale", 0.1f); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, diffuse_texture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, normal_texture); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, depth_texture); + glBindVertexArray(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + glUseProgram(0); + + /* NOTE(pryazha): Draw normals */ + glUseProgram(normals_debug_shader); + shader_set_mat4fv(normals_debug_shader, "proj", proj); + shader_set_mat4fv(normals_debug_shader, "model", model); + shader_set_mat4fv(normals_debug_shader, "view", view); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, diffuse_texture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, normal_texture); + glBindVertexArray(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + glUseProgram(0); + + glfwSwapBuffers(window); + + time = glfwGetTime(); + state.dt = time-last_time; + last_time = time; + } + + glDeleteVertexArrays(1, &vao); + arena_release(arena); + glfwTerminate(); + return(0); + +error: + arena_release(arena); + glfwTerminate(); + return(1); +} |