initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
Import("env_modules")
env_lightmapper_rd = env_modules.Clone()
env_lightmapper_rd.GLSL_HEADER("lm_raster.glsl")
env_lightmapper_rd.GLSL_HEADER("lm_compute.glsl")
env_lightmapper_rd.GLSL_HEADER("lm_blendseams.glsl")
env_lightmapper_rd.Depends(Glob("*.glsl.gen.h"), ["lm_common_inc.glsl", "#glsl_builders.py"])
# Godot source files
env_lightmapper_rd.add_source_files(env.modules_sources, "*.cpp")

View File

@@ -0,0 +1,6 @@
def can_build(env, platform):
return env.editor_build
def configure(env):
pass

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,320 @@
/**************************************************************************/
/* lightmapper_rd.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 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. */
/**************************************************************************/
#pragma once
#include "core/templates/local_vector.h"
#include "scene/3d/lightmapper.h"
#include "scene/resources/mesh.h"
#include "servers/rendering/rendering_device.h"
class RDShaderFile;
class LightmapperRD : public Lightmapper {
GDCLASS(LightmapperRD, Lightmapper)
struct BakeParameters {
float world_size[3] = {};
float bias = 0.0;
float to_cell_offset[3] = {};
int32_t grid_size = 0;
float to_cell_size[3] = {};
uint32_t light_count = 0;
float env_transform[12] = {};
int32_t atlas_size[2] = {};
float exposure_normalization = 0.0f;
uint32_t bounces = 0;
float bounce_indirect_energy = 0.0f;
uint32_t shadowmask_light_idx = 0;
uint32_t transparency_rays = 0;
float supersampling_factor = 0.0f;
};
struct MeshInstance {
MeshData data;
int slice = 0;
Vector2i offset;
};
struct Light {
float position[3] = {};
uint32_t type = LIGHT_TYPE_DIRECTIONAL;
float direction[3] = {};
float energy = 0.0;
float color[3] = {};
float size = 0.0;
float range = 0.0;
float attenuation = 0.0;
float cos_spot_angle = 0.0;
float inv_spot_attenuation = 0.0;
float indirect_energy = 0.0;
float shadow_blur = 0.0;
uint32_t static_bake = 0;
uint32_t pad = 0;
bool operator<(const Light &p_light) const {
return type < p_light.type;
}
};
struct LightMetadata {
String name;
uint32_t type = LIGHT_TYPE_DIRECTIONAL;
bool operator<(const LightMetadata &p_light) const {
return type < p_light.type;
}
};
struct Vertex {
float position[3] = {};
float normal_z = 0.0;
float uv[2] = {};
float normal_xy[2] = {};
bool operator==(const Vertex &p_vtx) const {
return (position[0] == p_vtx.position[0]) &&
(position[1] == p_vtx.position[1]) &&
(position[2] == p_vtx.position[2]) &&
(uv[0] == p_vtx.uv[0]) &&
(uv[1] == p_vtx.uv[1]) &&
(normal_xy[0] == p_vtx.normal_xy[0]) &&
(normal_xy[1] == p_vtx.normal_xy[1]) &&
(normal_z == p_vtx.normal_z);
}
};
struct Edge {
Vector3 a;
Vector3 b;
Vector3 na;
Vector3 nb;
bool operator==(const Edge &p_seam) const {
return a == p_seam.a && b == p_seam.b && na == p_seam.na && nb == p_seam.nb;
}
Edge() {
}
Edge(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_na, const Vector3 &p_nb) {
a = p_a;
b = p_b;
na = p_na;
nb = p_nb;
}
};
struct Probe {
float position[4] = {};
};
Vector<Probe> probe_positions;
struct EdgeHash {
_FORCE_INLINE_ static uint32_t hash(const Edge &p_edge) {
uint32_t h = hash_murmur3_one_float(p_edge.a.x);
h = hash_murmur3_one_float(p_edge.a.y, h);
h = hash_murmur3_one_float(p_edge.a.z, h);
h = hash_murmur3_one_float(p_edge.b.x, h);
h = hash_murmur3_one_float(p_edge.b.y, h);
h = hash_murmur3_one_float(p_edge.b.z, h);
return h;
}
};
struct EdgeUV2 {
Vector2 a;
Vector2 b;
Vector2i indices;
bool operator==(const EdgeUV2 &p_uv2) const {
return a == p_uv2.a && b == p_uv2.b;
}
bool seam_found = false;
EdgeUV2(Vector2 p_a, Vector2 p_b, Vector2i p_indices) {
a = p_a;
b = p_b;
indices = p_indices;
}
EdgeUV2() {}
};
struct Seam {
Vector2i a;
Vector2i b;
uint32_t slice;
bool operator<(const Seam &p_seam) const {
return slice < p_seam.slice;
}
};
struct VertexHash {
_FORCE_INLINE_ static uint32_t hash(const Vertex &p_vtx) {
uint32_t h = hash_murmur3_one_float(p_vtx.position[0]);
h = hash_murmur3_one_float(p_vtx.position[1], h);
h = hash_murmur3_one_float(p_vtx.position[2], h);
h = hash_murmur3_one_float(p_vtx.uv[0], h);
h = hash_murmur3_one_float(p_vtx.uv[1], h);
h = hash_murmur3_one_float(p_vtx.normal_xy[0], h);
h = hash_murmur3_one_float(p_vtx.normal_xy[1], h);
h = hash_murmur3_one_float(p_vtx.normal_z, h);
return hash_fmix32(h);
}
};
struct Triangle {
uint32_t indices[3] = {};
uint32_t slice = 0;
float min_bounds[3] = {};
uint32_t cull_mode = 0;
float max_bounds[3] = {};
float pad1 = 0.0;
bool operator<(const Triangle &p_triangle) const {
return slice < p_triangle.slice;
}
};
struct ClusterAABB {
float min_bounds[3];
float pad0 = 0.0f;
float max_bounds[3];
float pad1 = 0.0f;
};
Vector<MeshInstance> mesh_instances;
Vector<Light> lights;
Vector<LightMetadata> light_metadata;
struct TriangleSort {
uint32_t cell_index = 0;
uint32_t triangle_index = 0;
AABB triangle_aabb;
bool operator<(const TriangleSort &p_triangle_sort) const {
return cell_index < p_triangle_sort.cell_index; //sorting by triangle index in this case makes no sense
}
};
template <int T>
struct TriangleSortAxis {
bool operator()(const TriangleSort &p_a, const TriangleSort &p_b) const {
return p_a.triangle_aabb.get_center()[T] < p_b.triangle_aabb.get_center()[T];
}
};
void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[3], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size);
void _sort_triangle_clusters(uint32_t p_cluster_size, uint32_t p_cluster_index, uint32_t p_index_start, uint32_t p_count, LocalVector<TriangleSort> &p_triangle_sort, LocalVector<ClusterAABB> &p_cluster_aabb);
struct RasterPushConstant {
float atlas_size[2] = {};
float uv_offset[2] = {};
float to_cell_size[3] = {};
uint32_t base_triangle = 0;
float to_cell_offset[3] = {};
float bias = 0.0;
int32_t grid_size[3] = {};
uint32_t pad2 = 0;
};
struct RasterSeamsPushConstant {
uint32_t base_index = 0;
uint32_t slice = 0;
float uv_offset[2] = {};
uint32_t debug = 0;
float blend = 0.0;
uint32_t pad[2] = {};
};
struct PushConstant {
uint32_t atlas_slice = 0;
uint32_t ray_count = 0;
uint32_t ray_from = 0;
uint32_t ray_to = 0;
uint32_t region_ofs[2] = {};
uint32_t probe_count = 0;
uint32_t denoiser_range = 0;
};
Vector<Ref<Image>> lightmap_textures;
Vector<Ref<Image>> shadowmask_textures;
Vector<Color> probe_values;
struct DilateParams {
uint32_t radius;
uint32_t pad[3];
};
struct DenoiseParams {
float spatial_bandwidth;
float light_bandwidth;
float albedo_bandwidth;
float normal_bandwidth;
int half_search_window;
float filter_strength;
float pad[2];
};
BakeError _blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, float p_supersampling_factor, BakeStepFunc p_step_function, void *p_bake_userdata);
void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, uint32_t p_cluster_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &lights_buffer, RID &r_triangle_indices_buffer, RID &r_cluster_indices_buffer, RID &r_cluster_aabbs_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata);
void _raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform);
BakeError _dilate(RenderingDevice *rd, Ref<RDShaderFile> &compute_shader, RID &compute_base_uniform_set, PushConstant &push_constant, RID &source_light_tex, RID &dest_light_tex, const Size2i &atlas_size, int atlas_slices);
BakeError _denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, RID p_unocclude_tex, float p_denoiser_strength, int p_denoiser_range, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function, void *p_bake_userdata);
BakeError _pack_l1(RenderingDevice *rd, Ref<RDShaderFile> &compute_shader, RID &compute_base_uniform_set, PushConstant &push_constant, RID &source_light_tex, RID &dest_light_tex, const Size2i &atlas_size, int atlas_slices);
Error _store_pfm(RenderingDevice *p_rd, RID p_atlas_tex, int p_index, const Size2i &p_atlas_size, const String &p_name, bool p_shadowmask);
Ref<Image> _read_pfm(const String &p_name, bool p_shadowmask);
BakeError _denoise_oidn(RenderingDevice *p_rd, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, bool p_shadowmask, const String &p_exe);
public:
virtual void add_mesh(const MeshData &p_mesh) override;
virtual void add_directional_light(const String &p_name, bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_energy, float p_angular_distance, float p_shadow_blur) override;
virtual void add_omni_light(const String &p_name, bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) override;
virtual void add_spot_light(const String &p_name, bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) override;
virtual void add_probe(const Vector3 &p_position) override;
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_bake_shadowmask, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, float p_exposure_normalization = 1.0, float p_supersampling_factor = 1.0f) override;
int get_bake_texture_count() const override;
Ref<Image> get_bake_texture(int p_index) const override;
int get_shadowmask_texture_count() const override;
Ref<Image> get_shadowmask_texture(int p_index) const override;
int get_bake_mesh_count() const override;
Variant get_bake_mesh_userdata(int p_index) const override;
Rect2 get_bake_mesh_uv_scale(int p_index) const override;
int get_bake_mesh_texture_slice(int p_index) const override;
int get_bake_probe_count() const override;
Vector3 get_bake_probe_point(int p_probe) const override;
Vector<Color> get_bake_probe_sh(int p_probe) const override;
LightmapperRD();
};

