]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/sky.c
Add trees
[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/scene.h"
9 #include "client/shader.h"
10 #include "client/sky.h"
11 #include "client/texture.h"
12 #include "day.h"
13
14 static struct
15 {
16         GLuint skybox_prog;
17         GLint skybox_loc_VP;
18         GLint skybox_loc_daylight;
19         GLuint skybox_textures[2];
20         Mesh *skybox_mesh;
21         GLuint sun_prog;
22         GLint sun_loc_MVP;
23         Texture *sun_texture;
24         Mesh *sun_mesh;
25         GLuint clouds_prog;
26         GLint clouds_loc_VP;
27         GLint clouds_loc_daylight;
28         Mesh *clouds_mesh;
29 } sky;
30
31 typedef struct
32 {
33         GLfloat x, y, z;
34 } __attribute__((packed)) VertexSunPosition;
35
36 typedef struct
37 {
38         GLfloat s, t;
39 } __attribute__((packed)) VertexSunTextureCoordinates;
40
41 typedef struct
42 {
43         VertexSunPosition position;
44         VertexSunTextureCoordinates textureCoordinates;
45 } __attribute__((packed)) VertexSun;
46
47 static VertexAttribute sun_vertex_attributes[2] = {
48         // position
49         {
50                 .type = GL_FLOAT,
51                 .length = 3,
52                 .size = sizeof(VertexSunPosition),
53         },
54         // textureCoordinates
55         {
56                 .type = GL_FLOAT,
57                 .length = 2,
58                 .size = sizeof(VertexSunTextureCoordinates),
59         },
60 };
61
62 static VertexLayout sun_vertex_layout = {
63         .attributes = sun_vertex_attributes,
64         .count = 2,
65         .size = sizeof(VertexSun),
66 };
67
68 static VertexSun sun_vertices[6] = {
69         {{-0.5, -0.5, +0.0}, {+0.0, +0.0}},
70         {{+0.5, -0.5, +0.0}, {+1.0, +0.0}},
71         {{+0.5, +0.5, +0.0}, {+1.0, +1.0}},
72         {{+0.5, +0.5, +0.0}, {+1.0, +1.0}},
73         {{-0.5, +0.5, +0.0}, {+0.0, +1.0}},
74         {{-0.5, -0.5, +0.0}, {+0.0, +0.0}},
75 };
76
77 typedef struct
78 {
79         GLfloat x, y, z;
80 } __attribute__((packed)) VertexSkyboxPosition;
81
82 typedef struct
83 {
84         VertexSkyboxPosition position;
85 } __attribute__((packed)) VertexSkybox;
86
87 static VertexAttribute skybox_vertex_attributes[2] = {
88         // position
89         {
90                 .type = GL_FLOAT,
91                 .length = 3,
92                 .size = sizeof(VertexSkyboxPosition),
93         },
94 };
95
96 static VertexLayout skybox_vertex_layout = {
97         .attributes = skybox_vertex_attributes,
98         .count = 1,
99         .size = sizeof(VertexSkybox),
100 };
101
102 static VertexSkybox skybox_vertices[6][6];
103 static VertexSkybox clouds_vertices[6][6];
104
105 bool sky_init()
106 {
107         // skybox
108
109         if (! shader_program_create(RESSOURCEPATH "shaders/sky/skybox", &sky.skybox_prog, NULL)) {
110                 fprintf(stderr, "Failed to create skybox shader program\n");
111                 return false;
112         }
113
114         sky.skybox_loc_VP = glGetUniformLocation(sky.skybox_prog, "VP");
115         sky.skybox_loc_daylight = glGetUniformLocation(sky.skybox_prog, "daylight");
116
117         sky.skybox_textures[0] = texture_create_cubemap(RESSOURCEPATH "textures/skybox/day");
118         sky.skybox_textures[1] = texture_create_cubemap(RESSOURCEPATH "textures/skybox/night");
119
120         GLint texture_indices[2];
121         for (GLint i = 0; i < 2; i++)
122                 texture_indices[i] = i;
123
124         glProgramUniform1iv(sky.skybox_prog, glGetUniformLocation(sky.skybox_prog, "textures"), 2, texture_indices);
125
126         for (int f = 0; f < 6; f++) {
127                 for (int v = 0; v < 6; v++) {
128                         skybox_vertices[f][v].position.x = cube_vertices[f][v].position.x;
129                         skybox_vertices[f][v].position.y = cube_vertices[f][v].position.y;
130                         skybox_vertices[f][v].position.z = cube_vertices[f][v].position.z;
131                 }
132         }
133
134         sky.skybox_mesh = mesh_create();
135         sky.skybox_mesh->textures = sky.skybox_textures;
136         sky.skybox_mesh->textures_count = 2;
137         sky.skybox_mesh->free_textures = false;
138         sky.skybox_mesh->vertices = skybox_vertices;
139         sky.skybox_mesh->vertices_count = 36;
140         sky.skybox_mesh->free_vertices = false;
141         sky.skybox_mesh->layout = &skybox_vertex_layout;
142
143         // sun
144
145         if (! shader_program_create(RESSOURCEPATH "shaders/sky/sun", &sky.sun_prog, NULL)) {
146                 fprintf(stderr, "Failed to create sun shader program\n");
147                 return false;
148         }
149
150         sky.sun_loc_MVP = glGetUniformLocation(sky.sun_prog, "MVP");
151
152         sky.sun_texture = texture_load(RESSOURCEPATH "textures/sun.png", false);
153
154         sky.sun_mesh = mesh_create();
155         sky.sun_mesh->textures = &sky.sun_texture->id;
156         sky.sun_mesh->textures_count = 1;
157         sky.sun_mesh->free_textures = false;
158         sky.sun_mesh->vertices = sun_vertices;
159         sky.sun_mesh->vertices_count = 6;
160         sky.sun_mesh->free_vertices = false;
161         sky.sun_mesh->layout = &sun_vertex_layout;
162
163         // clouds
164
165         if (! shader_program_create(RESSOURCEPATH "shaders/sky/clouds", &sky.clouds_prog, NULL)) {
166                 fprintf(stderr, "Failed to create clouds shader program\n");
167                 return false;
168         }
169
170         sky.clouds_loc_VP = glGetUniformLocation(sky.clouds_prog, "VP");
171         sky.clouds_loc_daylight = glGetUniformLocation(sky.clouds_prog, "daylight");
172
173         for (int f = 0; f < 6; f++) {
174                 for (int v = 0; v < 6; v++) {
175                         clouds_vertices[f][v].position.x = cube_vertices[f][v].position.x;
176                         clouds_vertices[f][v].position.y = fmax(cube_vertices[f][v].position.y, 0.0);
177                         clouds_vertices[f][v].position.z = cube_vertices[f][v].position.z;
178                 }
179         }
180
181         sky.clouds_mesh = mesh_create();
182         sky.clouds_mesh->textures = sky.skybox_textures;
183         sky.clouds_mesh->textures_count = 1;
184         sky.clouds_mesh->free_textures = false;
185         sky.clouds_mesh->vertices = clouds_vertices;
186         sky.clouds_mesh->vertices_count = 36;
187         sky.clouds_mesh->free_vertices = false;
188         sky.clouds_mesh->layout = &skybox_vertex_layout;
189
190         return true;
191 }
192
193 void sky_deinit()
194 {
195         glDeleteProgram(sky.skybox_prog);
196         glDeleteTextures(1, &sky.skybox_textures[0]);
197         glDeleteTextures(1, &sky.skybox_textures[1]);
198         mesh_delete(sky.skybox_mesh);
199
200         glDeleteProgram(sky.sun_prog);
201         mesh_delete(sky.sun_mesh);
202 }
203
204 #pragma GCC diagnostic push
205 #pragma GCC diagnostic ignored "-Wpedantic"
206 void sky_render()
207 {
208         f64 daylight = get_daylight();
209         f64 sun_angle = get_sun_angle();
210
211         vec3 sun_pos = {0.0f, cos(sun_angle), sin(sun_angle)};
212         vec3_norm(sun_pos, sun_pos);
213         vec3_scale(sun_pos, sun_pos, 5.0f);
214
215         mat4x4 model;
216         mat4x4_translate(model, sun_pos[0], sun_pos[1], sun_pos[2]);
217         mat4x4_rotate(model, model, 1.0f, 0.0f, 0.0f, sun_angle + M_PI / 2.0f);
218
219         mat4x4 view;
220         mat4x4_dup(view, camera.view);
221         view[3][0] = 0.0f;
222         view[3][1] = 0.0f;
223         view[3][2] = 0.0f;
224
225         mat4x4 VP;
226         mat4x4_mul(VP, scene.projection, view);
227
228         mat4x4 MVP;
229         mat4x4_mul(MVP, VP, model);
230
231         glDisable(GL_CULL_FACE);
232         glDepthFunc(GL_LEQUAL);
233
234         glUseProgram(sky.skybox_prog);
235         glUniformMatrix4fv(sky.skybox_loc_VP, 1, GL_FALSE, VP[0]);
236         glUniform1f(sky.skybox_loc_daylight, daylight);
237         mesh_render(sky.skybox_mesh);
238
239         glUseProgram(sky.sun_prog);
240         glUniformMatrix4fv(sky.sun_loc_MVP, 1, GL_FALSE, MVP[0]);
241         mesh_render(sky.sun_mesh);
242
243         glUseProgram(sky.clouds_prog);
244         glUniformMatrix4fv(sky.clouds_loc_VP, 1, GL_FALSE, VP[0]);
245         glUniform1f(sky.clouds_loc_daylight, daylight);
246         mesh_render(sky.clouds_mesh);
247
248         glDepthFunc(GL_LESS);
249         glEnable(GL_CULL_FACE);
250 }
251 #pragma GCC diagnostic pop