#include "plugin.h" #include #include #include #include #include #include #include #include #include // Default texture to load if no texture is provided. static const char* DEFAULT_TEXTURE = "/assets/skybox/clouds1/clouds1_west.bmp"; // static const char* DEFAULT_TEXTURE = "/assets/checkerboard.jpg"; struct State { Scene* scene; SceneCamera* camera; }; bool init(Game* game, State** pp_state) { assert(game); assert(pp_state); State* state = calloc(1, sizeof(State)); if (!state) { goto cleanup; } // Usage: [texture file] const char* texture_file = game->argc > 1 ? game->argv[1] : DEFAULT_TEXTURE; RenderBackend* render_backend = gfx_get_render_backend(game->gfx); const Texture* texture = gfx_load_texture( game->gfx, &(LoadTextureCmd){ .origin = AssetFromFile, .type = LoadTexture, .filtering = LinearFiltering, .mipmaps = false, .data.texture.filepath = mstring_make(texture_file)}); if (!texture) { goto cleanup; } ShaderProgram* shader = gfx_make_view_texture_shader(render_backend); if (!shader) { goto cleanup; } Geometry* geometry = gfx_make_quad_11(render_backend); if (!geometry) { goto cleanup; } MaterialDesc material_desc = (MaterialDesc){.num_uniforms = 1}; material_desc.uniforms[0] = (ShaderUniform){ .type = UniformTexture, .value.texture = texture, .name = sstring_make("Texture")}; Material* material = gfx_make_material(&material_desc); if (!material) { goto cleanup; } const MeshDesc mesh_desc = (MeshDesc){.geometry = geometry, .material = material, .shader = shader}; Mesh* mesh = gfx_make_mesh(&mesh_desc); if (!mesh) { goto cleanup; } SceneObject* object = gfx_make_object(&(ObjectDesc){.num_meshes = 1, .meshes = {mesh}}); if (!object) { goto cleanup; } if (!(state->scene = gfx_make_scene())) { goto cleanup; } SceneNode* node = gfx_make_object_node(object); if (!node) { goto cleanup; } SceneNode* root = gfx_get_scene_root(state->scene); if (!root) { goto cleanup; } gfx_set_node_parent(node, root); if (!(state->camera = gfx_make_camera())) { goto cleanup; } *pp_state = state; return true; cleanup: shutdown(game, state); if (state) { free(state); } return false; } void shutdown(Game* game, State* state) { assert(game); if (state) { gfx_destroy_camera(&state->camera); gfx_destroy_scene(&state->scene); // State freed by plugin engine. } } void render(const Game* game, const State* state) { assert(game); assert(state); Renderer* renderer = gfx_get_renderer(game->gfx); gfx_render_scene( renderer, &(RenderSceneParams){ .mode = RenderDefault, .scene = state->scene, .camera = state->camera}); } void resize(Game* game, State* state, int width, int height) { assert(game); assert(state); const R fovy = 90 * TO_RAD; const R aspect = (R)width / (R)height; const R near = 0.1; const R far = 1000; const mat4 projection = mat4_perspective(fovy, aspect, near, far); Camera* camera = gfx_get_camera_camera(state->camera); camera->projection = projection; }