View File

@@ -0,0 +1,108 @@
#[versions]
lines = "#define MODE_LINES";
triangles = "#define MODE_TRIANGLES";
#[vertex]
#version 450
#VERSION_DEFINES
#include "lm_common_inc.glsl"
layout(push_constant, std430) uniform Params {
uint base_index;
uint slice;
vec2 uv_offset;
bool debug;
float blend;
uint pad[2];
}
params;
layout(location = 0) out vec3 uv_interp;
void main() {
#ifdef MODE_TRIANGLES
uint triangle_idx = params.base_index + gl_VertexIndex / 3;
uint triangle_subidx = gl_VertexIndex % 3;
vec2 uv;
if (triangle_subidx == 0) {
uv = vertices.data[triangles.data[triangle_idx].indices.x].uv;
} else if (triangle_subidx == 1) {
uv = vertices.data[triangles.data[triangle_idx].indices.y].uv;
} else {
uv = vertices.data[triangles.data[triangle_idx].indices.z].uv;
}
uv_interp = vec3(uv, float(params.slice));
gl_Position = vec4((uv + params.uv_offset) * 2.0 - 1.0, 0.0001, 1.0);
#endif
#ifdef MODE_LINES
uint seam_idx = params.base_index + gl_VertexIndex / 4;
uint seam_subidx = gl_VertexIndex % 4;
uint src_idx;
uint dst_idx;
if (seam_subidx == 0) {
src_idx = seams.data[seam_idx].b.x;
dst_idx = seams.data[seam_idx].a.x;
} else if (seam_subidx == 1) {
src_idx = seams.data[seam_idx].b.y;
dst_idx = seams.data[seam_idx].a.y;
} else if (seam_subidx == 2) {
src_idx = seams.data[seam_idx].a.x;
dst_idx = seams.data[seam_idx].b.x;
} else if (seam_subidx == 3) {
src_idx = seams.data[seam_idx].a.y;
dst_idx = seams.data[seam_idx].b.y;
}
vec2 src_uv = vertices.data[src_idx].uv;
vec2 dst_uv = vertices.data[dst_idx].uv + params.uv_offset;
uv_interp = vec3(src_uv, float(params.slice));
gl_Position = vec4(dst_uv * 2.0 - 1.0, 0.0001, 1.0);
#endif
}
#[fragment]
#version 450
#VERSION_DEFINES
#include "lm_common_inc.glsl"
layout(push_constant, std430) uniform Params {
uint base_index;
uint slice;
vec2 uv_offset;
bool debug;
float blend;
uint pad[2];
}
params;
layout(location = 0) in vec3 uv_interp;
layout(location = 0) out vec4 dst_color;
layout(set = 1, binding = 0) uniform texture2DArray src_color_tex;
void main() {
if (params.debug) {
#ifdef MODE_TRIANGLES
dst_color = vec4(1, 0, 1, 1);
#else
dst_color = vec4(1, 1, 0, 1);
#endif
} else {
vec4 src_color = textureLod(sampler2DArray(src_color_tex, linear_sampler), uv_interp, 0.0);
dst_color = vec4(src_color.rgb, params.blend); //mix
}
}

