/*************************************************************************/ /* baked_light_baker.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #ifndef BAKED_LIGHT_BAKER_H #define BAKED_LIGHT_BAKER_H #include "scene/3d/baked_light_instance.h" #include "scene/3d/light.h" #include "scene/3d/mesh_instance.h" #include "os/thread.h" #if 0 class BakedLightBaker { public: enum { ATTENUATION_CURVE_LEN=256, OCTANT_POOL_CHUNK=1000000 }; /* struct OctantLight { double accum[8][3]; }; */ struct Octant { bool leaf; AABB aabb; uint16_t texture_x; uint16_t texture_y; int sampler_ofs; float normal_accum[8][3]; double full_accum[3]; int parent; union { struct { int next_leaf; float offset[3]; int bake_neighbour; bool first_neighbour; double light_accum[8][3]; }; int children[8]; }; }; struct OctantHash { int next; uint32_t hash; uint64_t value; }; struct MeshTexture { Vector<uint8_t> tex; int tex_w,tex_h; _FORCE_INLINE_ void get_color(const Vector2& p_uv,Color& ret) { if (tex_w && tex_h) { int x = Math::fast_ftoi(Math::fposmod(p_uv.x,1.0)*tex_w); int y = Math::fast_ftoi(Math::fposmod(p_uv.y,1.0)*tex_w); x=CLAMP(x,0,tex_w-1); y=CLAMP(y,0,tex_h-1); const uint8_t*ptr = &tex[(y*tex_w+x)*4]; ret.r*=ptr[0]/255.0; ret.g*=ptr[1]/255.0; ret.b*=ptr[2]/255.0; ret.a*=ptr[3]/255.0; } } }; struct Param { Color color; MeshTexture*tex; _FORCE_INLINE_ Color get_color(const Vector2& p_uv) { Color ret=color; if (tex) tex->get_color(p_uv,ret); return ret; } }; struct MeshMaterial { Param diffuse; Param specular; Param emission; }; struct Triangle { AABB aabb; Vector3 vertices[3]; Vector2 uvs[3]; Vector2 bake_uvs[3]; Vector3 normals[3]; MeshMaterial *material; int baked_texture; _FORCE_INLINE_ Vector2 get_uv(const Vector3& p_pos) { Vector3 v0 = vertices[1] - vertices[0]; Vector3 v1 = vertices[2] - vertices[0]; Vector3 v2 = p_pos - vertices[0]; float d00 = v0.dot( v0); float d01 = v0.dot( v1); float d11 = v1.dot( v1); float d20 = v2.dot( v0); float d21 = v2.dot( v1); float denom = (d00 * d11 - d01 * d01); if (denom==0) return uvs[0]; float v = (d11 * d20 - d01 * d21) / denom; float w = (d00 * d21 - d01 * d20) / denom; float u = 1.0f - v - w; return uvs[0]*u + uvs[1]*v + uvs[2]*w; } _FORCE_INLINE_ void get_uv_and_normal(const Vector3& p_pos,Vector2& r_uv,Vector3& r_normal) { Vector3 v0 = vertices[1] - vertices[0]; Vector3 v1 = vertices[2] - vertices[0]; Vector3 v2 = p_pos - vertices[0]; float d00 = v0.dot( v0); float d01 = v0.dot( v1); float d11 = v1.dot( v1); float d20 = v2.dot( v0); float d21 = v2.dot( v1); float denom = (d00 * d11 - d01 * d01); if (denom==0) { r_normal=normals[0]; r_uv=uvs[0]; return; } float v = (d11 * d20 - d01 * d21) / denom; float w = (d00 * d21 - d01 * d20) / denom; float u = 1.0f - v - w; r_uv=uvs[0]*u + uvs[1]*v + uvs[2]*w; r_normal=(normals[0]*u+normals[1]*v+normals[2]*w).normalized(); } }; struct BVH { AABB aabb; Vector3 center; Triangle *leaf; BVH*children[2]; }; struct BVHCmpX { bool operator()(const BVH* p_left, const BVH* p_right) const { return p_left->center.x < p_right->center.x; } }; struct BVHCmpY { bool operator()(const BVH* p_left, const BVH* p_right) const { return p_left->center.y < p_right->center.y; } }; struct BVHCmpZ { bool operator()(const BVH* p_left, const BVH* p_right) const { return p_left->center.z < p_right->center.z; } }; struct BakeTexture { Vector<uint8_t> data; int width,height; }; struct LightData { VS::LightType type; Vector3 pos; Vector3 up; Vector3 left; Vector3 dir; Color diffuse; Color specular; float energy; float length; int rays_thrown; bool bake_shadow; float radius; float attenuation; float spot_angle; float darkening; float spot_attenuation; float area; float constant; bool bake_direct; Vector<float> attenuation_table; }; Vector<LightData> lights; List<MeshMaterial> materials; List<MeshTexture> textures; AABB octree_aabb; Vector<Octant> octant_pool; int octant_pool_size; BVH*bvh; Vector<Triangle> triangles; Vector<BakeTexture> baked_textures; Transform base_inv; int leaf_list; int octree_depth; int bvh_depth; int cell_count; uint32_t *ray_stack; BVH **bvh_stack; uint32_t *octant_stack; uint32_t *octantptr_stack; struct ThreadStack { uint32_t *octant_stack; uint32_t *octantptr_stack; uint32_t *ray_stack; BVH **bvh_stack; }; Map<Vector3,Vector3> endpoint_normal; Map<Vector3,uint64_t> endpoint_normal_bits; float cell_size; float plot_size; //multiplied by cell size float octree_extra_margin; int max_bounces; int64_t total_rays; bool use_diffuse; bool use_specular; bool use_translucency; bool linear_color; int baked_octree_texture_w; int baked_octree_texture_h; int baked_light_texture_w; int baked_light_texture_h; int lattice_size; float edge_damp; float normal_damp; float tint; float ao_radius; float ao_strength; bool paused; bool baking; bool first_bake_to_map; Map<Ref<Material>,MeshMaterial*> mat_map; Map<Ref<Texture>,MeshTexture*> tex_map; MeshTexture* _get_mat_tex(const Ref<Texture>& p_tex); void _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform,int p_baked_texture=-1); void _parse_geometry(Node* p_node); BVH* _parse_bvh(BVH** p_children,int p_size,int p_depth,int& max_depth); void _make_bvh(); void _make_octree(); void _make_octree_texture(); void _octree_insert(int p_octant, Triangle* p_triangle, int p_depth); _FORCE_INLINE_ void _plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma); void _free_bvh(BVH* p_bvh); void _fix_lights(); Ref<BakedLight> baked_light; //void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,int p_octant=0); void _plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Color& p_tint_light,bool p_only_full,const Plane& p_plane); //void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light); float _throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false); float total_light_area; Vector<Thread*> threads; bool bake_thread_exit; static void _bake_thread_func(void *arg); void _start_thread(); void _stop_thread(); public: void throw_rays(ThreadStack &thread_stack, int p_amount); double get_normalization(int p_light_idx) const; double get_modifier(int p_light_idx) const; void bake(const Ref<BakedLight>& p_light,Node *p_base); bool is_baking(); void set_pause(bool p_pause); bool is_paused(); uint64_t get_rays_thrown() { return total_rays; } Error transfer_to_lightmaps(); void update_octree_sampler(PoolVector<int> &p_sampler); void update_octree_images(PoolVector<uint8_t> &p_octree,PoolVector<uint8_t> &p_light); Ref<BakedLight> get_baked_light() { return baked_light; } void clear(); BakedLightBaker(); ~BakedLightBaker(); }; #endif // BAKED_LIGHT_BAKER_H #endif