]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/sky.c
refactoring
[dragonblocks_alpha.git] / src / client / sky.c
1 #include <stdio.h>
2 #include <GL/glew.h>
3 #include <GL/gl.h>
4 #include "client/camera.h"
5 #include "client/client.h"
6 #include "client/cube.h"
7 #include "client/mesh.h"
8 #include "client/shader.h"
9 #include "client/sky.h"
10 #include "client/texture.h"
11 #include "client/window.h"
12 #include "day.h"
13
14 static GLuint sun_prog;
15 static GLint sun_loc_MVP;
16 static GLuint sun_texture;
17 typedef struct {
18         v3f32 position;
19         v2f32 textureCoordinates;
20 } __attribute__((packed)) SunVertex;
21 static Mesh sun_mesh = {
22         .layout = &(VertexLayout) {
23                 .attributes = (VertexAttribute[]) {
24                         {GL_FLOAT, 3, sizeof(v3f32)}, // position
25                         {GL_FLOAT, 2, sizeof(v2f32)}, // textureCoordinates
26                 },
27                 .count = 2,
28                 .size = sizeof(SunVertex),
29         },
30         .vao = 0,
31         .vbo = 0,
32         .data = (SunVertex[]) {
33                 {{-0.5, -0.5, +0.0}, {+0.0, +0.0}},
34                 {{+0.5, -0.5, +0.0}, {+1.0, +0.0}},
35                 {{+0.5, +0.5, +0.0}, {+1.0, +1.0}},
36                 {{+0.5, +0.5, +0.0}, {+1.0, +1.0}},
37                 {{-0.5, +0.5, +0.0}, {+0.0, +1.0}},
38                 {{-0.5, -0.5, +0.0}, {+0.0, +0.0}},
39         },
40         .count = 6,
41         .free_data = false,
42 };
43
44 static GLuint skybox_prog;
45 static GLint skybox_loc_VP;
46 static GLint skybox_loc_daylight;
47 static GLuint skybox_texture_day;
48 static GLuint skybox_texture_night;
49 typedef struct {
50         v3f32 position;
51 } __attribute__((packed)) SkyboxVertex;
52 static Mesh skybox_mesh = {
53         .layout = &(VertexLayout) {
54                 .attributes = (VertexAttribute[]) {
55                         {GL_FLOAT, 3, sizeof(v3f32)}, // position
56                 },
57                 .count = 1,
58                 .size = sizeof(SkyboxVertex),
59         },
60         .vao = 0,
61         .vbo = 0,
62         .data = NULL,
63         .count = 36,
64         .free_data = false,
65 };
66
67 static GLuint clouds_prog;
68 static GLint clouds_loc_VP;
69 static GLint clouds_loc_daylight;
70 static Mesh clouds_mesh;
71
72 bool sky_init()
73 {
74         clouds_mesh = skybox_mesh;
75         SkyboxVertex skybox_vertices[6][6], clouds_vertices[6][6];
76         for (int f = 0; f < 6; f++) {
77                 for (int v = 0; v < 6; v++) {
78                         skybox_vertices[f][v].position =
79                                 clouds_vertices[f][v].position =
80                                 cube_vertices[f][v].position;
81
82                         clouds_vertices[f][v].position.y = fmax(clouds_vertices[f][v].position.y, 0.0);
83                 }
84         }
85
86         // skybox
87
88         if (!shader_program_create(RESSOURCE_PATH "shaders/sky/skybox", &skybox_prog, NULL)) {
89                 fprintf(stderr, "[error] failed to create skybox shader program\n");
90                 return false;
91         }
92
93         glProgramUniform1iv(skybox_prog, glGetUniformLocation(skybox_prog, "textures"), 2, (GLint[]) {0, 1});
94
95         skybox_loc_VP = glGetUniformLocation(skybox_prog, "VP");
96         skybox_loc_daylight = glGetUniformLocation(skybox_prog, "daylight");
97         skybox_texture_day = texture_load_cubemap(RESSOURCE_PATH "textures/skybox/day")->txo;
98         skybox_texture_night = texture_load_cubemap(RESSOURCE_PATH "textures/skybox/night")->txo;
99         skybox_mesh.data = skybox_vertices;
100         mesh_upload(&skybox_mesh);
101
102         // sun
103
104         if (!shader_program_create(RESSOURCE_PATH "shaders/sky/sun", &sun_prog, NULL)) {
105                 fprintf(stderr, "[error] failed to create sun shader program\n");
106                 return false;
107         }
108
109         sun_loc_MVP = glGetUniformLocation(sun_prog, "MVP");
110         sun_texture = texture_load(RESSOURCE_PATH "textures/sun.png", false)->txo;
111
112         // clouds
113
114         if (!shader_program_create(RESSOURCE_PATH "shaders/sky/clouds", &clouds_prog, NULL)) {
115                 fprintf(stderr, "[error] failed to create clouds shader program\n");
116                 return false;
117         }
118
119         clouds_loc_VP = glGetUniformLocation(clouds_prog, "VP");
120         clouds_loc_daylight = glGetUniformLocation(clouds_prog, "daylight");
121         clouds_mesh.data = clouds_vertices;
122         mesh_upload(&clouds_mesh);
123
124         return true;
125 }
126
127 void sky_deinit()
128 {
129         glDeleteProgram(sun_prog);
130         mesh_destroy(&sun_mesh);
131
132         glDeleteProgram(skybox_prog);
133         mesh_destroy(&skybox_mesh);
134
135         glDeleteProgram(clouds_prog);
136         mesh_destroy(&clouds_mesh);
137 }
138
139 void sky_render()
140 {
141         f64 daylight = get_daylight();
142         f64 sun_angle = get_sun_angle();
143
144         vec3 sun_pos = {0.0f, cos(sun_angle), sin(sun_angle)};
145         vec3_norm(sun_pos, sun_pos);
146         vec3_scale(sun_pos, sun_pos, 5.0f);
147
148         mat4x4 model;
149         mat4x4_translate(model, sun_pos[0], sun_pos[1], sun_pos[2]);
150         mat4x4_rotate(model, model, 1.0f, 0.0f, 0.0f, sun_angle + M_PI / 2.0f);
151
152         mat4x4 view;
153         mat4x4_dup(view, camera.view);
154         view[3][0] = 0.0f;
155         view[3][1] = 0.0f;
156         view[3][2] = 0.0f;
157
158         mat4x4 vp;
159         mat4x4_mul(vp, window.projection, view);
160
161         mat4x4 mvp;
162         mat4x4_mul(mvp, vp, model);
163
164         glDisable(GL_CULL_FACE);
165         glDepthFunc(GL_LEQUAL);
166
167         glUseProgram(skybox_prog);
168         glUniformMatrix4fv(skybox_loc_VP, 1, GL_FALSE, vp[0]);
169         glUniform1f(skybox_loc_daylight, daylight);
170         glBindTextureUnit(0, skybox_texture_day);
171         glBindTextureUnit(1, skybox_texture_night);
172         mesh_render(&skybox_mesh);
173
174         glUseProgram(sun_prog);
175         glUniformMatrix4fv(sun_loc_MVP, 1, GL_FALSE, mvp[0]);
176         glBindTextureUnit(0, sun_texture);
177         mesh_render(&sun_mesh);
178
179         glUseProgram(clouds_prog);
180         glUniformMatrix4fv(clouds_loc_VP, 1, GL_FALSE, vp[0]);
181         glUniform1f(clouds_loc_daylight, daylight);
182         glBindTextureUnit(0, skybox_texture_day);
183         mesh_render(&clouds_mesh);
184
185         glDepthFunc(GL_LESS);
186         glEnable(GL_CULL_FACE);
187 }