diff options
25 files changed, 1086 insertions, 6 deletions
@@ -15,3 +15,5 @@ libs/glew/lib/libGLEW.so.2.1.0 advanced_lighting/3.1.shadow_mapping/shadow_mapping advanced_lighting/3.2.point_shadows/point_shadows advanced_lighting/4.normal_mapping/normal_mapping +advanced_lighting/6.hdr/hdr +advanced_lighting/5.parallax_mapping/parallax_mapping diff --git a/advanced_lighting/5.parallax_mapping/build.sh b/advanced_lighting/5.parallax_mapping/build.sh new file mode 100755 index 0000000..e36f110 --- /dev/null +++ b/advanced_lighting/5.parallax_mapping/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +. ../../config +TARGET='parallax_mapping' +set -x +gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS 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); +} diff --git a/advanced_lighting/5.parallax_mapping/shaders/normals_debug.frag b/advanced_lighting/5.parallax_mapping/shaders/normals_debug.frag new file mode 100644 index 0000000..32e36a7 --- /dev/null +++ b/advanced_lighting/5.parallax_mapping/shaders/normals_debug.frag @@ -0,0 +1,10 @@ +#version 330 core + +in vec3 vcolor; + +out vec4 frag_color; + +void main(void) +{ + frag_color = vec4(vcolor, 1.0); +} diff --git a/advanced_lighting/5.parallax_mapping/shaders/normals_debug.geom b/advanced_lighting/5.parallax_mapping/shaders/normals_debug.geom new file mode 100644 index 0000000..79fd4f6 --- /dev/null +++ b/advanced_lighting/5.parallax_mapping/shaders/normals_debug.geom @@ -0,0 +1,44 @@ +#version 330 core +layout(triangles) in; +layout(line_strip, max_vertices=18) out; + +in VS_OUT { + vec4 tangent; + vec4 bitangent; + vec4 normal; +} gs_in[]; + +out vec3 vcolor; + +uniform mat4 proj; + +void gen_normals(int index) +{ + vcolor = vec3(1.0, 0.0, 0.0); + gl_Position = proj*(gl_in[index].gl_Position); + EmitVertex(); + gl_Position = proj*(gl_in[index].gl_Position+0.5*gs_in[index].tangent); + EmitVertex(); + EndPrimitive(); + + vcolor = vec3(0.0, 0.0, 1.0); + gl_Position = proj*(gl_in[index].gl_Position); + EmitVertex(); + gl_Position = proj*(gl_in[index].gl_Position+0.5*gs_in[index].bitangent); + EmitVertex(); + EndPrimitive(); + + vcolor = vec3(0.0, 1.0, 0.0); + gl_Position = proj*(gl_in[index].gl_Position); + EmitVertex(); + gl_Position = proj*(gl_in[index].gl_Position+0.5*gs_in[index].normal); + EmitVertex(); + EndPrimitive(); +} + +void main(void) +{ + gen_normals(0); + gen_normals(1); + gen_normals(2); +} diff --git a/advanced_lighting/5.parallax_mapping/shaders/normals_debug.vert b/advanced_lighting/5.parallax_mapping/shaders/normals_debug.vert new file mode 100644 index 0000000..935fb84 --- /dev/null +++ b/advanced_lighting/5.parallax_mapping/shaders/normals_debug.vert @@ -0,0 +1,22 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 3) in vec3 atangent; +layout(location = 4) in vec3 abitangent; + +out VS_OUT { + vec4 tangent; + vec4 bitangent; + vec4 normal; +} vs_out; + +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + vs_out.tangent = view*model*vec4(normalize(atangent), 0.0); + vs_out.bitangent = view*model*vec4(normalize(abitangent), 0.0); + vs_out.normal = view*model*vec4(normalize(anormal), 0.0); + gl_Position = view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/5.parallax_mapping/shaders/parallax.frag b/advanced_lighting/5.parallax_mapping/shaders/parallax.frag new file mode 100644 index 0000000..6813a30 --- /dev/null +++ b/advanced_lighting/5.parallax_mapping/shaders/parallax.frag @@ -0,0 +1,126 @@ +#version 330 core + +in VS_OUT { + vec3 frag_pos; + vec2 tex_coords; + vec3 tangent_light_pos; + vec3 tangent_view_pos; + vec3 tangent_frag_pos; +} fs_in; + +out vec4 frag_color; + +uniform sampler2D diffuse_texture; +uniform sampler2D normal_map; +uniform sampler2D depth_map; + +uniform float hscale; + +vec2 parallax_mapping(vec2 tex_coords, vec3 view_dir) +{ + float h; + vec2 p, r; + + h = texture(depth_map, tex_coords).r; + p = view_dir.xy/view_dir.z*h*hscale; + r = tex_coords-p; + + return r; +} + +vec2 step_parallax_mapping(vec2 tex_coords, vec3 view_dir) +{ + float minsteps, maxsteps, nsteps, step, dstep, depth; + vec2 p, cur_tex_coords, dtex_coords; + + minsteps = 8.0; + maxsteps = 32.0; + nsteps = mix(maxsteps, minsteps, max(dot(vec3(0.0, 0.0, 1.0), view_dir), 0.0)); + + dstep = 1.0/nsteps; + step = 0.0; + + p = view_dir.xy*hscale; + dtex_coords = p/nsteps; + + cur_tex_coords = tex_coords; + depth = texture(depth_map, cur_tex_coords).r; + + while (step < depth) { + cur_tex_coords -= dtex_coords; + depth = texture(depth_map, cur_tex_coords).r; + step += dstep; + } + + return cur_tex_coords; +} + +vec2 parallax_occlusion_mapping(vec2 tex_coords, vec3 view_dir) +{ + float minsteps, maxsteps, nsteps, step, dstep, depth, + after_depth, before_depth, weight; + vec2 p, cur_tex_coords, dtex_coords, prev_tex_coords, result; + + minsteps = 8.0; + maxsteps = 32.0; + nsteps = mix(maxsteps, minsteps, max(dot(vec3(0.0, 0.0, 1.0), view_dir), 0.0)); + + dstep = 1.0/nsteps; + step = 0.0; + + p = view_dir.xy*hscale; + dtex_coords = p/nsteps; + + cur_tex_coords = tex_coords; + depth = texture(depth_map, cur_tex_coords).r; + + while (step < depth) { + cur_tex_coords -= dtex_coords; + depth = texture(depth_map, cur_tex_coords).r; + step += dstep; + } + + prev_tex_coords = cur_tex_coords+dtex_coords; + + after_depth = depth-step; + before_depth = texture(depth_map, prev_tex_coords).r-step+dstep; + + weight = after_depth/(after_depth-before_depth); + result = prev_tex_coords*weight+cur_tex_coords*(1.0-weight); + + return result; +} + +void main(void) +{ + vec3 color, light_color, + normal, view_dir, halfway_dir, light_dir, + ambient, diffuse, specular, result; + vec2 tex_coords; + float diff, spec; + + view_dir = normalize(fs_in.tangent_view_pos-fs_in.tangent_frag_pos); + tex_coords = parallax_occlusion_mapping(fs_in.tex_coords, view_dir); + if ((tex_coords.x > 1.0) || (tex_coords.y > 1.0) || (tex_coords.x < 0.0) || (tex_coords.y < 0.0)) + discard; + + color = vec3(texture(diffuse_texture, tex_coords)); + normal = vec3(texture(normal_map, tex_coords)); + normal = normalize((normal*2.0)-1.0); + + light_color = vec3(1.0); + + ambient = vec3(0.01); + + light_dir = normalize(fs_in.tangent_light_pos-fs_in.tangent_frag_pos); + diff = max(dot(light_dir, normal), 0.0); + diffuse = diff*light_color; + + halfway_dir = normalize(light_dir+view_dir); + spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0); + specular = spec*light_color; + + result = (ambient+diffuse+specular)*color; + + frag_color = vec4(result, 1.0); +} diff --git a/advanced_lighting/5.parallax_mapping/shaders/parallax.vert b/advanced_lighting/5.parallax_mapping/shaders/parallax.vert new file mode 100644 index 0000000..a3451c3 --- /dev/null +++ b/advanced_lighting/5.parallax_mapping/shaders/parallax.vert @@ -0,0 +1,37 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 2) in vec2 atex_coords; +layout(location = 3) in vec3 atangent; +layout(location = 4) in vec3 abitangent; + +out VS_OUT { + vec3 frag_pos; + vec2 tex_coords; + vec3 tangent_light_pos; + vec3 tangent_view_pos; + vec3 tangent_frag_pos; +} vs_out; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +uniform vec3 light_pos; +uniform vec3 view_pos; + +void main(void) +{ + gl_Position = proj*view*model*vec4(apos, 1.0); + vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); + vs_out.tex_coords = atex_coords; + + vec3 T = normalize(mat3(model)*atangent); + vec3 B = normalize(mat3(model)*abitangent); + vec3 N = normalize(mat3(model)*anormal); + mat3 TBN = transpose(mat3(T, B, N)); + + vs_out.tangent_light_pos = TBN*light_pos; + vs_out.tangent_view_pos = TBN*view_pos; + vs_out.tangent_frag_pos = TBN*vs_out.frag_pos; +} diff --git a/advanced_lighting/6.hdr/build.sh b/advanced_lighting/6.hdr/build.sh new file mode 100755 index 0000000..3957e1d --- /dev/null +++ b/advanced_lighting/6.hdr/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +. ../../config +TARGET='hdr' +set -x +gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS diff --git a/advanced_lighting/6.hdr/hdr.c b/advanced_lighting/6.hdr/hdr.c new file mode 100644 index 0000000..911f9da --- /dev/null +++ b/advanced_lighting/6.hdr/hdr.c @@ -0,0 +1,254 @@ +#include "GL/glew.h" +#include "GLFW/glfw3.h" + +#include "pwyazh.h" +#include "pwyazh_GL.h" + +#include "common.h" + +#define LCOUNT 8 + +int main(void) +{ + S32 width, height; + + GLFWwindow *window; + F64 time, last_time; + + State state = {0}; + + U32 wooodtex; + + Mesh *quad, + *cube, + *tubecube; + + U32 blinn_shader, + hdr_shader, + light_shader, + normals_debug_shader; + + U32 hdrfbo, + hdrcolorbuf, + hdrrbo; + + S32 i; + + F32 a, da, r; + V3F lpos[LCOUNT]; + + F32 exposure; + + S32 show_normals, show_lights; + + 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); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + window = glfwCreateWindow(width, height, "HDR", 0, 0); + if (!window) + goto error; + + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + glfwMakeContextCurrent(window); + + if (glewInit() != GLEW_OK) + goto error; + + glEnable(GL_DEPTH_TEST); + + /* NOTE(pryazha): Program init */ + state.arena = arena_alloc(Kilobytes(256)); + + state.input.first_mouse = 1; + + state.camera = (Camera){ v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 100.0f, 0.0f, 0.0f }; + state.camera_dp = v3f_zero(); + + da = 2.0f*pi_F32/LCOUNT; + for (i = 0, a = 0.0f, r = 2.0f; i < LCOUNT; i++, a += da) + lpos[i] = v3f(f32_sin(a)*r, 0.0f, f32_cos(a)*r); + + exposure = 1.0f; + + show_normals = 0; + show_lights = 1; + + /* NOTE(pryazha): Textures */ + wooodtex = load_texture_gamma("../../data/textures/wood.png", 1); + + /* NOTE(pryazha): Meshes */ + quad = mesh_gen_quad(state.arena); + cube = mesh_load_obj(state.arena, "../../data/models/cube.obj"); + tubecube = mesh_load_obj(state.arena, "../../data/models/tube_with_cube.obj"); + + /* NOTE(pryazha): Shaders */ + blinn_shader = create_shader_program("shaders/blinn.vert", "shaders/blinn.frag"); + hdr_shader = create_shader_program("shaders/hdr.vert", "shaders/hdr.frag"); + light_shader = create_shader_program("shaders/light.vert", "shaders/light.frag"); + normals_debug_shader = create_shader_program_geom("shaders/normals_debug.vert", + "shaders/normals_debug.frag", + "shaders/normals_debug.geom"); + + /* NOTE(pryazha): Create HDR framebuffer, color buffer texture and + * renderbuffer */ + glGenFramebuffers(1, &hdrfbo); + glGenTextures(1, &hdrcolorbuf); + glBindTexture(GL_TEXTURE_2D, hdrcolorbuf); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glGenRenderbuffers(1, &hdrrbo); + glBindRenderbuffer(GL_RENDERBUFFER, hdrrbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); + + glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hdrcolorbuf, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, hdrrbo); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + fprintf(stderr, "[ERROR] : GL : Failed to complete framebuffer\n"); + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + last_time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + glfwGetFramebufferSize(window, &width, &height); + process_glfw_keyboard(window, &state.input); + process_glfw_mouse_pos(window, &state.input); + + if (key_first_press(state.input.exit)) + glfwSetWindowShouldClose(window, GLFW_TRUE); + + /* NOTE(pryazha): Update */ + F32 speed, sensitivity; + V3F dv; + + speed = 2.0f; + dv = get_dv_camera_first_person(&state.input, &state.camera, speed, state.dt); + state.camera_dp = v3f_add(state.camera_dp, dv); + state.camera_dp = v3f_scalef(state.camera_dp, 0.8f); + state.camera.pos = v3f_add(state.camera.pos, state.camera_dp); + + sensitivity = 0.1f; + state.input.mouse_offset = v2f_scalef(state.input.mouse_offset, sensitivity); + state.camera.yaw += state.input.mouse_offset.x; + state.camera.pitch += state.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; + + if (key_first_press(state.input.jump)) { + show_normals = !show_normals; + show_lights = !show_lights; + } + + if (key_is_pressed(state.input.action_down)) + exposure -= 0.01f; + if (key_is_pressed(state.input.action_up)) + exposure += 0.01f; + + for (i = 0; i < LCOUNT; i++) + lpos[i].y = f32_sin(glfwGetTime()+i); + + /* NOTE(pryazha): Render */ + F32 ar; + MAT4 proj, view, model; + char lstr[1024]; + + ar = (F32)width/(F32)height; + proj = camera_persp(state.camera, ar); + view = get_view_matrix(&state.camera); + + glClearColor(0.15f, 0.15f, 0.15f, 1.0f); + + glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo); + + glViewport(0, 0, width, height); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + model = mat4_identity(); + + glUseProgram(blinn_shader); + shader_set_mat4fv(blinn_shader, "proj", proj); + shader_set_mat4fv(blinn_shader, "view", view); + shader_set_mat4fv(blinn_shader, "model", model); + shader_set_1i(blinn_shader, "lcount", LCOUNT); + for (i = 0; i < LCOUNT; i++) { + snprintf(lstr, 1024, "lpos[%d]", i); + shader_set_3fv(blinn_shader, lstr, lpos[i]); + } + glBindTexture(GL_TEXTURE_2D, wooodtex); + shader_set_1i(blinn_shader, "invert_normals", 0); + mesh_draw(cube); + shader_set_1i(blinn_shader, "invert_normals", 1); + mesh_draw(tubecube); + glBindTexture(GL_TEXTURE_2D, 0); + glUseProgram(0); + + if (show_lights) { + glUseProgram(light_shader); + shader_set_mat4fv(light_shader, "proj", proj); + shader_set_mat4fv(light_shader, "view", view); + for (i = 0; i < LCOUNT; i++) { + model = mat4_make_scale(v3f(0.2f, 0.2f, 0.2f)); + model = mat4_translate(model, lpos[i]); + shader_set_mat4fv(light_shader, "model", model); + mesh_draw(cube); + } + glUseProgram(0); + } + + if (show_normals) { + model = mat4_identity(); + + glUseProgram(normals_debug_shader); + shader_set_mat4fv(normals_debug_shader, "proj", proj); + shader_set_mat4fv(normals_debug_shader, "view", view); + shader_set_mat4fv(normals_debug_shader, "model", model); + mesh_draw(cube); + glUseProgram(0); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(hdr_shader); + shader_set_1f(hdr_shader, "exposure", exposure); + glBindTexture(GL_TEXTURE_2D, hdrcolorbuf); + mesh_draw(quad); + glUseProgram(0); + + glfwSwapBuffers(window); + + time = glfwGetTime(); + state.dt = time-last_time; + last_time = time; + + input_update_last_state(&state.input); + } + + arena_release(state.arena); + glfwTerminate(); + return 0; + +error: + arena_release(state.arena); + glfwTerminate(); + return 1; +} diff --git a/advanced_lighting/6.hdr/shaders/blinn.frag b/advanced_lighting/6.hdr/shaders/blinn.frag new file mode 100644 index 0000000..5dca1f7 --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/blinn.frag @@ -0,0 +1,54 @@ +#version 330 core + +in VS_OUT { + vec3 fpos; + vec3 fn; + vec2 texc; +} fsin; + +out vec4 fcolor; + +uniform sampler2D diftex; + +const int lmax = 30; + +uniform int lcount; +uniform vec3 lpos[lmax]; +uniform vec3 vpos; + +void main(void) +{ + vec3 l, v, n, difcolor, lcolor, ambient, halfdir, result; + float diff, spec, specf, dist, attenuation; + int i; + + n = normalize(fsin.fn); + v = normalize(vpos-fsin.fpos); + + ambient = vec3(0.001); + + difcolor = vec3(texture(diftex, fsin.texc)); + + /* lcolor = vec3(0.3, 0.0, 0.1); */ + lcolor = vec3(1.0); + + specf = 0.2; + + result = vec3(0.0); + + for (i = 0; i < lcount; i++) { + l = normalize(lpos[i]-fsin.fpos); + halfdir = normalize(l+v); + + diff = max(dot(n, l), 0.0); + + spec = pow(max(dot(n, halfdir), 0.0), 16.0)*specf; + + dist = length(lpos[i]-fsin.fpos); + attenuation = 1.0/dist; + + result += (diff+spec)*difcolor*lcolor*attenuation; + } + + fcolor = vec4(ambient+result, 1.0); +} diff --git a/advanced_lighting/6.hdr/shaders/blinn.vert b/advanced_lighting/6.hdr/shaders/blinn.vert new file mode 100644 index 0000000..f08f38e --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/blinn.vert @@ -0,0 +1,34 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 2) in vec2 atexc; + +out VS_OUT { + vec3 fpos; + vec3 fn; + vec2 texc; +} vsout; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +uniform bool invert_normals; + +void main(void) +{ + mat3 normtransf; + + vsout.fpos = vec3(model*vec4(apos, 1.0)); + + normtransf = mat3(transpose(inverse(model))); + + if (invert_normals) + vsout.fn = normtransf*(-anormal); + else + vsout.fn = normtransf*anormal; + + vsout.texc = atexc; + + gl_Position = proj*view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/6.hdr/shaders/hdr.frag b/advanced_lighting/6.hdr/shaders/hdr.frag new file mode 100644 index 0000000..f12c6a8 --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/hdr.frag @@ -0,0 +1,29 @@ +#version 330 core + +in VSOUT { + vec2 texc; +} vsout; + +out vec4 fcolor; + +uniform sampler2D hdrbuf; +uniform float exposure; + +void main(void) +{ + const float gamma = 2.2; + + vec3 hdrcolor, mapped; + + hdrcolor = vec3(texture(hdrbuf, vsout.texc)); + + /* NOTE(pryazha): Reinhard tone mapping */ + /* mapped = hdrcolor/(hdrcolor+vec3(1.0)); */ + + /* NOTE(pryazha): Tone mapping with exposure (i guess) */ + mapped = vec3(1.0)-exp(-hdrcolor*exposure); + + mapped = pow(mapped, vec3(1.0/gamma)); + + fcolor = vec4(mapped, 1.0); +} diff --git a/advanced_lighting/6.hdr/shaders/hdr.vert b/advanced_lighting/6.hdr/shaders/hdr.vert new file mode 100644 index 0000000..4f15c72 --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/hdr.vert @@ -0,0 +1,14 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 2) in vec2 atexc; + +out VSOUT { + vec2 texc; +} vsout; + +void main(void) +{ + vsout.texc = atexc; + + gl_Position = vec4(apos, 1.0); +} diff --git a/advanced_lighting/6.hdr/shaders/light.frag b/advanced_lighting/6.hdr/shaders/light.frag new file mode 100644 index 0000000..3829c91 --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/light.frag @@ -0,0 +1,8 @@ +#version 330 core + +out vec4 fcolor; + +void main(void) +{ + fcolor = vec4(1.0); +} diff --git a/advanced_lighting/6.hdr/shaders/light.vert b/advanced_lighting/6.hdr/shaders/light.vert new file mode 100644 index 0000000..a24ade5 --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/light.vert @@ -0,0 +1,11 @@ +#version 330 core +layout(location = 0) in vec3 apos; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + gl_Position = proj*view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/6.hdr/shaders/normals_debug.frag b/advanced_lighting/6.hdr/shaders/normals_debug.frag new file mode 100644 index 0000000..32e36a7 --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/normals_debug.frag @@ -0,0 +1,10 @@ +#version 330 core + +in vec3 vcolor; + +out vec4 frag_color; + +void main(void) +{ + frag_color = vec4(vcolor, 1.0); +} diff --git a/advanced_lighting/6.hdr/shaders/normals_debug.geom b/advanced_lighting/6.hdr/shaders/normals_debug.geom new file mode 100644 index 0000000..bdbc1b3 --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/normals_debug.geom @@ -0,0 +1,28 @@ +#version 330 core +layout(triangles) in; +layout(line_strip, max_vertices=6) out; + +in VS_OUT { + vec4 normal; +} gs_in[]; + +out vec3 vcolor; + +uniform mat4 proj; + +void gen_normals(int index) +{ + vcolor = vec3(0.0, 1.0, 0.0); + gl_Position = proj*(gl_in[index].gl_Position); + EmitVertex(); + gl_Position = proj*(gl_in[index].gl_Position+0.5*gs_in[index].normal); + EmitVertex(); + EndPrimitive(); +} + +void main(void) +{ + gen_normals(0); + gen_normals(1); + gen_normals(2); +} diff --git a/advanced_lighting/6.hdr/shaders/normals_debug.vert b/advanced_lighting/6.hdr/shaders/normals_debug.vert new file mode 100644 index 0000000..2d3a4b5 --- /dev/null +++ b/advanced_lighting/6.hdr/shaders/normals_debug.vert @@ -0,0 +1,16 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; + +out VS_OUT { + vec4 normal; +} vs_out; + +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + vs_out.normal = view*model*vec4(normalize(anormal), 0.0); + gl_Position = view*model*vec4(apos, 1.0); +} diff --git a/data/models/tube_with_cube.obj b/data/models/tube_with_cube.obj new file mode 100644 index 0000000..cf2d7e9 --- /dev/null +++ b/data/models/tube_with_cube.obj @@ -0,0 +1,79 @@ +# Blender 4.3.2 +# www.blender.org +o Cube +v 4.000000 4.000000 -4.000000 +v 4.000000 -4.000000 -4.000000 +v 4.000000 4.000000 4.000000 +v 4.000000 -4.000000 4.000000 +v -4.000000 4.000000 -4.000000 +v -4.000000 -4.000000 -4.000000 +v -4.000000 4.000000 4.000000 +v -4.000000 -4.000000 4.000000 +v 1.701859 1.701859 4.000000 +v 1.701859 -1.701859 4.000000 +v -1.701859 1.701859 4.000000 +v -1.701859 -1.701859 4.000000 +v 1.701859 1.701859 22.548218 +v 1.701859 -1.701859 22.548218 +v -1.701859 1.701859 22.548218 +v -1.701859 -1.701859 22.548218 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 1.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 0.000000 0.000000 +vt 0.287268 0.712732 +vt 0.000000 1.000000 +vt 1.000000 0.000000 +vt 0.287268 0.287268 +vt 0.712732 0.712732 +vt 1.000000 1.000000 +vt 0.712732 0.287268 +vt 0.183507 -0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 0.367013 -0.000000 +vt 0.183507 1.000000 +vt 0.183507 -0.000000 +vt 0.550520 0.000000 +vt 0.367013 1.000000 +vt 0.367013 0.000000 +vt 0.734026 -0.000000 +vt 0.550520 1.000000 +vt 0.550520 0.000000 +vt 0.183507 1.000000 +vt 0.367013 1.000000 +vt 0.550520 1.000000 +vt 0.734026 1.000000 +s 0 +f 5/1/1 3/2/1 1/3/1 +f 8/4/2 11/5/2 7/6/2 +f 7/1/3 6/2/3 8/3/3 +f 2/1/4 8/2/4 6/3/4 +f 1/1/5 4/2/5 2/3/5 +f 5/1/6 2/2/6 6/3/6 +f 4/7/2 12/8/2 8/4/2 +f 7/6/2 9/9/2 3/10/2 +f 3/10/2 10/11/2 4/7/2 +f 11/12/1 13/13/1 9/14/1 +f 12/15/3 15/16/3 11/17/3 +f 10/18/4 16/19/4 12/20/4 +f 9/21/5 14/22/5 10/23/5 +f 5/1/1 7/10/1 3/2/1 +f 8/4/2 12/8/2 11/5/2 +f 7/1/3 5/10/3 6/2/3 +f 2/1/4 4/10/4 8/2/4 +f 1/1/5 3/10/5 4/2/5 +f 5/1/6 1/10/6 2/2/6 +f 4/7/2 10/11/2 12/8/2 +f 7/6/2 11/5/2 9/9/2 +f 3/10/2 9/9/2 10/11/2 +f 11/12/1 15/24/1 13/13/1 +f 12/15/3 16/25/3 15/16/3 +f 10/18/4 14/26/4 16/19/4 +f 9/21/5 13/27/5 14/22/5 diff --git a/data/textures/bricks2.jpg b/data/textures/bricks2.jpg Binary files differnew file mode 100644 index 0000000..3583508 --- /dev/null +++ b/data/textures/bricks2.jpg diff --git a/data/textures/bricks2_disp.jpg b/data/textures/bricks2_disp.jpg Binary files differnew file mode 100644 index 0000000..48ab26f --- /dev/null +++ b/data/textures/bricks2_disp.jpg diff --git a/data/textures/bricks2_normal.jpg b/data/textures/bricks2_normal.jpg Binary files differnew file mode 100644 index 0000000..aa6643d --- /dev/null +++ b/data/textures/bricks2_normal.jpg diff --git a/libs/common.h b/libs/common.h index b12e4a1..b535c72 100644 --- a/libs/common.h +++ b/libs/common.h @@ -12,7 +12,7 @@ #include <sys/stat.h> #include <fcntl.h> -U8 * read_entire_file(const char *filename) +U8 *read_entire_file(const char *filename) { U8 *result; FILE *f; @@ -40,7 +40,7 @@ U8 * read_entire_file(const char *filename) return(result); } -void * mmap_file(size_t *len, const char *filename) +void *mmap_file(size_t *len, const char *filename) { struct stat sb; char* p; @@ -95,7 +95,33 @@ void read_entire_file_mmap(void* ctx, const char* filename, const int is_mtl, *len = data_len; } -Mesh * mesh_load_obj(Arena *arena, const char *filename) +Mesh *mesh_gen_quad(Arena *arena) +{ + Mesh *m; + Vertex verts[4]; + U32 ids[6]; + + m = 0; + + verts[0] = vertex(v3f( 1.0f, 1.0f, 0.0f), v3f_zero(), v2f(1.0f, 1.0f)); + verts[1] = vertex(v3f(-1.0f, 1.0f, 0.0f), v3f_zero(), v2f(0.0f, 1.0f)); + verts[2] = vertex(v3f(-1.0f, -1.0f, 0.0f), v3f_zero(), v2f(0.0f, 0.0f)); + verts[3] = vertex(v3f( 1.0f, -1.0f, 0.0f), v3f_zero(), v2f(1.0f, 0.0f)); + + ids[0] = 0; + ids[1] = 1; + ids[2] = 2; + + ids[3] = 0; + ids[4] = 2; + ids[5] = 3; + + m = mesh_init(arena, verts, 4, ids, 6); + + return m; +} + +Mesh *mesh_load_obj(Arena *arena, const char *filename) { tinyobj_attrib_t attrib; tinyobj_shape_t *shapes = 0; @@ -767,9 +793,22 @@ V3F get_dv_camera_first_person(Input *input, Camera *camera, return(dv); } +MAT4 camera_persp(Camera camera, F32 ar) +{ + MAT4 result; + result = perspective(camera.fovx, ar, camera.near, camera.far); + return result; +} + typedef struct { - Camera camera; - F32 dt; + Arena *arena; + + Input input; + + Camera camera; + V3F camera_dp; + + F32 dt; } State; #endif /* COMMON_H */ diff --git a/libs/pwyazh/types.h b/libs/pwyazh/types.h index 0704299..988206a 100644 --- a/libs/pwyazh/types.h +++ b/libs/pwyazh/types.h @@ -34,9 +34,9 @@ typedef struct { } MAT4; typedef struct { - U8 *memory; U64 capacity; U64 used; + U8 *memory; } Arena; /* NOTE(pryazha): String types */ |