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 | ||
