commit 0ff60c40ac67f3bd0b9daa70cafa7b37328dbfdd
parent bf16c6674db2a5dd3cfb23a22b418223502e3c25
Author: William Casarin <jb55@jb55.com>
Date: Sun, 28 Oct 2018 23:05:41 -0700
shadows working
Diffstat:
19 files changed, 137 insertions(+), 52 deletions(-)
diff --git a/Makefile b/Makefile
@@ -16,6 +16,7 @@ OBJS += $(SRC)/buffer.o
OBJS += $(SRC)/camera.o
OBJS += $(SRC)/debug.o
OBJS += $(SRC)/delaunay.o
+OBJS += $(SRC)/entity.o
OBJS += $(SRC)/event.o
OBJS += $(SRC)/fbo.o
OBJS += $(SRC)/file.o
@@ -34,11 +35,11 @@ OBJS += $(SRC)/quat.o
OBJS += $(SRC)/render.o
OBJS += $(SRC)/shader.o
OBJS += $(SRC)/terrain.o
+OBJS += $(SRC)/ui.o
OBJS += $(SRC)/uniform.o
OBJS += $(SRC)/update.o
OBJS += $(SRC)/util.o
OBJS += $(SRC)/vec3.o
-OBJS += $(SRC)/ui.o
SRCS=$(OBJS:.o=.c)
diff --git a/etc/shaders/terrain.glsl b/etc/shaders/terrain.glsl
@@ -7,6 +7,7 @@ in vec3 normal;
uniform mat4 world;
uniform mat4 mvp;
+uniform mat4 depth_mvp;
uniform mat4 model_view;
uniform mat4 normal_matrix;
uniform vec3 camera_position;
@@ -16,6 +17,7 @@ uniform vec3 light_intensity;
flat out float v_light;
flat out vec3 v_color;
out vec3 v_ray;
+out vec4 shadow_coord;
const int nlands = 6;
@@ -58,6 +60,7 @@ void main()
{
vec4 v4_pos = vec4(position, 1.0);
gl_Position = mvp * v4_pos;
+ shadow_coord = depth_mvp * v4_pos;
vec3 color = land[0].xyz;
@@ -71,6 +74,7 @@ void main()
// v_color = vec3(0.2 + position.z*0.05, position.z*0.0095, position.z*0.0001) * 0.5;
// v_color = vec3(position.z, position.z, position.z) * 0.005;
+
v_color = hemispherical(color);
v_ray = camera_position - (world * v4_pos).xyz;
}
diff --git a/etc/shaders/test.f.glsl b/etc/shaders/test.f.glsl
@@ -4,14 +4,18 @@ precision mediump float;
flat in vec3 v_color;
in vec3 v_ray;
+in vec4 shadow_coord;
out vec4 fragmentColor;
uniform vec3 camera_position;
uniform bool fog_on;
uniform bool diffuse_on;
uniform vec3 light_intensity;
+uniform vec3 light_dir;
uniform mat4 normal_matrix;
+uniform sampler2D shadow_map;
+
vec3 apply_fog(in vec3 rgb, in float distance, in vec3 ray_orig, in vec3 ray_dir) {
const float b = 0.00026;
const float v = 1.0;
@@ -32,7 +36,7 @@ vec3 apply_fog(in vec3 rgb, in float distance, in vec3 ray_orig, in vec3 ray_dir
void main() {
vec3 light_position = vec3(2.0,1.0,5.0);
-
+ float visibility = 1.0;
vec3 color;
vec3 frag = v_color;
@@ -44,6 +48,16 @@ void main() {
else
color = frag;
+ float bias = 0.0009;
+ float shadow_map_z = texture(shadow_map, shadow_coord.xy).z;
+ if (light_dir.z > 0.0 && shadow_map_z < shadow_coord.z - bias) {
+ float factor = 1.0/dot(light_dir, vec3(0.0, 0.0, 1.0));
+ visibility = clamp(0.2 * factor, 0.5, 1.0);
+
+ }
+
+ color = color * visibility;
+
// fragmentColor = vec4(color + diffuse, 1.0);
fragmentColor = vec4(color, 1.0);
}
diff --git a/etc/shaders/vertex-color.glsl b/etc/shaders/vertex-color.glsl
@@ -9,6 +9,7 @@ in vec3 color;
uniform mat4 world;
uniform mat4 mvp;
+uniform mat4 depth_mvp;
uniform mat4 model_view;
uniform mat4 normal_matrix;
uniform vec3 camera_position;
@@ -19,6 +20,7 @@ flat out float v_light;
flat out vec3 v_color;
flat out vec3 v_normal;
out vec3 v_ray;
+out vec4 shadow_coord;
// TODO: includes
// #include "lighting.glsl"
@@ -54,6 +56,7 @@ void main()
{
vec4 v4_pos = vec4(position, 1.0);
gl_Position = mvp * v4_pos;
+ shadow_coord = depth_mvp * v4_pos;
v_color = hemispherical(color);
// v_normal = trans_normal.xyz;
diff --git a/src/entity.c b/src/entity.c
@@ -0,0 +1,10 @@
+
+#include "entity.h"
+#include "node.h"
+#include "model.h"
+
+
+void init_entity(struct entity *ent) {
+ node_init(&ent->node);
+ ent->casts_shadows = 0;
+}
diff --git a/src/entity.h b/src/entity.h
@@ -8,7 +8,10 @@
struct entity {
struct node node;
struct model model;
+ int casts_shadows;
};
+void init_entity(struct entity *);
+
#endif /* ENTITY_H */
diff --git a/src/fbo.c b/src/fbo.c
@@ -19,19 +19,12 @@ int fbo_attach_renderbuffer(struct fbo *fbo,
GLuint *rbo = &fbo->attachments[fbo->n_attachments++];
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
- check_gl();
glGenRenderbuffers(1, rbo);
- check_gl();
glBindRenderbuffer(GL_RENDERBUFFER, *rbo);
- check_gl();
glRenderbufferStorage(GL_RENDERBUFFER, internalformat, fbo->width, fbo->height);
- check_gl();
glBindRenderbuffer(GL_RENDERBUFFER, 0);
- check_gl();
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, *rbo);
- check_gl();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- check_gl();
return *rbo;
}
@@ -49,18 +42,16 @@ int fbo_attach_texture(struct fbo *fbo, GLint internalformat, GLint format,
GLuint *texture = &fbo->attachments[fbo->n_attachments++];
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
- check_gl();
glGenTextures(1, texture);
- check_gl();
glBindTexture(GL_TEXTURE_2D, *texture);
- check_gl();
glTexImage2D(GL_TEXTURE_2D, 0, internalformat, fbo->width, fbo->height, 0,
format, type, NULL);
- check_gl();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- check_gl();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- check_gl();
+ if (attachment == GL_DEPTH_ATTACHMENT) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, *texture,
0);
diff --git a/src/game.c b/src/game.c
@@ -7,6 +7,7 @@
#include "render.h"
#include "util.h"
#include "update.h"
+#include "entity.h"
#include <assert.h>
mat4 *cam_init = (float[16]){
@@ -35,6 +36,7 @@ void game_init(struct game *game, int width, int height) {
struct node *sun_camera = &res->sun_camera;
struct entity *player = &res->player;
struct terrain *terrain = &game->terrain;
+
mat4 *light_dir = res->light_dir;
mat4 *light_intensity = res->light_intensity;
int ok = 0;
@@ -53,11 +55,13 @@ void game_init(struct game *game, int width, int height) {
.scale = 1.0
};
+ int shadowmap_scale = 1.0;
+
// default ortho screenspace projection
- mat4_ortho(0.0, // left
- width, // right
- 0.0, // bottom
- height, // top
+ mat4_ortho(-width/2.0 * shadowmap_scale, // left
+ width/2.0 * shadowmap_scale, // right
+ -height/2.0 * shadowmap_scale, // bottom
+ height/2.0 * shadowmap_scale, // top
-10000.0, // near
10000.0, // far
res->proj_ortho
@@ -84,7 +88,7 @@ void game_init(struct game *game, int width, int height) {
// FBO STUFF
init_fbo(&res->shadow_buffer);
- resize_fbos(game, width, height);
+ resize_fbos(game, width * shadowmap_scale, height * shadowmap_scale);
// FBO STUFF END
@@ -92,13 +96,16 @@ void game_init(struct game *game, int width, int height) {
game->test_resources.diffuse_on = 0;
node_init(root);
- node_init(&player->node);
node_init(camera);
node_init(sun_camera);
- node_init(&terrain->entity.node);
+
+ init_entity(&terrain->entity);
+ init_entity(player);
+ player->casts_shadows = 1;
+ terrain->entity.casts_shadows = 0;
// player init
- ok = load_model(&player->model, "pirate-officer");
+ ok = load_model(&player->model, "ship");
assert(ok);
player->model.shading = SHADING_VERT_COLOR;
player->node.label = "player";
@@ -109,20 +116,16 @@ void game_init(struct game *game, int width, int height) {
node_attach(&player->node, root);
node_attach(camera, &player->node);
- node_attach(sun_camera, &player->node);
+ /* node_attach(sun_camera, root); */
quat_axis_angle(V3(1,0,0), -45, camera->orientation);
- quat_axis_angle(V3(1,0,0), 5, sun_camera->orientation);
- /* quat_axis_angle(V3(1,0,0), 0, sun_camera->orientation); */
- /* quat_axis_angle(V3(1,0,0), -45, alt_camera->orientation); */
+ /* quat_axis_angle(V3(1,0,0), -90, camera->orientation); */
+ /* node_rotate(sun_camera, V3(-7.5, 0, 0)); */
+ /* node_translate(sun_camera, V3(width/shadowmap_scale, 2000, 0)); */
node_translate(&player->node, V3(terrain->size/2.,terrain->size/2.,0.0));
/* vec3_scale(player->node.scale, 10.0, player->node.scale); */
- /* node_translate(alt_camera, V3(0,60,-100)); */
-
- node_translate(sun_camera, V3(width/2.0, height/2.0, 50));
-
node_rotate(camera, V3(100, 0, 0));
node_translate(camera, V3(0,-40,20));
/* node_recalc(camera); */
diff --git a/src/game.h b/src/game.h
@@ -32,6 +32,7 @@ struct resources {
GLint light_dir;
GLint light_intensity;
GLint mvp;
+ GLint depth_mvp;
GLint normal_matrix;
GLint view;
GLint fog_on;
diff --git a/src/main.c b/src/main.c
@@ -43,17 +43,21 @@ int main(void)
check_gl();
u32 last = SDL_GetTicks();
+ static float depth_mvp[MAT4_ELEMS];
+ mat4_id(depth_mvp);
struct render_config fbo_render_config = {
.draw_ui = 0,
.camera = game.test_resources.sun_camera.mat,
- .projection = game.test_resources.proj_ortho
+ .projection = game.test_resources.proj_ortho,
+ .depth_mvp = depth_mvp
};
struct render_config default_config = {
.draw_ui = 1,
.camera = game.test_resources.camera.mat,
- .projection = game.test_resources.proj_persp
+ .projection = game.test_resources.proj_persp,
+ .depth_mvp = depth_mvp
};
while (1) {
@@ -67,11 +71,7 @@ int main(void)
struct fbo *fbo = &game.test_resources.shadow_buffer;
check_fbo(fbo);
bind_fbo(fbo);
-
- /* glViewport( 0, 0, width, height ); */
-
- /* glDrawBuffer(GL_NONE); */
- check_gl();
+ /* glDrawBuffer(GL_NONE); */
render(&game, &fbo_render_config);
unbind_fbo(&game.test_resources.shadow_buffer);
render(&game, &default_config);
diff --git a/src/node.c b/src/node.c
@@ -115,6 +115,10 @@ void node_attach(struct node *node, struct node *to) {
to->children[to->n_children++] = node;
}
+float *node_pos(struct node *node) {
+ return &node->mat[M_X];
+}
+
void node_forward(struct node *node, float *dir) {
float movement[3] = {0};
float q[4] = {0};
diff --git a/src/node.h b/src/node.h
@@ -19,6 +19,7 @@ struct node {
struct node* children[MAX_NODE_CHILDREN];
};
+float *node_pos(struct node *node);
int node_recalc(struct node *root);
void node_attach(struct node *node, struct node *to);
void node_mark_for_recalc(struct node *node);
diff --git a/src/quat.c b/src/quat.c
@@ -26,6 +26,11 @@ void quat_multiply(quat *a, quat *b, quat *dest) {
dest[3] = aw * bw - ax * bx - ay * by - az * bz;
}
+/* void quat_from_vec3(float *vec3, quat *dest) { */
+/* float angle = atan2(vec3[0], vec3[2]); */
+/* dest[0] = 0; */
+/* dest[1] = 1 * sin(angle/2); */
+/* } */
void quat_axis_angle(float *axis, float angle, quat *dest) {
float half_angle = angle / 2.0;
diff --git a/src/render.c b/src/render.c
@@ -102,6 +102,9 @@ init_gl(struct resources *resources, int width, int height) {
resources->uniforms.camera_position =
glGetUniformLocation(handle, "camera_position");
+ resources->uniforms.depth_mvp =
+ glGetUniformLocation(handle, "depth_mvp");
+
resources->uniforms.light_intensity =
glGetUniformLocation(handle, "light_intensity");
@@ -164,6 +167,7 @@ void render (struct game *game, struct render_config *config) {
static float view_proj[MAT4_ELEMS] = { 0 };
static float normal_matrix[MAT4_ELEMS] = { 0 };
static float model_view[MAT4_ELEMS] = { 0 };
+ static float depth_bias[MAT4_ELEMS] = { 0 };
mat4_id(id);
mat4_id(model_view);
struct resources *res = &game->test_resources;
@@ -180,8 +184,12 @@ void render (struct game *game, struct render_config *config) {
, &game->test_resources.player
};
+ int is_shadow = config->draw_ui == 0;
+
for (size_t i = 0; i < ARRAY_SIZE(entities); ++i) {
struct entity *entity = entities[i];
+ if (is_shadow && !entity->casts_shadows)
+ continue;
// TODO this is a bit wonky, refactor this
if (i == 0)
glUseProgram(game->test_resources.terrain_program.handle);
@@ -192,6 +200,22 @@ void render (struct game *game, struct render_config *config) {
mat4_inverse(camera, view);
mat4_multiply(projection, view, view_proj);
+ // TODO: use something other than draw_ui to detect shadow map fbo phase
+ if (is_shadow) {
+ static const float bias_matrix[] = {
+ 0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 0.5, 0.0,
+ 0.5, 0.5, 0.5, 1.0
+ };
+
+ mat4_multiply(bias_matrix, view_proj, config->depth_mvp);
+ /* mat4_copy(view_proj, config->depth_mvp); */
+ }
+ else {
+ glUniformMatrix4fv(res->uniforms.depth_mvp, 1, 0, config->depth_mvp);
+ }
+
glUniform3f(res->uniforms.camera_position,
camera[M_X],
camera[M_Y],
@@ -207,6 +231,7 @@ void render (struct game *game, struct render_config *config) {
mat4_copy(entity->node.mat, model_view);
glUniformMatrix4fv(res->uniforms.mvp, 1, 0, mvp);
+ glUniformMatrix4fv(res->uniforms.depth_mvp, 1, 0, config->depth_mvp);
glUniformMatrix4fv(res->uniforms.model_view, 1, 0, model_view);
glUniformMatrix4fv(res->uniforms.world, 1, 0, entity->node.mat);
diff --git a/src/render.h b/src/render.h
@@ -9,6 +9,7 @@ struct render_config {
int draw_ui;
float *camera;
float *projection;
+ float *depth_mvp;
};
void init_gl(struct resources *resources, int width, int height);
diff --git a/src/update.c b/src/update.c
@@ -228,23 +228,28 @@ void resize_fbos(struct game *game, int width, int height) {
static void day_night_cycle(float n, struct resources *res) {
float darkest = 0.25;
float val = n;
- float roots = sin(val);
- float circle = fmod(val, TAU);
- float angle = circle/TAU;
- float intensity = angle <= 0.5
- ? clamp(roots, darkest, 1.0)
- : clamp(-roots * 0.4, darkest, 0.5);
+ float roots = vec3_dot(res->light_dir, V3(0.0, 0.0, 1.0));
+ float intensity = 1.0;//clamp(roots, darkest, 1.0);
+ float light_pos[3];
- /* printf("intensity %f(%f) angle %f hour %f n %f\n", roots, intensity, angle, */
- /* hour, n); */
+ /* float intensity = angle <= 0.5 */
+ /* ? clamp(roots, darkest, 1.0) */
+ /* : clamp(-roots * 0.4, darkest, 0.5); */
res->light_intensity[0] = intensity;
res->light_intensity[1] = intensity;
res->light_intensity[2] = intensity;
- res->light_dir[0] = -cos(val);
- res->light_dir[1] = -sin(val);
- res->light_dir[2] = 0.8;
+ res->light_dir[0] = 0.0;
+ res->light_dir[1] = sin(val);
+ res->light_dir[2] = cos(val);
+
+ /* printf("intensity %f(%f) n %f light_dir %f %f\n", roots, intensity, */
+ /* n, res->light_dir[0], res->light_dir[1]); */
+
+ vec3_add(&res->player.node.mat[M_X], res->light_dir, light_pos);
+
+ look_at(light_pos, node_pos(&res->player.node), V3(0, 0, 1.0), res->sun_camera.mat);
}
void update (struct game *game, u32 dt) {
@@ -308,4 +313,12 @@ void update (struct game *game, u32 dt) {
n += 0.00001f;
node_recalc(root);
+
+ /* look_at(&res->sun_camera.mat[M_X], */
+ /* &res->player.node.mat[M_X], */
+ /* V3(0,0,-1.0), */
+ /* res->sun_camera.mat */
+ /* ); */
+
+
}
diff --git a/src/util.c b/src/util.c
@@ -67,17 +67,21 @@ void look_at(vec3 *eye, vec3 *target, vec3 *up, mat4 *dest) {
dest[0] = x[0];
dest[1] = x[1];
dest[2] = x[2];
- /* dest[3] = -vec3_dot(x, eye); */
+ /* dest[3] = vec3_dot(x, eye); */
dest[4] = y[0];
dest[5] = y[1];
dest[6] = y[2];
- /* dest[7] = -vec3_dot(y, eye); */
+ /* dest[7] = vec3_dot(y, eye); */
dest[8] = z[0];
dest[9] = z[1];
dest[10] = z[2];
- /* dest[11] = -vec3_dot(z, eye); */
+ /* dest[11] = vec3_dot(z, eye); */
+
+ dest[12] = eye[0];
+ dest[13] = eye[1];
+ dest[14] = eye[2];
}
diff --git a/src/util.h b/src/util.h
@@ -18,6 +18,7 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+void look_at(vec3 *eye, vec3 *target, vec3 *up, mat4 *dest);
int clampi(int a, int mina, int maxa);
double clamp(double a, double mina, double maxa);
double max(double a, double b);
diff --git a/src/vec3.h b/src/vec3.h
@@ -5,6 +5,7 @@ typedef float vec3;
#define V_Y 1
#define V_Z 2
+vec3 *vec3_direction (vec3 *vec, vec3 *vec2, vec3 *dest);
vec3 *vec3_scale(vec3 *vec, float val, vec3 *dest);
vec3 *vec3_subtract(vec3 *vec, vec3 *vec2, vec3 *dest);
vec3 *vec3_cross (vec3 *vec, vec3 *vec2, vec3 *dest);