#pragma once #include #include "nanort.h" #include "nanosg.h" #include "tinyusdz.hh" namespace example { // GLES-like naming using vec3 = tinyusdz::value::float3; using vec2 = tinyusdz::value::float2; using mat2 = tinyusdz::value::matrix2f; struct AOV { size_t width; size_t height; std::vector rgb; // 3 x width x height std::vector shading_normal; // 3 x width x height std::vector geometric_normal; // 3 x width x height std::vector texcoords; // 2 x width x height void Resize(size_t w, size_t h) { width = w; height = h; rgb.resize(width * height * 3); memset(rgb.data(), 0, sizeof(float) * rgb.size()); shading_normal.resize(width * height * 3); memset(shading_normal.data(), 0, sizeof(float) * shading_normal.size()); geometric_normal.resize(width * height * 3); memset(geometric_normal.data(), 0, sizeof(float) * geometric_normal.size()); texcoords.resize(width * height * 2); memset(texcoords.data(), 0, sizeof(float) * texcoords.size()); } }; struct Camera { float eye[3] = {0.0f, 0.0f, 25.0f}; float up[3] = {0.0f, 1.0f, 0.0f}; float look_at[3] = {0.0f, 0.0f, 0.0f}; float quat[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float fov = 60.0f; // in degree }; template struct Buffer { size_t num_coords{1}; // e.g. 3 for vec3 type. std::vector data; }; // // Renderable Node class for NanoSG. Includes xform // struct DrawNode { std::array translation{0.0f, 0.0f, 0.0f}; std::array rotation{0.0f, 0.0f, 0.0f}; // euler rotation std::array scale{1.0f, 1.0f, 1.0f}; }; // // Renderable Mesh class for tinyusdz::GeomMesh // Mesh data is converted to triangle meshes. // struct DrawGeomMesh { DrawGeomMesh(const tinyusdz::GeomMesh *p) : ref_mesh(p) {} // Pointer to Reference GeomMesh. const tinyusdz::GeomMesh *ref_mesh = nullptr; /// /// Required accessor API for NanoSG /// const float *GetVertices() const { return nullptr; // TODO //return reinterpret_cast(ref_mesh->points.data()); } size_t GetVertexStrideBytes() const { return sizeof(float) * 3; } std::vector vertices; // vec3f std::vector facevertex_indices; // triangulated indices. 3 x num_faces std::vector facevarying_normals; // 3 x 3 x num_faces std::vector facevarying_texcoords; // 2 x 3 x num_faces // arbitrary primvars(including texcoords(float2)) std::vector> float_primvars; std::map float_primvars_map; // // arbitrary primvars in int type(e.g. texcoord indices(int3)) std::vector> int_primvars; std::map int_primvars_map; // int material_id{-1}; // per-geom material. index to `RenderScene::materials` nanort::BVHAccel accel; }; template struct UVReader { static_assert(std::is_same::value || std::is_same::value || std::is_same::value, "Unsupported type for UVReader"); int32_t st_id{-1}; // index to DrawGeomMesh::float_primvars int32_t indices_id{-1}; // index to DrawGeomMesh::int_primvars mat2 uv_transform; // Fetch interpolated UV coordinate T fetch_uv(size_t face_id, float varyu, float varyv); }; struct Texture { enum Channel { TEXTURE_CHANNEL_R, TEXTURE_CHANNEL_G, TEXTURE_CHANNEL_B, TEXTURE_CHANNEL_RGB, TEXTURE_CHANNEL_RGBA, }; UVReader uv_reader; int32_t image_id{-1}; // NOTE: for single channel(e.g. R), [0] will be filled for the return value. std::array fetch(size_t face_id, float varyu, float varyv, Channel channel); }; // https://graphics.pixar.com/usd/release/spec_usdpreviewsurface.html#texture-reader // https://learn.foundry.com/modo/901/content/help/pages/uving/udim_workflow.html // Up to 10 tiles for U direction. // Not sure there is an limitation for V direction. Anyway maximum tile id is // 9999. #if 0 static uint32_t GetUDIMTileId(uint32_t u, uint32_t v) { uint32_t uu = std::max(1u, std::min(10u, u+1)); // clamp U dir. return 1000 + v * 10 + uu; } #endif struct UDIMTexture { UVReader uv_reader; std::unordered_map images; // key: udim tile_id, value: image_id // NOTE: for single channel(e.g. R), [0] will be filled for the return value. std::array fetch(size_t face_id, float varyu, float varyv, Texture::Channel channel); }; // base color(fallback color) or Texture template struct ShaderParam { ShaderParam(const T &t) { value = t; } T value; int32_t texture_id{-1}; }; // UsdPreviewSurface struct PreviewSurfaceShader { bool useSpecularWorkFlow{false}; ShaderParam diffuseColor{{0.18f, 0.18f, 0.18f}}; ShaderParam metallic{0.0f}; ShaderParam roughness{0.5f}; ShaderParam clearcoat{0.0f}; ShaderParam clearcoatRoughness{0.01f}; ShaderParam opacity{1.0f}; ShaderParam opacityThreshold{0.0f}; ShaderParam ior{1.5f}; ShaderParam normal{{0.0f, 0.0f, 1.0f}}; ShaderParam displacement{0.0f}; ShaderParam occlusion{0.0f}; }; struct Material { PreviewSurfaceShader shader; }; // Simple LDR texture struct Image { std::vector image; int32_t width{-1}; int32_t height{-1}; int32_t channels{-1}; // e.g. 3 for RGB. }; class RenderScene { public: std::vector draw_meshes; std::vector materials; std::vector textures; std::vector images; std::vector> nodes; nanosg::Scene scene; // Convert meshes and build BVH bool Setup(); }; bool Render(const RenderScene &scene, const Camera &cam, AOV *output); // Render images for lines [start_y, end_y] // single-threaded. for webassembly. bool RenderLines(int start_y, int end_y, const RenderScene &scene, const Camera &cam, AOV *output); } // namespace example