1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "common.h"
int main(void)
{
state_t state = init_state(1600, 800);
init_glfw(&state);
init_gl();
/* meshes */
Mesh *sphere = mesh_load_obj(state.arena, "../../data/models/sphere.obj");
Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj");
Mesh *quad = mesh_gen_quad(state.arena);
/* shaders */
add_shader("pbr.vert", "pbr.frag", 0);
add_shader("hdr.vert", "hdr.frag", 0);
U32 shader = find_shader("pbr");
if (!shader)
die("not again");
glUseProgram(shader);
shader_set_1i(shader, "color_map", 0);
shader_set_1i(shader, "normal_map", 1);
shader_set_1i(shader, "metallic_map", 2);
shader_set_1i(shader, "roughness_map", 3);
shader_set_1i(shader, "ao_map", 4);
glUseProgram(0);
light_t lights[4] = {
{{-6.0f, 0.0f, 7.0f}, {300.0f, 300.0f, 300.0f}},
{{-4.0f, 0.0f, 6.0f}, {300.0f, 300.0f, 300.0f}},
{{ 1.0f, 0.0f, 5.0f}, {300.0f, 300.0f, 300.0f}},
{{ 3.0f, 0.0f, 8.0f}, {300.0f, 300.0f, 300.0f}},
};
/* textures */
U32 color_map = load_texture("../../data/textures/pbr/albedo.png");
U32 normal_map = load_texture("../../data/textures/pbr/normal.png");
U32 metallic_map = load_texture("../../data/textures/pbr/metallic.png");
U32 roughness_map = load_texture("../../data/textures/pbr/roughness.png");
U32 ao_map = load_texture("../../data/textures/pbr/ao.png");
/* framebuffers */
U32 hdr_fbo, hdr_colorbuffer, hdr_rbo;
glGenFramebuffers(1, &hdr_fbo);
glGenTextures(1, &hdr_colorbuffer);
glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, state.width, state.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, &hdr_rbo);
glBindRenderbuffer(GL_RENDERBUFFER, hdr_rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, state.width, state.height);
glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hdr_colorbuffer, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, hdr_rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
die("failed to create framebuffer");
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
F32 time = 0;
while (!glfwWindowShouldClose(state.window)) {
handle_glfw_events(state.window, &state.input);
F32 dt = lock_framerate(60);
fps_info(dt, 10);
/* update */
update_camera_first_person(&state.camera, &state.input, dt, 2.0f);
F32 limit = 4.0f;
for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++)
lights[i].position.y = sinf(2.0f * time + i) * limit;
time += dt;
/* render */
F32 ar = (F32)state.width / (F32)state.height;
MAT4 projection = camera_persp(state.camera, ar);
MAT4 view = get_view_matrix(&state.camera);
glClearColor(0.16f, 0.16f, 0.16f, 1.0f);
glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader = find_shader("pbr");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, color_map);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normal_map);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, metallic_map);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, roughness_map);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, ao_map);
if (!shader) die("wha");
glUseProgram(shader);
shader_set_mat4fv(shader, "projection", projection);
shader_set_mat4fv(shader, "view", view);
shader_set_3fv(shader, "camera", state.camera.pos);
for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++) {
char str[512];
snprintf(str, 512, "lights[%d].position", i);
shader_set_3fv(shader, str, lights[i].position);
snprintf(str, 512, "lights[%d].color", i);
shader_set_3fv(shader, str, lights[i].color);
}
S32 rows = 7;
S32 cols = 7;
F32 offset = 3.0f;
for (S32 row = 0; row < rows; row++) {
for (S32 col = 0; col < cols; col++) {
V3F pos = {(col - cols / 2.0f) * offset, (row - rows / 2.0f) * offset, 0.0f};
MAT4 model = mat4_make_translate(pos);
shader_set_mat4fv(shader, "model", model);
mesh_draw(cube);
}
}
for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++) {
MAT4 model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
model = mat4_translate(model, lights[i].position);
shader_set_mat4fv(shader, "model", model);
mesh_draw(sphere);
}
glUseProgram(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader = find_shader("hdr");
if (!shader) die("!");
glUseProgram(shader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer);
shader_set_mat4fv(shader, "model", mat4_identity());
mesh_draw(quad);
glUseProgram(0);
glfwSwapBuffers(state.window);
}
return 0;
}
|