aboutsummaryrefslogtreecommitdiff
path: root/src/util/skyquad.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/skyquad.c')
-rw-r--r--src/util/skyquad.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/util/skyquad.c b/src/util/skyquad.c
new file mode 100644
index 0000000..08fa044
--- /dev/null
+++ b/src/util/skyquad.c
@@ -0,0 +1,161 @@
1#include <gfx/util/skyquad.h>
2
3#include <gfx/core.h>
4#include <gfx/gfx.h>
5#include <gfx/scene/light.h>
6#include <gfx/scene/material.h>
7#include <gfx/scene/mesh.h>
8#include <gfx/scene/node.h>
9#include <gfx/scene/object.h>
10#include <gfx/scene/scene.h>
11#include <gfx/util/geometry.h>
12#include <gfx/util/shader.h>
13
14#include <math/vec4.h>
15
16#include <assert.h>
17
18SceneObject* gfx_make_skyquad(GfxCore* gfxcore, const Texture* texture) {
19 assert(gfxcore);
20 assert(texture);
21
22 ShaderProgram* shader = 0;
23 Geometry* geometry = 0;
24 Material* material = 0;
25 Mesh* mesh = 0;
26 SceneObject* object = 0;
27
28 shader = gfx_make_skyquad_shader(gfxcore);
29 if (!shader) {
30 goto cleanup;
31 }
32
33 geometry = gfx_make_quad_11(gfxcore);
34 if (!geometry) {
35 goto cleanup;
36 }
37
38 MaterialDesc material_desc = (MaterialDesc){0};
39 material_desc.uniforms[0] = (ShaderUniform){
40 .type = UniformTexture,
41 .value.texture = texture,
42 .name = sstring_make("Skyquad")};
43 material_desc.num_uniforms = 1;
44 material = gfx_make_material(&material_desc);
45 if (!material) {
46 goto cleanup;
47 }
48
49 MeshDesc mesh_desc = (MeshDesc){0};
50 mesh_desc.geometry = geometry;
51 mesh_desc.material = material;
52 mesh_desc.shader = shader;
53 mesh = gfx_make_mesh(&mesh_desc);
54 if (!mesh) {
55 goto cleanup;
56 }
57
58 object = gfx_make_object(&(ObjectDesc){.num_meshes = 1, .meshes = {mesh}});
59 if (!object) {
60 goto cleanup;
61 }
62
63 return object;
64
65cleanup:
66 if (shader) {
67 gfx_destroy_shader_program(gfxcore, &shader);
68 }
69 if (geometry) {
70 gfx_destroy_geometry(gfxcore, &geometry);
71 }
72 if (material) {
73 gfx_destroy_material(&material);
74 }
75 if (mesh) {
76 gfx_destroy_mesh(&mesh);
77 }
78 if (object) {
79 gfx_destroy_object(&object);
80 }
81 return false;
82}
83
84/// Create an environment light node.
85static SceneNode* make_environment_light(
86 SceneNode* root, const Texture* environment_map) {
87 assert(root);
88 assert(environment_map);
89
90 Light* light = 0;
91 SceneNode* light_node = 0;
92
93 light = gfx_make_light(&(LightDesc){
94 .type = EnvironmentLightType,
95 .light = {(EnvironmentLightDesc){.environment_map = environment_map}}});
96 if (!light) {
97 goto cleanup;
98 }
99
100 light_node = gfx_make_light_node(light);
101 if (!light_node) {
102 goto cleanup;
103 }
104 gfx_set_node_parent(light_node, root);
105
106 return light_node;
107
108cleanup:
109 if (light) {
110 gfx_destroy_light(&light);
111 }
112 if (light_node) {
113 gfx_destroy_node(&light_node);
114 }
115 return 0;
116}
117
118SceneNode* gfx_setup_skyquad(
119 GfxCore* gfxcore, SceneNode* root, const Texture* environment_map) {
120 assert(gfxcore);
121 assert(root);
122 assert(environment_map);
123
124 SceneObject* skyquad_object = 0;
125 SceneNode* object_node = 0;
126 SceneNode* light_node = 0;
127
128 // Create the skyquad object.
129 skyquad_object = gfx_make_skyquad(gfxcore, environment_map);
130 if (!skyquad_object) {
131 goto cleanup;
132 }
133
134 // Create an object node to render the skyquad in the background.
135 object_node = gfx_make_object_node(skyquad_object);
136 if (!object_node) {
137 goto cleanup;
138 }
139 gfx_set_node_parent(object_node, root);
140
141 // Create an environment light node under which to root objects affected by
142 // the skyquad.
143 light_node = make_environment_light(root, environment_map);
144 if (!light_node) {
145 goto cleanup;
146 }
147
148 return light_node;
149
150cleanup:
151 if (skyquad_object) {
152 gfx_destroy_object(&skyquad_object);
153 }
154 if (object_node) {
155 gfx_destroy_node(&object_node);
156 }
157 if (light_node) {
158 gfx_destroy_node(&light_node);
159 }
160 return 0;
161}