summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gfx/include/gfx/util/skyquad.h20
-rw-r--r--gfx/src/util/skyquad.c83
-rw-r--r--gltfview/src/game.c62
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
4typedef struct Gfx Gfx; 4typedef struct Gfx Gfx;
5typedef struct Scene Scene; 5typedef struct Scene Scene;
6typedef struct SceneNode SceneNode;
6typedef struct SceneObject SceneObject; 7typedef struct SceneObject SceneObject;
7typedef struct Texture Texture; 8typedef struct Texture Texture;
8 9
9/// Create a skyquad. 10/// Create a skyquad.
10SceneObject* gfx_make_skyquad(Gfx*, Scene*, const Texture*); 11SceneObject* 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.
21SceneNode* 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
16SceneObject* gfx_make_skyquad(Gfx* gfx, Scene* scene, const Texture* texture) { 18SceneObject* 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.
90static 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
112cleanup:
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
122SceneNode* 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
154cleanup:
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.
59static Texture* load_environment_map(RenderBackend* render_backend) { 59static 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.
79static SceneNode* make_skyquad_object_node( 79static 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.
97static 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.
116static 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.
132static bool load_scene( 92static 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.
168static bool load_texture_debugger_scene(Game* game) { 128static bool load_texture_debugger_scene(Game* game) {
169 assert(game); 129 assert(game);
170 130