View File

@@ -0,0 +1,131 @@
layout(set = 0, binding = 0) uniform BakeParameters {
vec3 world_size;
float bias;
vec3 to_cell_offset;
int grid_size;
vec3 to_cell_size;
uint light_count;
mat3x4 env_transform;
ivec2 atlas_size;
float exposure_normalization;
uint bounces;
float bounce_indirect_energy;
int shadowmask_light_idx;
uint transparency_rays;
float supersampling_factor;
}
bake_params;
struct Vertex {
vec3 position;
float normal_z;
vec2 uv;
vec2 normal_xy;
};
layout(set = 0, binding = 1, std430) restrict readonly buffer Vertices {
Vertex data[];
}
vertices;
#define CULL_DISABLED 0
#define CULL_FRONT 1
#define CULL_BACK 2
struct Triangle {
uvec3 indices;
uint slice;
vec3 min_bounds;
uint cull_mode;
vec3 max_bounds;
uint pad1;
};
struct ClusterAABB {
vec3 min_bounds;
uint pad0;
vec3 max_bounds;
uint pad1;
};
layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles {
Triangle data[];
}
triangles;
layout(set = 0, binding = 3, std430) restrict readonly buffer TriangleIndices {
uint data[];
}
triangle_indices;
#define LIGHT_TYPE_DIRECTIONAL 0
#define LIGHT_TYPE_OMNI 1
#define LIGHT_TYPE_SPOT 2
struct Light {
vec3 position;
uint type;
vec3 direction;
float energy;
vec3 color;
float size;
float range;
float attenuation;
float cos_spot_angle;
float inv_spot_attenuation;
float indirect_energy;
float shadow_blur;
bool static_bake;
uint pad;
};
layout(set = 0, binding = 4, std430) restrict readonly buffer Lights {
Light data[];
}
lights;
struct Seam {
uvec2 a;
uvec2 b;
};
layout(set = 0, binding = 5, std430) restrict readonly buffer Seams {
Seam data[];
}
seams;
layout(set = 0, binding = 6, std430) restrict readonly buffer Probes {
vec4 data[];
}
probe_positions;
layout(set = 0, binding = 7) uniform utexture3D grid;
layout(set = 0, binding = 8) uniform texture2DArray albedo_tex;
layout(set = 0, binding = 9) uniform texture2DArray emission_tex;
layout(set = 0, binding = 10) uniform sampler linear_sampler;
layout(set = 0, binding = 11, std430) restrict readonly buffer ClusterIndices {
uint data[];
}
cluster_indices;
layout(set = 0, binding = 12, std430) restrict readonly buffer ClusterAABBs {
ClusterAABB data[];
}
cluster_aabbs;
// Fragment action constants
const uint FA_NONE = 0;
const uint FA_SMOOTHEN_POSITION = 1;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,167 @@
#[vertex]
#version 450
#VERSION_DEFINES
#include "lm_common_inc.glsl"
layout(location = 0) out vec3 vertex_interp;
layout(location = 1) out vec3 normal_interp;
layout(location = 2) out vec2 uv_interp;
layout(location = 3) out vec3 barycentric;
layout(location = 4) flat out uvec3 vertex_indices;
layout(location = 5) flat out vec3 face_normal;
layout(location = 6) flat out uint fragment_action;
layout(push_constant, std430) uniform Params {
vec2 atlas_size;
vec2 uv_offset;
vec3 to_cell_size;
uint base_triangle;
vec3 to_cell_offset;
float bias;
ivec3 grid_size;
uint pad2;
}
params;
void main() {
uint triangle_idx = params.base_triangle + gl_VertexIndex / 3;
uint triangle_subidx = gl_VertexIndex % 3;
vertex_indices = triangles.data[triangle_idx].indices;
uint vertex_idx;
if (triangle_subidx == 0) {
vertex_idx = vertex_indices.x;
barycentric = vec3(1, 0, 0);
} else if (triangle_subidx == 1) {
vertex_idx = vertex_indices.y;
barycentric = vec3(0, 1, 0);
} else {
vertex_idx = vertex_indices.z;
barycentric = vec3(0, 0, 1);
}
vertex_interp = vertices.data[vertex_idx].position;
uv_interp = vertices.data[vertex_idx].uv;
normal_interp = vec3(vertices.data[vertex_idx].normal_xy, vertices.data[vertex_idx].normal_z);
face_normal = -normalize(cross((vertices.data[vertex_indices.x].position - vertices.data[vertex_indices.y].position), (vertices.data[vertex_indices.x].position - vertices.data[vertex_indices.z].position)));
{
const float FLAT_THRESHOLD = 0.99;
const vec3 norm_a = vec3(vertices.data[vertex_indices.x].normal_xy, vertices.data[vertex_indices.x].normal_z);
const vec3 norm_b = vec3(vertices.data[vertex_indices.y].normal_xy, vertices.data[vertex_indices.y].normal_z);
const vec3 norm_c = vec3(vertices.data[vertex_indices.z].normal_xy, vertices.data[vertex_indices.z].normal_z);
fragment_action = (dot(norm_a, norm_b) < FLAT_THRESHOLD || dot(norm_a, norm_c) < FLAT_THRESHOLD || dot(norm_b, norm_c) < FLAT_THRESHOLD) ? FA_SMOOTHEN_POSITION : FA_NONE;
}
gl_Position = vec4((uv_interp + params.uv_offset) * 2.0 - 1.0, 0.0001, 1.0);
}
#[fragment]
#version 450
#VERSION_DEFINES
#include "lm_common_inc.glsl"
layout(push_constant, std430) uniform Params {
vec2 atlas_size;
vec2 uv_offset;
vec3 to_cell_size;
uint base_triangle;
vec3 to_cell_offset;
float bias;
ivec3 grid_size;
uint pad2;
}
params;
layout(location = 0) in vec3 vertex_interp;
layout(location = 1) in vec3 normal_interp;
layout(location = 2) in vec2 uv_interp;
layout(location = 3) in vec3 barycentric;
layout(location = 4) in flat uvec3 vertex_indices;
layout(location = 5) in flat vec3 face_normal;
layout(location = 6) in flat uint fragment_action;
layout(location = 0) out vec4 position;
layout(location = 1) out vec4 normal;
layout(location = 2) out vec4 unocclude;
void main() {
vec3 vertex_pos = vertex_interp;
if (fragment_action == FA_SMOOTHEN_POSITION) {
// smooth out vertex position by interpolating its projection in the 3 normal planes (normal plane is created by vertex pos and normal)
// because we don't want to interpolate inwards, normals found pointing inwards are pushed out.
vec3 pos_a = vertices.data[vertex_indices.x].position;
vec3 pos_b = vertices.data[vertex_indices.y].position;
vec3 pos_c = vertices.data[vertex_indices.z].position;
vec3 center = (pos_a + pos_b + pos_c) * 0.3333333;
vec3 norm_a = vec3(vertices.data[vertex_indices.x].normal_xy, vertices.data[vertex_indices.x].normal_z);
vec3 norm_b = vec3(vertices.data[vertex_indices.y].normal_xy, vertices.data[vertex_indices.y].normal_z);
vec3 norm_c = vec3(vertices.data[vertex_indices.z].normal_xy, vertices.data[vertex_indices.z].normal_z);
{
vec3 dir_a = normalize(pos_a - center);
float d_a = dot(dir_a, norm_a);
if (d_a < 0) {
//pointing inwards
norm_a = normalize(norm_a - dir_a * d_a);
}
}
{
vec3 dir_b = normalize(pos_b - center);
float d_b = dot(dir_b, norm_b);
if (d_b < 0) {
//pointing inwards
norm_b = normalize(norm_b - dir_b * d_b);
}
}
{
vec3 dir_c = normalize(pos_c - center);
float d_c = dot(dir_c, norm_c);
if (d_c < 0) {
//pointing inwards
norm_c = normalize(norm_c - dir_c * d_c);
}
}
float d_a = dot(norm_a, pos_a);
float d_b = dot(norm_b, pos_b);
float d_c = dot(norm_c, pos_c);
vec3 proj_a = vertex_pos - norm_a * (dot(norm_a, vertex_pos) - d_a);
vec3 proj_b = vertex_pos - norm_b * (dot(norm_b, vertex_pos) - d_b);
vec3 proj_c = vertex_pos - norm_c * (dot(norm_c, vertex_pos) - d_c);
vec3 smooth_position = proj_a * barycentric.x + proj_b * barycentric.y + proj_c * barycentric.z;
if (dot(face_normal, smooth_position) > dot(face_normal, vertex_pos)) { //only project outwards
vertex_pos = smooth_position;
}
}
{
// unocclusion technique based on:
// https://ndotl.wordpress.com/2018/08/29/baking-artifact-free-lightmaps/
/* compute texel size */
vec3 delta_uv = max(abs(dFdx(vertex_interp)), abs(dFdy(vertex_interp)));
float texel_size = max(delta_uv.x, max(delta_uv.y, delta_uv.z));
texel_size *= sqrt(2.0); //expand to unit box edge length (again, worst case)
unocclude.xyz = face_normal;
unocclude.w = texel_size;
//continued on lm_compute.glsl
}
position = vec4(vertex_pos, 1.0);
normal = vec4(normalize(normal_interp), 1.0);
}

