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