diff options
-rw-r--r-- | gfx/include/gfx/util/skyquad.h | 20 | ||||
-rw-r--r-- | gfx/src/util/skyquad.c | 83 | ||||
-rw-r--r-- | gltfview/src/game.c | 62 |
3 files changed, 108 insertions, 57 deletions
diff --git a/gfx/include/gfx/util/skyquad.h b/gfx/include/gfx/util/skyquad.h index 88c9c41..f792a13 100644 --- a/gfx/include/gfx/util/skyquad.h +++ b/gfx/include/gfx/util/skyquad.h | |||
@@ -1,10 +1,22 @@ | |||
1 | /// A skyquad is like a skybox but with a single quad. | 1 | /// A skyquad is like a skybox but with a single quad. |
2 | #pragma once | 2 | #pragma once |
3 | 3 | ||
4 | typedef struct Gfx Gfx; | 4 | typedef struct Gfx Gfx; |
5 | typedef struct Scene Scene; | 5 | typedef struct Scene Scene; |
6 | typedef struct SceneNode SceneNode; | ||
6 | typedef struct SceneObject SceneObject; | 7 | typedef struct SceneObject SceneObject; |
7 | typedef struct Texture Texture; | 8 | typedef struct Texture Texture; |
8 | 9 | ||
9 | /// Create a skyquad. | 10 | /// Create a skyquad. |
10 | SceneObject* gfx_make_skyquad(Gfx*, Scene*, const Texture*); | 11 | SceneObject* gfx_make_skyquad(Gfx*, const Texture*); |
12 | |||
13 | /// Set up a skyquad in the scene. | ||
14 | /// | ||
15 | /// This function adds two scene nodes under the given root node: | ||
16 | /// - An object node to render the skyquad in the background. | ||
17 | /// - A light node to light up other objects with the skyquad. | ||
18 | /// | ||
19 | /// Return the light node under which objects affected by the light can be | ||
20 | /// rooted. | ||
21 | SceneNode* gfx_setup_skyquad( | ||
22 | Gfx*, SceneNode* root, const Texture* environment_map); | ||
diff --git a/gfx/src/util/skyquad.c b/gfx/src/util/skyquad.c index 2461f8c..b59d7b9 100644 --- a/gfx/src/util/skyquad.c +++ b/gfx/src/util/skyquad.c | |||
@@ -2,8 +2,10 @@ | |||
2 | 2 | ||
3 | #include <gfx/gfx.h> | 3 | #include <gfx/gfx.h> |
4 | #include <gfx/render_backend.h> | 4 | #include <gfx/render_backend.h> |
5 | #include <gfx/scene/light.h> | ||
5 | #include <gfx/scene/material.h> | 6 | #include <gfx/scene/material.h> |
6 | #include <gfx/scene/mesh.h> | 7 | #include <gfx/scene/mesh.h> |
8 | #include <gfx/scene/node.h> | ||
7 | #include <gfx/scene/object.h> | 9 | #include <gfx/scene/object.h> |
8 | #include <gfx/scene/scene.h> | 10 | #include <gfx/scene/scene.h> |
9 | #include <gfx/util/geometry.h> | 11 | #include <gfx/util/geometry.h> |
@@ -13,9 +15,8 @@ | |||
13 | 15 | ||
14 | #include <assert.h> | 16 | #include <assert.h> |
15 | 17 | ||
16 | SceneObject* gfx_make_skyquad(Gfx* gfx, Scene* scene, const Texture* texture) { | 18 | SceneObject* gfx_make_skyquad(Gfx* gfx, const Texture* texture) { |
17 | assert(gfx); | 19 | assert(gfx); |
18 | assert(scene); | ||
19 | assert(texture); | 20 | assert(texture); |
20 | 21 | ||
21 | // TODO: pass RenderBackend directly? | 22 | // TODO: pass RenderBackend directly? |
@@ -84,3 +85,81 @@ cleanup: | |||
84 | } | 85 | } |
85 | return false; | 86 | return false; |
86 | } | 87 | } |
88 | |||
89 | /// Create an environment light node. | ||
90 | static SceneNode* make_environment_light( | ||
91 | SceneNode* root, const Texture* environment_light) { | ||
92 | assert(root); | ||
93 | |||
94 | Light* light = 0; | ||
95 | SceneNode* light_node = 0; | ||
96 | |||
97 | light = gfx_make_light(&(LightDesc){ | ||
98 | .type = EnvironmentLightType, | ||
99 | .light = (EnvironmentLightDesc){.environment_map = environment_light}}); | ||
100 | if (!light) { | ||
101 | goto cleanup; | ||
102 | } | ||
103 | |||
104 | light_node = gfx_make_light_node(light); | ||
105 | if (!light_node) { | ||
106 | goto cleanup; | ||
107 | } | ||
108 | gfx_set_node_parent(light_node, root); | ||
109 | |||
110 | return light_node; | ||
111 | |||
112 | cleanup: | ||
113 | if (light) { | ||
114 | gfx_destroy_light(&light); | ||
115 | } | ||
116 | if (light_node) { | ||
117 | gfx_destroy_node(&light_node); | ||
118 | } | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | SceneNode* gfx_setup_skyquad( | ||
123 | Gfx* gfx, SceneNode* root, const Texture* environment_map) { | ||
124 | assert(gfx); | ||
125 | assert(root); | ||
126 | assert(environment_map); | ||
127 | |||
128 | SceneObject* skyquad_object = 0; | ||
129 | SceneNode* object_node = 0; | ||
130 | SceneNode* light_node = 0; | ||
131 | |||
132 | // Create the skyquad object. | ||
133 | skyquad_object = gfx_make_skyquad(gfx, environment_map); | ||
134 | if (!skyquad_object) { | ||
135 | goto cleanup; | ||
136 | } | ||
137 | |||
138 | // Create an object node to render the skyquad in the background. | ||
139 | object_node = gfx_make_object_node(skyquad_object); | ||
140 | if (!object_node) { | ||
141 | goto cleanup; | ||
142 | } | ||
143 | gfx_set_node_parent(object_node, root); | ||
144 | |||
145 | // Create an environment light node under which to root objects affected by | ||
146 | // the skyquad. | ||
147 | light_node = make_environment_light(root, environment_map); | ||
148 | if (!light_node) { | ||
149 | goto cleanup; | ||
150 | } | ||
151 | |||
152 | return light_node; | ||
153 | |||
154 | cleanup: | ||
155 | if (skyquad_object) { | ||
156 | gfx_destroy_object(&skyquad_object); | ||
157 | } | ||
158 | if (object_node) { | ||
159 | gfx_destroy_node(&object_node); | ||
160 | } | ||
161 | if (light_node) { | ||
162 | gfx_destroy_node(&light_node); | ||
163 | } | ||
164 | return 0; | ||
165 | } | ||
diff --git a/gltfview/src/game.c b/gltfview/src/game.c index bd474d6..54e498b 100644 --- a/gltfview/src/game.c +++ b/gltfview/src/game.c | |||
@@ -55,7 +55,7 @@ static ShaderProgram* load_shader( | |||
55 | return shader; | 55 | return shader; |
56 | } | 56 | } |
57 | 57 | ||
58 | /// Loads the skyquad texture. | 58 | /// Load the skyquad texture. |
59 | static Texture* load_environment_map(RenderBackend* render_backend) { | 59 | static Texture* load_environment_map(RenderBackend* render_backend) { |
60 | return gfx_load_texture( | 60 | return gfx_load_texture( |
61 | render_backend, | 61 | render_backend, |
@@ -75,60 +75,20 @@ static Texture* load_environment_map(RenderBackend* render_backend) { | |||
75 | }); | 75 | }); |
76 | } | 76 | } |
77 | 77 | ||
78 | /// Creates an object to render the skyquad in the background. | 78 | /// Load the skyquad and return the environment light node. |
79 | static SceneNode* make_skyquad_object_node( | 79 | static SceneNode* load_skyquad(Game* game) { |
80 | Game* game, const Texture* environment_map) { | ||
81 | assert(game); | 80 | assert(game); |
82 | 81 | ||
83 | SceneObject* skyquad_object = | ||
84 | gfx_make_skyquad(game->gfx, game->scene, environment_map); | ||
85 | if (!skyquad_object) { | ||
86 | return 0; | ||
87 | } | ||
88 | SceneNode* skyquad_node = gfx_make_object_node(skyquad_object); | ||
89 | if (!skyquad_node) { | ||
90 | return 0; | ||
91 | } | ||
92 | gfx_set_node_parent(skyquad_node, gfx_get_scene_root(game->scene)); | ||
93 | return skyquad_node; | ||
94 | } | ||
95 | |||
96 | /// Creates an environment light. | ||
97 | static SceneNode* make_environment_light( | ||
98 | Game* game, const Texture* environment_light) { | ||
99 | assert(game); | ||
100 | |||
101 | Light* light = gfx_make_light(&(LightDesc){ | ||
102 | .type = EnvironmentLightType, | ||
103 | .light = (EnvironmentLightDesc){.environment_map = environment_light}}); | ||
104 | if (!light) { | ||
105 | return 0; | ||
106 | } | ||
107 | SceneNode* light_node = gfx_make_light_node(light); | ||
108 | if (!light_node) { | ||
109 | return 0; | ||
110 | } | ||
111 | gfx_set_node_parent(light_node, gfx_get_scene_root(game->scene)); | ||
112 | return light_node; | ||
113 | } | ||
114 | |||
115 | /// Loads the skyquad and returns the SceneNode with the environment light. | ||
116 | static bool load_skyquad(Game* game, SceneNode** node) { | ||
117 | assert(game); | ||
118 | assert(node); | ||
119 | |||
120 | Texture* environment_map = load_environment_map(game->render_backend); | 82 | Texture* environment_map = load_environment_map(game->render_backend); |
121 | if (!environment_map) { | 83 | if (!environment_map) { |
122 | return false; | 84 | return 0; |
123 | } | 85 | } |
124 | 86 | ||
125 | make_skyquad_object_node(game, environment_map); | 87 | return gfx_setup_skyquad( |
126 | *node = make_environment_light(game, environment_map); | 88 | game->gfx, gfx_get_scene_root(game->scene), environment_map); |
127 | |||
128 | return true; | ||
129 | } | 89 | } |
130 | 90 | ||
131 | /// Loads the 3D scene. | 91 | /// Load the 3D scene. |
132 | static bool load_scene( | 92 | static bool load_scene( |
133 | Game* game, const char* scene_filepath, const char* view_mode) { | 93 | Game* game, const char* scene_filepath, const char* view_mode) { |
134 | assert(game); | 94 | assert(game); |
@@ -143,8 +103,8 @@ static bool load_scene( | |||
143 | // Damaged helmet. | 103 | // Damaged helmet. |
144 | spatial3_set_position(&camera->spatial, vec3_make(0, 0, 2)); | 104 | spatial3_set_position(&camera->spatial, vec3_make(0, 0, 2)); |
145 | 105 | ||
146 | SceneNode* sky_node = 0; | 106 | SceneNode* sky_light_node = load_skyquad(game); |
147 | if (!load_skyquad(game, &sky_node) || !sky_node) { | 107 | if (!sky_light_node) { |
148 | return false; | 108 | return false; |
149 | } | 109 | } |
150 | 110 | ||
@@ -155,7 +115,7 @@ static bool load_scene( | |||
155 | // } | 115 | // } |
156 | 116 | ||
157 | if (!gfx_load_scene( | 117 | if (!gfx_load_scene( |
158 | game->gfx, sky_node, | 118 | game->gfx, sky_light_node, |
159 | &(LoadSceneCmd){ | 119 | &(LoadSceneCmd){ |
160 | .origin = SceneFromFile, .filepath = scene_filepath})) { | 120 | .origin = SceneFromFile, .filepath = scene_filepath})) { |
161 | return false; | 121 | return false; |
@@ -164,7 +124,7 @@ static bool load_scene( | |||
164 | return true; | 124 | return true; |
165 | } | 125 | } |
166 | 126 | ||
167 | /// Loads a scene for debugging textures. | 127 | /// Load a scene for debugging textures. |
168 | static bool load_texture_debugger_scene(Game* game) { | 128 | static bool load_texture_debugger_scene(Game* game) { |
169 | assert(game); | 129 | assert(game); |
170 | 130 | ||