View File

@@ -0,0 +1,74 @@
/**************************************************************************/
/* register_types.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 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. */
/**************************************************************************/
#include "register_types.h"
#include "lightmapper_rd.h"
#include "core/config/project_settings.h"
#include "scene/3d/lightmapper.h"
#ifndef _3D_DISABLED
static Lightmapper *create_lightmapper_rd() {
return memnew(LightmapperRD);
}
#endif
void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/low_quality_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 32);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/medium_quality_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 128);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/high_quality_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 512);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/ultra_quality_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 2048);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_performance/max_rays_per_pass", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 4);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_performance/region_size", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 512);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_performance/max_transparency_rays", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 8);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/low_quality_probe_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 64);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/medium_quality_probe_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 256);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/high_quality_probe_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 512);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 2048);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/bake_performance/max_rays_per_probe_pass", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lightmapping/denoising/denoiser", PROPERTY_HINT_ENUM, "JNLM,OIDN"), 0);
#ifndef _3D_DISABLED
GDREGISTER_CLASS(LightmapperRD);
Lightmapper::create_gpu = create_lightmapper_rd;
#endif
}
void uninitialize_lightmapper_rd_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
}

View File

@@ -0,0 +1,36 @@
/**************************************************************************/
/* register_types.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 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. */
/**************************************************************************/
#pragma once
#include "modules/register_module_types.h"
void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level);
void uninitialize_lightmapper_rd_module(ModuleInitializationLevel p_level);