Several fixes to 3D rendering, and multimesh implementation.

This commit is contained in:
Juan Linietsky 2019-09-14 00:37:42 -03:00
parent 9d7b7f931b
commit 6deffa62fb
36 changed files with 1212 additions and 222 deletions

View file

@ -404,6 +404,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
if (!p_no_cache) {
_remove_from_loading_map(local_path);
}
print_verbose("Failed loading resource: " + path);
return RES();
}
if (!p_no_cache)

View file

@ -3969,7 +3969,7 @@ RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Po
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID());
Buffer buffer;
Error err = _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
Error err = _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
ERR_FAIL_COND_V(err != OK, RID());
if (p_data.size()) {
@ -4600,6 +4600,8 @@ PoolVector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
buffer = index_buffer_owner.getornull(p_buffer);
} else if (texture_buffer_owner.owns(p_buffer)) {
buffer = &texture_buffer_owner.getornull(p_buffer)->buffer;
} else if (storage_buffer_owner.owns(p_buffer)) {
buffer = storage_buffer_owner.getornull(p_buffer);
} else {
ERR_FAIL_V_MSG(PoolVector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving.");
}

View file

@ -304,6 +304,8 @@ void DocData::generate(bool p_basic_types) {
}
}
//used to track uninitialized values using valgrind
//print_line("getting default value for " + String(name) + "." + String(E->get().name));
if (default_value_valid && default_value.get_type() != Variant::OBJECT) {
prop.default_value = default_value.get_construct_string().replace("\n", "");
}

View file

@ -115,8 +115,8 @@ void ResourceImporterTexture::update_imports() {
changed = true;
}
if (E->get().flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d"))) {
cf->set_value("params", "detect_3d", false);
if (E->get().flags & MAKE_3D_FLAG && bool(cf->get_value("params", "usage/detect_3d"))) {
cf->set_value("params", "usage/detect_3d", false);
cf->set_value("params", "compress/mode", 2);
cf->set_value("params", "format/mipmaps", true);
changed = true;
@ -214,9 +214,10 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/invert_color"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/HDR_as_SRGB"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "stream"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "detect_3d"), p_preset == PRESET_DETECT));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/mipmap_limit", PROPERTY_HINT_RANGE, "0,999,1"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "usage/stream"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "usage/detect_3d"), p_preset == PRESET_DETECT));
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 1.0));
}
@ -385,8 +386,8 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
bool fix_alpha_border = p_options["process/fix_alpha_border"];
bool premult_alpha = p_options["process/premult_alpha"];
bool invert_color = p_options["process/invert_color"];
bool stream = p_options["stream"];
int size_limit = p_options["size_limit"];
bool stream = p_options["usage/stream"];
int size_limit = p_options["process/size_limit"];
bool hdr_as_srgb = p_options["process/HDR_as_SRGB"];
int normal = p_options["compress/normal_map"];
float scale = p_options["svg/scale"];
@ -443,7 +444,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
image->unlock();
}
bool detect_3d = p_options["detect_3d"];
bool detect_3d = p_options["usage/detect_3d"];
bool detect_roughness = roughness == 0;
bool detect_normal = normal == 0;
bool force_normal = normal == 1;

View file

@ -172,7 +172,7 @@ void MultiMeshEditor::_populate() {
int instance_count = populate_amount->get_value();
multimesh->set_transform_format(MultiMesh::TRANSFORM_3D);
multimesh->set_color_format(MultiMesh::COLOR_NONE);
multimesh->set_use_colors(false);
multimesh->set_instance_count(instance_count);
float _tilt_random = populate_tilt_random->get_value();

View file

@ -514,7 +514,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
Octant::MultimeshInstance mmi;
RID mm = VS::get_singleton()->multimesh_create();
VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE);
VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D);
VS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid());
int idx = 0;

View file

@ -59,7 +59,7 @@ void CPUParticles2D::set_amount(int p_amount) {
}
particle_data.resize((8 + 4 + 1) * p_amount);
VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_2D, VS::MULTIMESH_COLOR_8BIT, VS::MULTIMESH_CUSTOM_DATA_FLOAT);
VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_2D, true, true);
particle_order.resize(p_amount);
}
@ -1077,7 +1077,7 @@ void CPUParticles2D::_update_render_thread() {
update_mutex->lock();
#endif
VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data);
VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data);
#ifndef NO_THREADS
update_mutex->unlock();

View file

@ -73,7 +73,7 @@ void CPUParticles::set_amount(int p_amount) {
}
particle_data.resize((12 + 4 + 1) * p_amount);
VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_8BIT, VS::MULTIMESH_CUSTOM_DATA_FLOAT);
VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, true, true);
particle_order.resize(p_amount);
}
@ -1144,7 +1144,7 @@ void CPUParticles::_update_render_thread() {
update_mutex->lock();
#endif
if (can_update) {
VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data);
VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data);
can_update = false; //wait for next time
}

View file

@ -364,9 +364,8 @@ VehicleWheel::VehicleWheel() {
steers = false;
engine_traction = false;
m_steering = real_t(0.);
//m_engineForce = real_t(0.);
m_engineForce = real_t(0.);
m_rotation = real_t(0.);
m_deltaRotation = real_t(0.);
m_brake = real_t(0.);

View file

@ -2339,7 +2339,7 @@ Ref<MultiMesh> VoxelLightBaker::create_debug_multimesh(DebugMode p_mode) {
mm.instance();
mm->set_transform_format(MultiMesh::TRANSFORM_3D);
mm->set_color_format(MultiMesh::COLOR_8BIT);
mm->set_use_colors(true);
mm->set_instance_count(leaf_voxel_count);
Ref<ArrayMesh> mesh;

View file

@ -300,7 +300,7 @@ void Viewport::_notification(int p_what) {
//3D
PhysicsServer::get_singleton()->space_set_debug_contacts(find_world()->get_space(), get_tree()->get_collision_debug_contact_count());
contact_3d_debug_multimesh = VisualServer::get_singleton()->multimesh_create();
VisualServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_8BIT);
VisualServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), VS::MULTIMESH_TRANSFORM_3D, true);
VisualServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0);
VisualServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid());
contact_3d_debug_instance = VisualServer::get_singleton()->instance_create();

View file

@ -937,6 +937,20 @@ float Environment::get_fog_height_curve() const {
return fog_height_curve;
}
#ifndef DISABLE_DEPRECATED
bool Environment::_set(const StringName &p_name, const Variant &p_value) {
if (p_name == "background_sky") {
set_sky(p_value);
return true;
} else if (p_name == "background_sky_custom_fov") {
set_sky_custom_fov(p_value);
return true;
} else {
return false;
}
}
#endif
void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background);

View file

@ -194,6 +194,9 @@ private:
protected:
static void _bind_methods();
virtual void _validate_property(PropertyInfo &property) const;
#ifndef DISABLE_DEPRECATED
bool _set(const StringName &p_name, const Variant &p_value);
#endif
public:
void set_background(BGMode p_bg);

View file

@ -590,6 +590,89 @@ Vector<Ref<Shape> > Mesh::convex_decompose() const {
Mesh::Mesh() {
}
static PoolVector<uint8_t> _fix_array_compatibility(const PoolVector<uint8_t> &p_src, uint32_t p_format, uint32_t p_elements) {
bool vertex_16bit = p_format & ((1 << (Mesh::ARRAY_VERTEX + Mesh::ARRAY_COMPRESS_BASE)));
bool bone_32_bits = (p_format & Mesh::ARRAY_FORMAT_BONES) && !(p_format & (Mesh::ARRAY_COMPRESS_INDEX << 2));
print_line("convert vertex16: " + itos(vertex_16bit) + " bone 32 " + itos(bone_32_bits));
if (!vertex_16bit && !bone_32_bits) {
return p_src;
}
bool vertex_2d = (p_format & (Mesh::ARRAY_COMPRESS_INDEX << 1));
uint32_t src_stride = p_src.size() / p_elements;
uint32_t dst_stride = src_stride + (vertex_16bit ? 4 : 0) - (bone_32_bits ? 16 : 0);
PoolVector<uint8_t> ret;
ret.resize(dst_stride * p_elements);
{
PoolVector<uint8_t>::Write w = ret.write();
PoolVector<uint8_t>::Read r = p_src.read();
for (uint32_t i = 0; i < p_elements; i++) {
uint32_t remaining = src_stride;
const uint8_t *src = (const uint8_t *)(r.ptr() + src_stride * i);
uint8_t *dst = (uint8_t *)(w.ptr() + dst_stride * i);
if (!vertex_2d) { //3D
if (vertex_16bit) {
float *dstw = (float *)dst;
const uint16_t *srcr = (const uint16_t *)src;
dstw[0] = Math::half_to_float(srcr[0]);
dstw[1] = Math::half_to_float(srcr[1]);
dstw[2] = Math::half_to_float(srcr[2]);
remaining -= 8;
src += 8;
} else {
src += 12;
remaining -= 12;
}
dst += 12;
} else {
if (vertex_16bit) {
float *dstw = (float *)dst;
const uint16_t *srcr = (const uint16_t *)src;
dstw[0] = Math::half_to_float(srcr[0]);
dstw[1] = Math::half_to_float(srcr[1]);
remaining -= 4;
src += 4;
} else {
src += 8;
remaining -= 8;
}
dst += 8;
}
if (bone_32_bits) {
const uint32_t *src_bones = (const uint32_t *)&src[remaining - 32];
const float *src_weights = (const float *)&src[remaining - 16];
uint16_t *dstw = (uint16_t *)&dst[remaining - 32];
dstw[0] = src_bones[0];
dstw[1] = src_bones[1];
dstw[2] = src_bones[2];
dstw[3] = src_bones[3];
dstw[4] = CLAMP(src_weights[0] * 65535, 0, 65535); //16bits unorm
dstw[5] = CLAMP(src_weights[1] * 65535, 0, 65535);
dstw[6] = CLAMP(src_weights[2] * 65535, 0, 65535);
dstw[7] = CLAMP(src_weights[3] * 65535, 0, 65535);
remaining -= 32;
}
for (uint32_t j = 0; j < remaining; j++) {
dst[j] = src[j];
}
}
}
return ret;
}
bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
String sname = p_name;
@ -624,11 +707,11 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
#ifdef ENABLE_DEPRECATED
#ifndef DISABLE_DEPRECATED
if (!sname.begins_with("surfaces"))
return false;
WARN_DEPRECATED("Mesh uses old surface format, which is deprecated (and loads slower). Consider re-importing or re-saving the scene.");
WARN_DEPRECATED_MSG("Mesh uses old surface format, which is deprecated (and loads slower). Consider re-importing or re-saving the scene.");
int idx = sname.get_slicec('/', 1).to_int();
String what = sname.get_slicec('/', 2);
@ -640,12 +723,13 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(!d.has("primitive"), false);
if (d.has("arrays")) {
//old format
//oldest format (2.x)
ERR_FAIL_COND_V(!d.has("morph_arrays"), false);
add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]);
} else if (d.has("array_data")) {
print_line("array data (old style");
//older format (3.x)
PoolVector<uint8_t> array_data = d["array_data"];
PoolVector<uint8_t> array_index_data;
if (d.has("array_index_data"))
@ -655,16 +739,24 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
uint32_t format = d["format"];
uint32_t primitive = d["primitive"];
if (primitive > PRIMITIVE_LINE_STRIP) {
primitive--; //line loop was deprecated, so it's not supported and indices go down by one
}
if (primitive > PRIMITIVE_TRIANGLE_STRIP) {
primitive = PRIMITIVE_TRIANGLE_STRIP; //fan is no longer supported
}
uint32_t primitive_remap[7] = {
PRIMITIVE_POINTS,
PRIMITIVE_LINES,
PRIMITIVE_LINE_STRIP,
PRIMITIVE_LINES,
PRIMITIVE_TRIANGLES,
PRIMITIVE_TRIANGLE_STRIP,
PRIMITIVE_TRIANGLE_STRIP
};
primitive = primitive_remap[primitive]; //compatibility
ERR_FAIL_COND_V(!d.has("vertex_count"), false);
int vertex_count = d["vertex_count"];
array_data = _fix_array_compatibility(array_data, format, vertex_count);
int index_count = 0;
if (d.has("index_count"))
index_count = d["index_count"];
@ -675,10 +767,15 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
Array blend_shape_data = d["blend_shape_data"];
for (int i = 0; i < blend_shape_data.size(); i++) {
PoolVector<uint8_t> shape = blend_shape_data[i];
shape = _fix_array_compatibility(shape, format, vertex_count);
blend_shapes.push_back(shape);
}
}
//clear unused flags
format &= ~((1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE)) | (ARRAY_COMPRESS_INDEX << 2));
ERR_FAIL_COND_V(!d.has("aabb"), false);
AABB aabb = d["aabb"];

View file

@ -31,6 +31,8 @@
#include "multimesh.h"
#include "servers/visual_server.h"
#ifndef DISABLE_DEPRECATED
void MultiMesh::_set_transform_array(const PoolVector<Vector3> &p_array) {
if (transform_format != TRANSFORM_3D)
return;
@ -146,7 +148,7 @@ void MultiMesh::_set_color_array(const PoolVector<Color> &p_array) {
PoolVector<Color> MultiMesh::_get_color_array() const {
if (instance_count == 0 || color_format == COLOR_NONE)
if (instance_count == 0 || !use_colors)
return PoolVector<Color>();
PoolVector<Color> colors;
@ -178,7 +180,7 @@ void MultiMesh::_set_custom_data_array(const PoolVector<Color> &p_array) {
PoolVector<Color> MultiMesh::_get_custom_data_array() const {
if (instance_count == 0 || custom_data_format == CUSTOM_DATA_NONE)
if (instance_count == 0 || !use_custom_data)
return PoolVector<Color>();
PoolVector<Color> custom_datas;
@ -191,6 +193,16 @@ PoolVector<Color> MultiMesh::_get_custom_data_array() const {
return custom_datas;
}
#endif
void MultiMesh::set_buffer(const PoolVector<float> &p_buffer) {
VS::get_singleton()->multimesh_set_buffer(multimesh, p_buffer);
}
PoolVector<float> MultiMesh::get_buffer() const {
return VS::get_singleton()->multimesh_get_buffer(multimesh);
}
void MultiMesh::set_mesh(const Ref<Mesh> &p_mesh) {
mesh = p_mesh;
@ -207,7 +219,7 @@ Ref<Mesh> MultiMesh::get_mesh() const {
void MultiMesh::set_instance_count(int p_count) {
ERR_FAIL_COND(p_count < 0);
VisualServer::get_singleton()->multimesh_allocate(multimesh, p_count, VS::MultimeshTransformFormat(transform_format), VS::MultimeshColorFormat(color_format), VS::MultimeshCustomDataFormat(custom_data_format));
VisualServer::get_singleton()->multimesh_allocate(multimesh, p_count, VS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data);
instance_count = p_count;
}
int MultiMesh::get_instance_count() const {
@ -217,6 +229,7 @@ int MultiMesh::get_instance_count() const {
void MultiMesh::set_visible_instance_count(int p_count) {
ERR_FAIL_COND(p_count < -1);
ERR_FAIL_COND(p_count > instance_count);
VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, p_count);
visible_instance_count = p_count;
}
@ -263,11 +276,6 @@ Color MultiMesh::get_instance_custom_data(int p_instance) const {
return VisualServer::get_singleton()->multimesh_instance_get_custom_data(multimesh, p_instance);
}
void MultiMesh::set_as_bulk_array(const PoolVector<float> &p_array) {
VisualServer::get_singleton()->multimesh_set_as_bulk_array(multimesh, p_array);
}
AABB MultiMesh::get_aabb() const {
return VisualServer::get_singleton()->multimesh_get_aabb(multimesh);
@ -278,26 +286,22 @@ RID MultiMesh::get_rid() const {
return multimesh;
}
void MultiMesh::set_color_format(ColorFormat p_color_format) {
void MultiMesh::set_use_colors(bool p_enable) {
ERR_FAIL_COND(instance_count > 0);
color_format = p_color_format;
use_colors = p_enable;
}
MultiMesh::ColorFormat MultiMesh::get_color_format() const {
return color_format;
bool MultiMesh::is_using_colors() const {
return use_colors;
}
void MultiMesh::set_custom_data_format(CustomDataFormat p_custom_data_format) {
void MultiMesh::set_use_custom_data(bool p_enable) {
ERR_FAIL_COND(instance_count > 0);
custom_data_format = p_custom_data_format;
use_custom_data = p_enable;
}
MultiMesh::CustomDataFormat MultiMesh::get_custom_data_format() const {
return custom_data_format;
bool MultiMesh::is_using_custom_data() const {
return use_custom_data;
}
void MultiMesh::set_transform_format(TransformFormat p_transform_format) {
@ -314,10 +318,10 @@ void MultiMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MultiMesh::set_mesh);
ClassDB::bind_method(D_METHOD("get_mesh"), &MultiMesh::get_mesh);
ClassDB::bind_method(D_METHOD("set_color_format", "format"), &MultiMesh::set_color_format);
ClassDB::bind_method(D_METHOD("get_color_format"), &MultiMesh::get_color_format);
ClassDB::bind_method(D_METHOD("set_custom_data_format", "format"), &MultiMesh::set_custom_data_format);
ClassDB::bind_method(D_METHOD("get_custom_data_format"), &MultiMesh::get_custom_data_format);
ClassDB::bind_method(D_METHOD("set_use_colors", "enable"), &MultiMesh::set_use_colors);
ClassDB::bind_method(D_METHOD("is_using_colors"), &MultiMesh::is_using_colors);
ClassDB::bind_method(D_METHOD("set_use_custom_data", "enable"), &MultiMesh::set_use_custom_data);
ClassDB::bind_method(D_METHOD("is_using_custom_data"), &MultiMesh::is_using_custom_data);
ClassDB::bind_method(D_METHOD("set_transform_format", "format"), &MultiMesh::set_transform_format);
ClassDB::bind_method(D_METHOD("get_transform_format"), &MultiMesh::get_transform_format);
@ -333,9 +337,22 @@ void MultiMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_instance_color", "instance"), &MultiMesh::get_instance_color);
ClassDB::bind_method(D_METHOD("set_instance_custom_data", "instance", "custom_data"), &MultiMesh::set_instance_custom_data);
ClassDB::bind_method(D_METHOD("get_instance_custom_data", "instance"), &MultiMesh::get_instance_custom_data);
ClassDB::bind_method(D_METHOD("set_as_bulk_array", "array"), &MultiMesh::set_as_bulk_array);
ClassDB::bind_method(D_METHOD("get_aabb"), &MultiMesh::get_aabb);
ClassDB::bind_method(D_METHOD("get_buffer"), &MultiMesh::get_buffer);
ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &MultiMesh::set_buffer);
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_format", PROPERTY_HINT_ENUM, "2D,3D"), "set_transform_format", "get_transform_format");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_colors"), "set_use_colors", "is_using_colors");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_custom_data"), "set_use_custom_data", "is_using_custom_data");
ADD_PROPERTY(PropertyInfo(Variant::INT, "instance_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"), "set_instance_count", "get_instance_count");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_instance_count", PROPERTY_HINT_RANGE, "-1,16384,1,or_greater"), "set_visible_instance_count", "get_visible_instance_count");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::POOL_REAL_ARRAY, "buffer", PROPERTY_HINT_NONE), "set_buffer", "get_buffer");
#ifndef DISABLE_DEPRECATED
//kept for compatibility
ClassDB::bind_method(D_METHOD("_set_transform_array"), &MultiMesh::_set_transform_array);
ClassDB::bind_method(D_METHOD("_get_transform_array"), &MultiMesh::_get_transform_array);
ClassDB::bind_method(D_METHOD("_set_transform_2d_array"), &MultiMesh::_set_transform_2d_array);
@ -345,34 +362,20 @@ void MultiMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_custom_data_array"), &MultiMesh::_set_custom_data_array);
ClassDB::bind_method(D_METHOD("_get_custom_data_array"), &MultiMesh::_get_custom_data_array);
ADD_PROPERTY(PropertyInfo(Variant::INT, "color_format", PROPERTY_HINT_ENUM, "None,Byte,Float"), "set_color_format", "get_color_format");
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_format", PROPERTY_HINT_ENUM, "2D,3D"), "set_transform_format", "get_transform_format");
ADD_PROPERTY(PropertyInfo(Variant::INT, "custom_data_format", PROPERTY_HINT_ENUM, "None,Byte,Float"), "set_custom_data_format", "get_custom_data_format");
ADD_PROPERTY(PropertyInfo(Variant::INT, "instance_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"), "set_instance_count", "get_instance_count");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_instance_count", PROPERTY_HINT_RANGE, "-1,16384,1,or_greater"), "set_visible_instance_count", "get_visible_instance_count");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "transform_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_transform_array", "_get_transform_array");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "transform_2d_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_transform_2d_array", "_get_transform_2d_array");
ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "color_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_color_array", "_get_color_array");
ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "custom_data_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_custom_data_array", "_get_custom_data_array");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "transform_array", PROPERTY_HINT_NONE, "", 0), "_set_transform_array", "_get_transform_array");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "transform_2d_array", PROPERTY_HINT_NONE, "", 0), "_set_transform_2d_array", "_get_transform_2d_array");
ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "color_array", PROPERTY_HINT_NONE, "", 0), "_set_color_array", "_get_color_array");
ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "custom_data_array", PROPERTY_HINT_NONE, "", 0), "_set_custom_data_array", "_get_custom_data_array");
#endif
BIND_ENUM_CONSTANT(TRANSFORM_2D);
BIND_ENUM_CONSTANT(TRANSFORM_3D);
BIND_ENUM_CONSTANT(COLOR_NONE);
BIND_ENUM_CONSTANT(COLOR_8BIT);
BIND_ENUM_CONSTANT(COLOR_FLOAT);
BIND_ENUM_CONSTANT(CUSTOM_DATA_NONE);
BIND_ENUM_CONSTANT(CUSTOM_DATA_8BIT);
BIND_ENUM_CONSTANT(CUSTOM_DATA_FLOAT);
}
MultiMesh::MultiMesh() {
multimesh = VisualServer::get_singleton()->multimesh_create();
color_format = COLOR_NONE;
custom_data_format = CUSTOM_DATA_NONE;
use_colors = false;
use_custom_data = false;
transform_format = TRANSFORM_2D;
visible_instance_count = -1;
instance_count = 0;

View file

@ -45,30 +45,20 @@ public:
TRANSFORM_3D = VS::MULTIMESH_TRANSFORM_3D
};
enum ColorFormat {
COLOR_NONE = VS::MULTIMESH_COLOR_NONE,
COLOR_8BIT = VS::MULTIMESH_COLOR_8BIT,
COLOR_FLOAT = VS::MULTIMESH_COLOR_FLOAT,
};
enum CustomDataFormat {
CUSTOM_DATA_NONE,
CUSTOM_DATA_8BIT,
CUSTOM_DATA_FLOAT,
};
private:
Ref<Mesh> mesh;
RID multimesh;
TransformFormat transform_format;
ColorFormat color_format;
CustomDataFormat custom_data_format;
bool use_colors;
bool use_custom_data;
int instance_count;
int visible_instance_count;
protected:
static void _bind_methods();
#ifndef DISABLE_DEPRECATED
void _set_transform_array(const PoolVector<Vector3> &p_array);
PoolVector<Vector3> _get_transform_array() const;
@ -80,16 +70,19 @@ protected:
void _set_custom_data_array(const PoolVector<Color> &p_array);
PoolVector<Color> _get_custom_data_array() const;
#endif
void set_buffer(const PoolVector<float> &p_buffer);
PoolVector<float> get_buffer() const;
public:
void set_mesh(const Ref<Mesh> &p_mesh);
Ref<Mesh> get_mesh() const;
void set_color_format(ColorFormat p_color_format);
ColorFormat get_color_format() const;
void set_use_colors(bool p_enable);
bool is_using_colors() const;
void set_custom_data_format(CustomDataFormat p_custom_data_format);
CustomDataFormat get_custom_data_format() const;
void set_use_custom_data(bool p_enable);
bool is_using_custom_data() const;
void set_transform_format(TransformFormat p_transform_format);
TransformFormat get_transform_format() const;
@ -111,8 +104,6 @@ public:
void set_instance_custom_data(int p_instance, const Color &p_custom_data);
Color get_instance_custom_data(int p_instance) const;
void set_as_bulk_array(const PoolVector<float> &p_array);
virtual AABB get_aabb() const;
virtual RID get_rid() const;
@ -122,7 +113,5 @@ public:
};
VARIANT_ENUM_CAST(MultiMesh::TransformFormat);
VARIANT_ENUM_CAST(MultiMesh::ColorFormat);
VARIANT_ENUM_CAST(MultiMesh::CustomDataFormat);
#endif // MULTI_MESH_H

View file

@ -394,7 +394,7 @@ Image::Format StreamTexture::get_format() const {
return format;
}
Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, int p_size_limit) {
Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int p_size_limit) {
alpha_cache.unref();
@ -420,29 +420,16 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_
#ifdef TOOLS_ENABLED
if (request_3d_callback && df & FORMAT_BIT_DETECT_3D) {
//print_line("request detect 3D at " + p_path);
VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this);
} else {
//print_line("not requesting detect 3D at " + p_path);
VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL);
}
r_request_3d = request_3d_callback && df & FORMAT_BIT_DETECT_3D;
r_request_roughness = request_roughness_callback && df & FORMAT_BIT_DETECT_ROUGNESS;
r_request_normal = request_normal_callback && df & FORMAT_BIT_DETECT_NORMAL;
if (request_roughness_callback && df & FORMAT_BIT_DETECT_ROUGNESS) {
//print_line("request detect srgb at " + p_path);
VS::get_singleton()->texture_set_detect_roughness_callback(texture, _requested_roughness, this);
} else {
//print_line("not requesting detect srgb at " + p_path);
VS::get_singleton()->texture_set_detect_roughness_callback(texture, NULL, NULL);
}
#else
r_request_3d = false;
r_request_roughness = false;
r_request_normal = false;
if (request_normal_callback && df & FORMAT_BIT_DETECT_NORMAL) {
//print_line("request detect srgb at " + p_path);
VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this);
} else {
//print_line("not requesting detect normal at " + p_path);
VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL);
}
#endif
if (!(df & FORMAT_BIT_STREAM)) {
p_size_limit = 0;
@ -607,7 +594,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_
}
}
return ERR_BUG; //unreachable
ERR_FAIL_V(ERR_BUG); //unreachable
}
Error StreamTexture::load(const String &p_path) {
@ -615,14 +602,15 @@ Error StreamTexture::load(const String &p_path) {
int lw, lh, lwc, lhc;
Ref<Image> image;
image.instance();
Error err = _load_data(p_path, lw, lh, lwc, lhc, image);
bool request_3d;
bool request_normal;
bool request_roughness;
Error err = _load_data(p_path, lw, lh, lwc, lhc, image, request_3d, request_normal, request_roughness);
if (err)
return err;
if (get_path() == String()) {
//temporarily set path if no path set for resource, helps find errors
VisualServer::get_singleton()->texture_set_path(texture, p_path);
}
if (texture.is_valid()) {
RID new_texture = VS::get_singleton()->texture_2d_create(image);
VS::get_singleton()->texture_replace(texture, new_texture);
@ -638,6 +626,38 @@ Error StreamTexture::load(const String &p_path) {
path_to_file = p_path;
format = image->get_format();
if (get_path() == String()) {
//temporarily set path if no path set for resource, helps find errors
VisualServer::get_singleton()->texture_set_path(texture, p_path);
}
#ifdef TOOLS_ENABLED
if (request_3d) {
//print_line("request detect 3D at " + p_path);
VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this);
} else {
//print_line("not requesting detect 3D at " + p_path);
VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL);
}
if (request_roughness) {
//print_line("request detect srgb at " + p_path);
VS::get_singleton()->texture_set_detect_roughness_callback(texture, _requested_roughness, this);
} else {
//print_line("not requesting detect srgb at " + p_path);
VS::get_singleton()->texture_set_detect_roughness_callback(texture, NULL, NULL);
}
if (request_normal) {
//print_line("request detect srgb at " + p_path);
VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this);
} else {
//print_line("not requesting detect normal at " + p_path);
VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL);
}
#endif
_change_notify();
emit_changed();
return OK;

View file

@ -155,7 +155,7 @@ public:
};
private:
Error _load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, int p_size_limit = 0);
Error _load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int p_size_limit = 0);
String path_to_file;
mutable RID texture;
Image::Format format;
@ -390,6 +390,7 @@ public:
class Cubemap : public TextureLayered {
GDCLASS(Cubemap, TextureLayered);
public:
Cubemap() :
TextureLayered(VS::TEXTURE_LAYERED_CUBEMAP) {}
@ -398,6 +399,7 @@ public:
class CubemapArray : public TextureLayered {
GDCLASS(CubemapArray, TextureLayered);
public:
CubemapArray() :
TextureLayered(VS::TEXTURE_LAYERED_CUBEMAP_ARRAY) {}

View file

@ -358,7 +358,8 @@ public:
virtual RID multimesh_create() = 0;
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE) = 0;
virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
@ -374,7 +375,8 @@ public:
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) = 0;
virtual void multimesh_set_buffer(RID p_multimesh, const PoolVector<float> &p_buffer) = 0;
virtual PoolVector<float> multimesh_get_buffer(RID p_multimesh) const = 0;
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;

View file

@ -2107,7 +2107,7 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V
if (p_textures_dirty && tex_uniform_count) {
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw());
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), false);
}
if (shader_data->ubo_size == 0 && !shader_data->uses_material_samplers) {

View file

@ -465,7 +465,7 @@ void RasterizerSceneForwardRD::MaterialData::update_parameters(const Map<StringN
if (p_textures_dirty && tex_uniform_count) {
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw());
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
}
if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
@ -607,6 +607,26 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements,
id.flags = 0;
id.mask = e->instance->layer_mask;
if (e->instance->base_type == VS::INSTANCE_MULTIMESH) {
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
uint32_t stride;
if (storage->multimesh_get_transform_format(e->instance->base) == VS::MULTIMESH_TRANSFORM_2D) {
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
stride = 2;
} else {
stride = 3;
}
if (storage->multimesh_uses_colors(e->instance->base)) {
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
stride += 1;
}
if (storage->multimesh_uses_custom_data(e->instance->base)) {
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
stride += 1;
}
id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
}
//forward
uint32_t reflection_count = 0;
@ -632,7 +652,7 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements,
}
if (reflection_count < 8) {
id.omni_light_indices[omni_count] = reflection_probe_instance_get_render_index(rpi_ptrs[j]);
id.reflection_probe_indices[reflection_count] = reflection_probe_instance_get_render_index(rpi_ptrs[j]);
reflection_count++;
}
}
@ -661,7 +681,7 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements,
}
} else {
if (spot_count < 8) {
id.omni_light_indices[spot_count] = light_instance_get_index(light_ptrs[j]);
id.spot_light_indices[spot_count] = light_instance_get_index(light_ptrs[j]);
spot_count++;
}
}
@ -686,6 +706,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
//global scope bindings
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, 1);
MaterialData *prev_material = nullptr;
// ShaderData *prev_shader = nullptr;
@ -693,6 +714,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
RID prev_vertex_array_rd;
RID prev_index_array_rd;
RID prev_pipeline_rd;
RID prev_xforms_uniform_set;
PushConstant push_constant;
zeromem(&push_constant, sizeof(PushConstant));
@ -703,6 +725,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
MaterialData *material = e->material;
ShaderData *shader = material->shader_data;
RID xforms_uniform_set;
//find cull variant
ShaderData::CullVariant cull_variant;
@ -725,7 +748,12 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index);
} break;
case VS::INSTANCE_MULTIMESH: {
ERR_CONTINUE(true); //should be a bug
RID mesh = storage->multimesh_get_mesh(e->instance->base);
ERR_CONTINUE(!mesh.is_valid()); //should be a bug
primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index);
xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, 1);
} break;
case VS::INSTANCE_IMMEDIATE: {
ERR_CONTINUE(true); //should be a bug
@ -790,7 +818,9 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
storage->mesh_surface_get_arrays_and_format(e->instance->base, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format);
} break;
case VS::INSTANCE_MULTIMESH: {
ERR_CONTINUE(true); //should be a bug
RID mesh = storage->multimesh_get_mesh(e->instance->base);
ERR_CONTINUE(!mesh.is_valid()); //should be a bug
storage->mesh_surface_get_arrays_and_format(mesh, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format);
} break;
case VS::INSTANCE_IMMEDIATE: {
ERR_CONTINUE(true); //should be a bug
@ -824,6 +854,11 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
prev_pipeline_rd = pipeline_rd;
}
if (xforms_uniform_set.is_valid() && prev_xforms_uniform_set != xforms_uniform_set) {
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, 1);
prev_xforms_uniform_set = xforms_uniform_set;
}
if (material != prev_material) {
//update uniform set
if (material->uniform_set.is_valid()) {
@ -841,7 +876,8 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid());
} break;
case VS::INSTANCE_MULTIMESH: {
uint32_t instances = storage->multimesh_get_instances_to_draw(e->instance->base);
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances);
} break;
case VS::INSTANCE_IMMEDIATE: {
@ -1223,28 +1259,35 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i
//mesh->last_pass=frame;
} break;
#if 0
case VS::INSTANCE_MULTIMESH: {
RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(inst->base);
ERR_CONTINUE(!multi_mesh);
if (multi_mesh->size == 0 || multi_mesh->visible_instances == 0)
if (storage->multimesh_get_instances_to_draw(inst->base) == 0) {
//not visible, 0 instances
continue;
}
RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(multi_mesh->mesh);
if (!mesh)
continue; //mesh not assigned
RID mesh = storage->multimesh_get_mesh(inst->base);
if (!mesh.is_valid()) {
continue;
}
int ssize = mesh->surfaces.size();
const RID *materials = NULL;
uint32_t surface_count;
for (int j = 0; j < ssize; j++) {
materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (!materials) {
continue; //nothing to do
}
RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
_add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass);
for (uint32_t j = 0; j < surface_count; j++) {
uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(inst->base, j, render_pass, &geometry_index);
_add_geometry(inst, j, materials[j], p_pass_mode, surface_index);
}
} break;
#if 0
case VS::INSTANCE_IMMEDIATE: {
RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
@ -2589,7 +2632,7 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
actions.renames["POINT_COORD"] = "gl_PointCoord";
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
actions.renames["SCREEN_UV"] = "screen_uv";
actions.renames["SCREEN_TEXTURE"] = "screen_texture";
actions.renames["SCREEN_TEXTURE"] = "color_buffer";
actions.renames["DEPTH_TEXTURE"] = "depth_buffer";
actions.renames["NORMAL_TEXTURE"] = "normal_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
@ -2697,6 +2740,17 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
}
{
default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256);
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(default_vec4_xform_buffer);
u.binding = 0;
uniforms.push_back(u);
default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 1);
}
{
RD::SamplerState sampler;

View file

@ -247,6 +247,15 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
float shadow_matrices[4][16];
};
enum {
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16,
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7,
};
struct InstanceData {
float transform[16];
float normal_transform[16];
@ -471,6 +480,9 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
RID default_material;
RID default_shader_rd;
RID default_vec4_xform_buffer;
RID default_vec4_xform_uniform_set;
enum PassMode {
PASS_MODE_COLOR,
PASS_MODE_COLOR_SPECULAR,

View file

@ -428,6 +428,7 @@ VS::EnvironmentReflectionSource RasterizerSceneRD::environment_get_reflection_so
void RasterizerSceneRD::environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->exposure = p_exposure;
env->tone_mapper = p_tone_mapper;
env->auto_exposure = p_auto_exposure;
env->white = p_white;
@ -1414,7 +1415,7 @@ bool RasterizerSceneRD::free(RID p_rid) {
reflection_atlas_owner.free(p_rid);
} else if (reflection_probe_instance_owner.owns(p_rid)) {
//not much to delete, just free it
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
//ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
} else if (sky_owner.owns(p_rid)) {

View file

@ -199,7 +199,7 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima
case Image::FORMAT_DXT1: {
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK;
r_format.format_srgb = RD::DATA_FORMAT_BC1_RGBA_SRGB_BLOCK;
r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK;
} else {
//not supported, reconvert
r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@ -788,16 +788,31 @@ void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width,
}
void RasterizerStorageRD::texture_set_path(RID p_texture, const String &p_path) {
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
tex->path = p_path;
}
String RasterizerStorageRD::texture_get_path(RID p_texture) const {
return String();
}
void RasterizerStorageRD::texture_set_detect_3d_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) {
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
tex->detect_3d_callback_ud = p_userdata;
tex->detect_3d_callback = p_callback;
}
void RasterizerStorageRD::texture_set_detect_normal_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) {
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
tex->detect_normal_callback_ud = p_userdata;
tex->detect_normal_callback = p_callback;
}
void RasterizerStorageRD::texture_set_detect_roughness_callback(RID p_texture, VS::TextureDetectRoughnessCallback p_callback, void *p_userdata) {
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
tex->detect_roughness_callback_ud = p_userdata;
tex->detect_roughness_callback = p_callback;
}
void RasterizerStorageRD::texture_debug_usage(List<VS::TextureInfo> *r_info) {
}
@ -1611,9 +1626,14 @@ void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringNa
}
}
void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures) {
void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
RasterizerStorageRD *singleton = (RasterizerStorageRD *)RasterizerStorage::base_singleton;
#ifdef TOOLS_ENABLED
Texture *roughness_detect_texture = nullptr;
VS::TextureDetectRoughnessChannel roughness_channel;
Texture *normal_detect_texture = nullptr;
#endif
for (int i = 0; i < p_texture_uniforms.size(); i++) {
@ -1653,8 +1673,31 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
} break;
}
} else {
bool srgb = p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO;
rd_texture = singleton->texture_get_rd_texture(texture, srgb);
bool srgb = p_use_linear_color && p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO;
Texture *tex = singleton->texture_owner.getornull(texture);
if (tex) {
rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
#ifdef TOOLS_ENABLED
if (tex->detect_3d_callback && p_use_linear_color) {
tex->detect_3d_callback(tex->detect_3d_callback_ud);
}
if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
normal_detect_texture = tex;
}
tex->detect_normal_callback(tex->detect_normal_callback_ud);
}
if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
//find the normal texture
roughness_detect_texture = tex;
roughness_channel = VS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
}
#endif
}
if (rd_texture.is_null()) {
//wtf
rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
@ -1663,6 +1706,11 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
p_textures[i] = rd_texture;
}
#ifdef TOOLS_ENABLED
if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
}
#endif
}
void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) {
@ -2087,6 +2135,568 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
}
////////////////// MULTIMESH
RID RasterizerStorageRD::multimesh_create() {
return multimesh_owner.make_rid(MultiMesh());
}
void RasterizerStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) {
return;
}
if (multimesh->buffer.is_valid()) {
RD::get_singleton()->free(multimesh->buffer);
multimesh->buffer = RID();
multimesh->uniform_set_3d = RID(); //cleared by dependency
}
if (multimesh->data_cache_dirty_regions) {
memdelete_arr(multimesh->data_cache_dirty_regions);
multimesh->data_cache_dirty_regions = nullptr;
multimesh->data_cache_used_dirty_regions = 0;
}
multimesh->instances = p_instances;
multimesh->xform_format = p_transform_format;
multimesh->uses_colors = p_use_colors;
multimesh->color_offset_cache = p_transform_format == VS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
multimesh->uses_custom_data = p_use_custom_data;
multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
multimesh->buffer_set = false;
print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == VS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
multimesh->data_cache = PoolVector<float>();
multimesh->aabb = AABB();
multimesh->aabb_dirty = false;
multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
if (multimesh->instances) {
multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache);
}
}
int RasterizerStorageRD::multimesh_get_instance_count(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, 0);
return multimesh->instances;
}
void RasterizerStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
if (multimesh->mesh == p_mesh) {
return;
}
multimesh->mesh = p_mesh;
if (multimesh->instances == 0) {
return;
}
if (multimesh->data_cache.size()) {
//we have a data cache, just mark it dirt
_multimesh_mark_all_dirty(multimesh, false, true);
} else if (multimesh->instances) {
//need to re-create AABB unfortunately, calling this has a penalty
{
PoolVector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
PoolVector<uint8_t>::Read r = buffer.read();
const float *data = (const float *)r.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
}
}
multimesh->instance_dependency.instance_notify_changed(true, true);
}
#define MULTIMESH_DIRTY_REGION_SIZE 512
void RasterizerStorageRD::_multimesh_make_local(MultiMesh *multimesh) const {
if (multimesh->data_cache.size() > 0) {
return; //already local
}
ERR_FAIL_COND(multimesh->data_cache.size() > 0);
// this means that the user wants to load/save individual elements,
// for this, the data must reside on CPU, so just copy it there.
multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache);
{
PoolVector<float>::Write w = multimesh->data_cache.write();
if (multimesh->buffer_set) {
PoolVector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
{
PoolVector<uint8_t>::Read r = buffer.read();
copymem(w.ptr(), r.ptr(), buffer.size());
}
} else {
zeromem(w.ptr(), multimesh->instances * multimesh->stride_cache * sizeof(float));
}
}
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
multimesh->data_cache_dirty_regions[i] = 0;
}
multimesh->data_cache_used_dirty_regions = 0;
}
void RasterizerStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE;
#ifdef DEBUG_ENABLED
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
ERR_FAIL_INDEX(region_index, data_cache_dirty_region_count); //bug
#endif
if (!multimesh->data_cache_dirty_regions[region_index]) {
multimesh->data_cache_dirty_regions[p_index] = true;
multimesh->data_cache_used_dirty_regions++;
}
if (p_aabb) {
multimesh->aabb_dirty = true;
}
if (!multimesh->dirty) {
multimesh->dirty_list = multimesh_dirty_list;
multimesh_dirty_list = multimesh;
multimesh->dirty = true;
}
}
void RasterizerStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) {
if (p_data) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
if (!multimesh->data_cache_dirty_regions[i]) {
multimesh->data_cache_dirty_regions[i] = true;
multimesh->data_cache_used_dirty_regions++;
}
}
}
if (p_aabb) {
multimesh->aabb_dirty = true;
}
if (!multimesh->dirty) {
multimesh->dirty_list = multimesh_dirty_list;
multimesh_dirty_list = multimesh;
multimesh->dirty = true;
}
}
void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) {
ERR_FAIL_COND(multimesh->mesh.is_null());
AABB aabb;
AABB mesh_aabb = mesh_get_aabb(multimesh->mesh);
for (int i = 0; i < p_instances; i++) {
const float *data = p_data + multimesh->stride_cache * i;
Transform t;
if (multimesh->xform_format == VS::MULTIMESH_TRANSFORM_3D) {
t.basis[0].x = data[0];
t.basis[0].y = data[1];
t.basis[0].z = data[2];
t.basis[1].x = data[3];
t.basis[1].y = data[4];
t.basis[1].z = data[5];
t.basis[2].x = data[6];
t.basis[2].y = data[7];
t.basis[2].z = data[8];
t.origin.x = data[9];
t.origin.y = data[10];
t.origin.z = data[11];
} else {
t.basis.elements[0].x = data[0];
t.basis.elements[1].x = data[1];
t.origin.x = data[3];
t.basis.elements[0].y = data[4];
t.basis.elements[1].y = data[5];
t.origin.y = data[7];
}
if (i == 0) {
aabb = t.xform(mesh_aabb);
} else {
aabb.merge_with(t.xform(mesh_aabb));
}
}
multimesh->aabb = aabb;
}
void RasterizerStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
ERR_FAIL_COND(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_3D);
_multimesh_make_local(multimesh);
{
PoolVector<float>::Write w = multimesh->data_cache.write();
float *dataptr = w.ptr() + p_index * multimesh->stride_cache;
dataptr[0] = p_transform.basis[0].x;
dataptr[1] = p_transform.basis[0].y;
dataptr[2] = p_transform.basis[0].z;
dataptr[3] = p_transform.basis[1].x;
dataptr[4] = p_transform.basis[1].y;
dataptr[5] = p_transform.basis[1].z;
dataptr[6] = p_transform.basis[2].x;
dataptr[7] = p_transform.basis[2].y;
dataptr[8] = p_transform.basis[2].z;
dataptr[9] = p_transform.origin.x;
dataptr[10] = p_transform.origin.y;
dataptr[11] = p_transform.origin.z;
}
_multimesh_mark_dirty(multimesh, p_index, true);
}
void RasterizerStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
ERR_FAIL_COND(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_2D);
_multimesh_make_local(multimesh);
{
PoolVector<float>::Write w = multimesh->data_cache.write();
float *dataptr = w.ptr() + p_index * multimesh->stride_cache;
dataptr[0] = p_transform.elements[0].x;
dataptr[1] = p_transform.elements[1].x;
dataptr[2] = 0;
dataptr[3] = p_transform.elements[2].x;
dataptr[4] = p_transform.elements[0].y;
dataptr[5] = p_transform.elements[1].y;
dataptr[6] = 0;
dataptr[7] = p_transform.elements[2].y;
}
_multimesh_mark_dirty(multimesh, p_index, true);
}
void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
ERR_FAIL_INDEX(p_index, !multimesh->uses_colors);
_multimesh_make_local(multimesh);
{
PoolVector<float>::Write w = multimesh->data_cache.write();
float *dataptr = w.ptr() + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
dataptr[0] = p_color.r;
dataptr[1] = p_color.g;
dataptr[2] = p_color.b;
dataptr[3] = p_color.a;
}
_multimesh_mark_dirty(multimesh, p_index, false);
}
void RasterizerStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
ERR_FAIL_INDEX(p_index, !multimesh->uses_custom_data);
_multimesh_make_local(multimesh);
{
PoolVector<float>::Write w = multimesh->data_cache.write();
float *dataptr = w.ptr() + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
dataptr[0] = p_color.r;
dataptr[1] = p_color.g;
dataptr[2] = p_color.b;
dataptr[3] = p_color.a;
}
_multimesh_mark_dirty(multimesh, p_index, false);
}
RID RasterizerStorageRD::multimesh_get_mesh(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, RID());
return multimesh->mesh;
}
Transform RasterizerStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Transform());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform());
ERR_FAIL_COND_V(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_3D, Transform());
_multimesh_make_local(multimesh);
Transform t;
{
PoolVector<float>::Read r = multimesh->data_cache.read();
const float *dataptr = r.ptr() + p_index * multimesh->stride_cache;
t.basis[0].x = dataptr[0];
t.basis[0].y = dataptr[1];
t.basis[0].z = dataptr[2];
t.basis[1].x = dataptr[3];
t.basis[1].y = dataptr[4];
t.basis[1].z = dataptr[5];
t.basis[2].x = dataptr[6];
t.basis[2].y = dataptr[7];
t.basis[2].z = dataptr[8];
t.origin.x = dataptr[9];
t.origin.y = dataptr[10];
t.origin.z = dataptr[11];
}
return t;
}
Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Transform2D());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
ERR_FAIL_COND_V(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_2D, Transform2D());
_multimesh_make_local(multimesh);
Transform2D t;
{
PoolVector<float>::Read r = multimesh->data_cache.read();
const float *dataptr = r.ptr() + p_index * multimesh->stride_cache;
t.elements[0].x = dataptr[0];
t.elements[1].x = dataptr[1];
t.elements[2].x = dataptr[3];
t.elements[0].y = dataptr[4];
t.elements[1].y = dataptr[5];
t.elements[2].y = dataptr[7];
}
return t;
}
Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
ERR_FAIL_INDEX_V(p_index, !multimesh->uses_colors, Color());
_multimesh_make_local(multimesh);
Color c;
{
PoolVector<float>::Read r = multimesh->data_cache.read();
const float *dataptr = r.ptr() + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
c.r = dataptr[0];
c.g = dataptr[1];
c.b = dataptr[2];
c.a = dataptr[3];
}
return c;
}
Color RasterizerStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
ERR_FAIL_INDEX_V(p_index, !multimesh->uses_custom_data, Color());
_multimesh_make_local(multimesh);
Color c;
{
PoolVector<float>::Read r = multimesh->data_cache.read();
const float *dataptr = r.ptr() + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
c.r = dataptr[0];
c.g = dataptr[1];
c.b = dataptr[2];
c.a = dataptr[3];
}
return c;
}
void RasterizerStorageRD::multimesh_set_buffer(RID p_multimesh, const PoolVector<float> &p_buffer) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
{
PoolVector<float>::Read r = p_buffer.read();
RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r.ptr(), false);
multimesh->buffer_set = true;
}
if (multimesh->data_cache.size()) {
//if we have a data cache, just update it
multimesh->data_cache = p_buffer;
{
//clear dirty since nothing will be dirty anymore
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
multimesh->data_cache_dirty_regions[i] = false;
}
multimesh->data_cache_used_dirty_regions = 0;
}
_multimesh_mark_all_dirty(multimesh, false, true); //update AABB
} else if (multimesh->mesh.is_valid()) {
//if we have a mesh set, we need to re-generate the AABB from the new data
PoolVector<float>::Read r = p_buffer.read();
const float *data = r.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
multimesh->instance_dependency.instance_notify_changed(true, false);
}
}
PoolVector<float> RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, PoolVector<float>());
if (multimesh->buffer.is_null()) {
return PoolVector<float>();
} else if (multimesh->data_cache.size()) {
return multimesh->data_cache;
} else {
//get from memory
PoolVector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
PoolVector<float> ret;
ret.resize(multimesh->instances);
{
PoolVector<float>::Write w = multimesh->data_cache.write();
PoolVector<uint8_t>::Read r = buffer.read();
copymem(w.ptr(), r.ptr(), buffer.size());
}
return ret;
}
}
void RasterizerStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
if (multimesh->visible_instances == p_visible) {
return;
}
if (multimesh->data_cache.size()) {
//there is a data cache..
_multimesh_mark_all_dirty(multimesh, false, true);
}
multimesh->visible_instances = p_visible;
}
int RasterizerStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, 0);
return multimesh->visible_instances;
}
AABB RasterizerStorageRD::multimesh_get_aabb(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, AABB());
if (multimesh->aabb_dirty) {
const_cast<RasterizerStorageRD *>(this)->_update_dirty_multimeshes();
}
return multimesh->aabb;
}
void RasterizerStorageRD::_update_dirty_multimeshes() {
while (multimesh_dirty_list) {
MultiMesh *multimesh = multimesh_dirty_list;
if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
PoolVector<float>::Read r = multimesh->data_cache.read();
const float *data = r.ptr();
uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
if (multimesh->data_cache_used_dirty_regions) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t visible_region_count = (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
//if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * multimesh->stride_cache), data, false);
} else {
//not that many regions? update them all
for (uint32_t i = 0; i < visible_region_count; i++) {
if (multimesh->data_cache_dirty_regions[i]) {
uint64_t offset = i * region_size;
uint64_t size = multimesh->stride_cache * multimesh->instances;
RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size], false);
}
}
}
for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
multimesh->data_cache_dirty_regions[i] = false;
}
multimesh->data_cache_used_dirty_regions = 0;
}
if (multimesh->aabb_dirty) {
//aabb is dirty..
_multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->aabb_dirty = false;
multimesh->instance_dependency.instance_notify_changed(true, false);
}
}
multimesh_dirty_list = multimesh->dirty_list;
multimesh->dirty_list = nullptr;
multimesh->dirty = false;
}
multimesh_dirty_list = nullptr;
}
/* LIGHT */
RID RasterizerStorageRD::light_create(VS::LightType p_type) {
@ -2889,6 +3499,13 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
if (mesh_owner.owns(p_base)) {
Mesh *mesh = mesh_owner.getornull(p_base);
p_instance->update_dependency(&mesh->instance_dependency);
} else if (multimesh_owner.owns(p_base)) {
MultiMesh *multimesh = multimesh_owner.getornull(p_base);
p_instance->update_dependency(&multimesh->instance_dependency);
if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance);
}
} else if (reflection_probe_owner.owns(p_base)) {
ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
p_instance->update_dependency(&rp->instance_dependency);
@ -2903,6 +3520,9 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
if (mesh_owner.owns(p_rid)) {
return VS::INSTANCE_MESH;
}
if (multimesh_owner.owns(p_rid)) {
return VS::INSTANCE_MULTIMESH;
}
if (reflection_probe_owner.owns(p_rid)) {
return VS::INSTANCE_REFLECTION_PROBE;
}
@ -2914,8 +3534,29 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
}
void RasterizerStorageRD::update_dirty_resources() {
_update_queued_materials();
_update_dirty_multimeshes();
}
bool RasterizerStorageRD::has_os_feature(const String &p_feature) const {
if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
if (p_feature == "pvrtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
return false;
}
bool RasterizerStorageRD::free(RID p_rid) {
if (texture_owner.owns(p_rid)) {
@ -2972,6 +3613,12 @@ bool RasterizerStorageRD::free(RID p_rid) {
Mesh *mesh = mesh_owner.getornull(p_rid);
mesh->instance_dependency.instance_notify_deleted(p_rid);
mesh_owner.free(p_rid);
} else if (multimesh_owner.owns(p_rid)) {
_update_dirty_multimeshes();
multimesh_allocate(p_rid, 0, VS::MULTIMESH_TRANSFORM_2D);
MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
multimesh->instance_dependency.instance_notify_deleted(p_rid);
multimesh_owner.free(p_rid);
} else if (reflection_probe_owner.owns(p_rid)) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
reflection_probe->instance_dependency.instance_notify_deleted(p_rid);

View file

@ -62,7 +62,7 @@ public:
struct MaterialData {
void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures);
void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
@ -135,6 +135,15 @@ private:
RID proxy_to;
Vector<RID> proxies;
VS::TextureDetectCallback detect_3d_callback = nullptr;
void *detect_3d_callback_ud = nullptr;
VS::TextureDetectCallback detect_normal_callback = nullptr;
void *detect_normal_callback_ud = nullptr;
VS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
void *detect_roughness_callback_ud = nullptr;
};
struct TextureToRDFormat {
@ -281,6 +290,43 @@ private:
RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
/* MultiMesh */
struct MultiMesh {
RID mesh;
int instances = 0;
VS::MultimeshTransformFormat xform_format = VS::MULTIMESH_TRANSFORM_3D;
bool uses_colors = false;
bool uses_custom_data = false;
int visible_instances = -1;
AABB aabb;
bool aabb_dirty = false;
bool buffer_set = false;
uint32_t stride_cache = 0;
uint32_t color_offset_cache = 0;
uint32_t custom_data_offset_cache = 0;
PoolVector<float> data_cache; //used if individual setting is used
bool *data_cache_dirty_regions = nullptr;
uint32_t data_cache_used_dirty_regions = 0;
RID buffer; //storage buffer
RID uniform_set_3d;
bool dirty = false;
MultiMesh *dirty_list = nullptr;
RasterizerScene::InstanceDependency instance_dependency;
};
mutable RID_Owner<MultiMesh> multimesh_owner;
MultiMesh *multimesh_dirty_list = nullptr;
_FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
_FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
_FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
_FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
void _update_dirty_multimeshes();
/* LIGHT */
struct Light {
@ -485,7 +531,7 @@ public:
_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
Material *material = material_owner.getornull(p_material);
if (material->shader_type != p_shader_type) {
if (!material || material->shader_type != p_shader_type) {
return NULL;
} else {
return material->data;
@ -612,30 +658,69 @@ public:
/* MULTIMESH API */
virtual RID multimesh_create() { return RID(); }
RID multimesh_create();
void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE) {}
int multimesh_get_instance_count(RID p_multimesh) const { return 0; }
void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false);
int multimesh_get_instance_count(RID p_multimesh) const;
void multimesh_set_mesh(RID p_multimesh, RID p_mesh) {}
void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) {}
void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {}
void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {}
void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {}
void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform);
void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
RID multimesh_get_mesh(RID p_multimesh) const { return RID(); }
RID multimesh_get_mesh(RID p_multimesh) const;
Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const { return Transform(); }
Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { return Transform2D(); }
Color multimesh_instance_get_color(RID p_multimesh, int p_index) const { return Color(); }
Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { return Color(); }
Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) {}
void multimesh_set_buffer(RID p_multimesh, const PoolVector<float> &p_buffer);
PoolVector<float> multimesh_get_buffer(RID p_multimesh) const;
void multimesh_set_visible_instances(RID p_multimesh, int p_visible) {}
int multimesh_get_visible_instances(RID p_multimesh) const { return 0; }
void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
int multimesh_get_visible_instances(RID p_multimesh) const;
AABB multimesh_get_aabb(RID p_multimesh) const { return AABB(); }
AABB multimesh_get_aabb(RID p_multimesh) const;
_FORCE_INLINE_ VS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
return multimesh->xform_format;
}
_FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
return multimesh->uses_colors;
}
_FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
return multimesh->uses_custom_data;
}
_FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
if (multimesh->visible_instances >= 0) {
return multimesh->visible_instances;
}
return multimesh->instances;
}
_FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
if (!multimesh->uniform_set_3d.is_valid()) {
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
u.ids.push_back(multimesh->buffer);
uniforms.push_back(u);
multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
}
return multimesh->uniform_set_3d;
}
/* IMMEDIATE API */
@ -919,7 +1004,7 @@ public:
bool free(RID p_rid);
bool has_os_feature(const String &p_feature) const { return false; }
bool has_os_feature(const String &p_feature) const;
void update_dirty_resources();

View file

@ -482,8 +482,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
//code for functions
for (int i = 0; i < pnode->functions.size(); i++) {
SL::FunctionNode *fnode = pnode->functions[i].function;
function = fnode;
current_func_name = fnode->name;
function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
function = NULL;
}
//place functions in actual code
@ -763,7 +765,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
sampler_name = actions.custom_samplers[texture_uniform];
} else {
if (shader->uniforms.has(texture_uniform)) {
print_line("shader from texture uniform " + itos(shader->uniforms[texture_uniform].filter) + ", " + itos(shader->uniforms[texture_uniform].repeat));
sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat);
} else {
bool found = false;

View file

@ -86,16 +86,50 @@ layout(location =8) out float dp_clip;
void main() {
instance_index = draw_call.instance_index;
/*if (draw_call.instance_increment) {
instance_index += gl_InstanceIndex;
}*/
vec3 vertex = vertex_attrib;
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
#endif
mat4 world_matrix = instances.data[instance_index].transform;
mat3 world_normal_matrix= mat3(instances.data[instance_index].normal_transform);
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) {
//multimesh, instances are for it
uint offset = (instances.data[instance_index].flags>>INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT)&INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;
offset*=gl_InstanceIndex;
mat4 matrix;
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
mat4 matrix = mat4(transforms.data[offset+0],transforms.data[offset+1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0));
offset+=2;
} else {
mat4 matrix = mat4(transforms.data[offset+0],transforms.data[offset+1],transforms.data[offset+2],vec4(0.0,0.0,0.0,1.0));
offset+=3;
}
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
#ifdef COLOR_USED
color_interp *= transforms.data[offset];
#endif
offset+=1;
}
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
instance_custom = transforms.data[offset];
}
//transposed, so multiply in opposite order
world_matrix = matrix * world_matrix;
world_normal_matrix = mat3(matrix) * world_normal_matrix;
} else {
//not a multimesh, instances are for multiple draw calls
instance_index += gl_InstanceIndex;
}
vec3 vertex = vertex_attrib;
vec3 normal = normal_attrib;
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
@ -103,10 +137,6 @@ void main() {
float binormalf = tangent_attrib.a;
#endif
#if defined(COLOR_USED)
color_interp = color_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
@ -124,7 +154,7 @@ void main() {
vec4 position;
#endif
vec4 instance_custom = vec4(0.0);
mat4 projection_matrix = scene_data.projection_matrix;
@ -768,7 +798,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
transmission,
#endif
#ifdef LIGHT_RIM_USED
rim * omni_attenuation, rim_tint,
rim * spot_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@ -932,7 +962,7 @@ void main() {
float normaldepth = 1.0;
#if defined(SCREEN_UV_USED)
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size;
#endif
float sss_strength = 0.0;
@ -1182,7 +1212,7 @@ FRAGMENT_SHADER_CODE
transmission,
#endif
#ifdef LIGHT_RIM_USED
rim * omni_attenuation, rim_tint,
rim, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,

View file

@ -118,11 +118,20 @@ layout(set=0,binding=8,std140) uniform SceneData {
#endif
} scene_data;
#define INSTANCE_FLAGS_FORWARD_MASK 3
#define INSTANCE_FLAGS_FORWARD_MASK 0x7
#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3
#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6
#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT 16
//3 bits of stride
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7
struct InstanceData {
mat4 transform;
@ -217,6 +226,11 @@ layout(set=0,binding=15,std430) buffer Skeletons {
//layout(set = 1, binding = 0) uniform textureBuffer multimesh_transforms;
layout(set=1,binding=0,std430) buffer Transforms {
vec4 data[];
} transforms;
/* Set 2 Instancing (Multimesh) data */
#if 0

View file

@ -145,7 +145,7 @@ vec3 tonemap_filmic(vec3 color, float white) {
vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;
float white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F;
return color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f);
return color_tonemapped / white_tonemapped;
}
vec3 tonemap_aces(vec3 color, float white) {
@ -159,7 +159,7 @@ vec3 tonemap_aces(vec3 color, float white) {
vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E);
float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E);
return color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f);
return color_tonemapped / white_tonemapped;
}
vec3 tonemap_reinhard(vec3 color, float white) {

View file

@ -307,6 +307,12 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_WHITE_TEXTURE, "hint_white" },
{ TK_HINT_BLACK_TEXTURE, "hint_black" },
{ TK_HINT_NORMAL_TEXTURE, "hint_normal" },
{ TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal" },
{ TK_HINT_ROUGHNESS_R, "hint_roughness_r" },
{ TK_HINT_ROUGHNESS_G, "hint_roughness_g" },
{ TK_HINT_ROUGHNESS_B, "hint_roughness_b" },
{ TK_HINT_ROUGHNESS_A, "hint_roughness_a" },
{ TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray" },
{ TK_HINT_ANISO_TEXTURE, "hint_aniso" },
{ TK_HINT_ALBEDO_TEXTURE, "hint_albedo" },
{ TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
@ -5171,6 +5177,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.hint = ShaderNode::Uniform::HINT_BLACK;
} else if (tk.type == TK_HINT_NORMAL_TEXTURE) {
uniform2.hint = ShaderNode::Uniform::HINT_NORMAL;
} else if (tk.type == TK_HINT_ROUGHNESS_NORMAL_TEXTURE) {
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL;
} else if (tk.type == TK_HINT_ROUGHNESS_R) {
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_R;
} else if (tk.type == TK_HINT_ROUGHNESS_G) {
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_G;
} else if (tk.type == TK_HINT_ROUGHNESS_B) {
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_B;
} else if (tk.type == TK_HINT_ROUGHNESS_A) {
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_A;
} else if (tk.type == TK_HINT_ROUGHNESS_GRAY) {
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_GRAY;
} else if (tk.type == TK_HINT_ANISO_TEXTURE) {
uniform2.hint = ShaderNode::Uniform::HINT_ANISO;
} else if (tk.type == TK_HINT_ALBEDO_TEXTURE) {

View file

@ -150,6 +150,12 @@ public:
TK_HINT_WHITE_TEXTURE,
TK_HINT_BLACK_TEXTURE,
TK_HINT_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_R,
TK_HINT_ROUGHNESS_G,
TK_HINT_ROUGHNESS_B,
TK_HINT_ROUGHNESS_A,
TK_HINT_ROUGHNESS_GRAY,
TK_HINT_ANISO_TEXTURE,
TK_HINT_ALBEDO_TEXTURE,
TK_HINT_BLACK_ALBEDO_TEXTURE,
@ -576,6 +582,12 @@ public:
HINT_ALBEDO,
HINT_BLACK_ALBEDO,
HINT_NORMAL,
HINT_ROUGHNESS_NORMAL,
HINT_ROUGHNESS_R,
HINT_ROUGHNESS_G,
HINT_ROUGHNESS_B,
HINT_ROUGHNESS_A,
HINT_ROUGHNESS_GRAY,
HINT_BLACK,
HINT_WHITE,
HINT_ANISO,

View file

@ -248,7 +248,7 @@ public:
BIND0R(RID, multimesh_create)
BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat, MultimeshCustomDataFormat)
BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool)
BIND1RC(int, multimesh_get_instance_count, RID)
BIND2(multimesh_set_mesh, RID, RID)
@ -265,7 +265,8 @@ public:
BIND2RC(Color, multimesh_instance_get_color, RID, int)
BIND2RC(Color, multimesh_instance_get_custom_data, RID, int)
BIND2(multimesh_set_as_bulk_array, RID, const PoolVector<float> &)
BIND2(multimesh_set_buffer, RID, const PoolVector<float> &)
BIND1RC(PoolVector<float>, multimesh_get_buffer, RID)
BIND2(multimesh_set_visible_instances, RID, int)
BIND1RC(int, multimesh_get_visible_instances, RID)

View file

@ -1863,7 +1863,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
bool keep = false;
if ((camera_layer_mask & ins->layer_mask) == 0) {
//failure
} else if (ins->base_type == VS::INSTANCE_LIGHT && ins->visible) {

View file

@ -175,7 +175,7 @@ public:
FUNCRID(multimesh)
FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat, MultimeshCustomDataFormat)
FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool)
FUNC1RC(int, multimesh_get_instance_count, RID)
FUNC2(multimesh_set_mesh, RID, RID)
@ -192,7 +192,8 @@ public:
FUNC2RC(Color, multimesh_instance_get_color, RID, int)
FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
FUNC2(multimesh_set_as_bulk_array, RID, const PoolVector<float> &)
FUNC2(multimesh_set_buffer, RID, const PoolVector<float> &)
FUNC1RC(PoolVector<float>, multimesh_get_buffer, RID)
FUNC2(multimesh_set_visible_instances, RID, int)
FUNC1RC(int, multimesh_get_visible_instances, RID)

View file

@ -1638,7 +1638,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear);
ClassDB::bind_method(D_METHOD("multimesh_create"), &VisualServer::multimesh_create);
ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &VisualServer::multimesh_allocate, DEFVAL(MULTIMESH_CUSTOM_DATA_NONE));
ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &VisualServer::multimesh_allocate, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &VisualServer::multimesh_get_instance_count);
ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &VisualServer::multimesh_set_mesh);
ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform);
@ -1653,7 +1653,8 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("multimesh_instance_get_custom_data", "multimesh", "index"), &VisualServer::multimesh_instance_get_custom_data);
ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &VisualServer::multimesh_set_visible_instances);
ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &VisualServer::multimesh_get_visible_instances);
ClassDB::bind_method(D_METHOD("multimesh_set_as_bulk_array", "multimesh", "array"), &VisualServer::multimesh_set_as_bulk_array);
ClassDB::bind_method(D_METHOD("multimesh_set_buffer", "multimesh", "buffer"), &VisualServer::multimesh_set_buffer);
ClassDB::bind_method(D_METHOD("multimesh_get_buffer", "multimesh"), &VisualServer::multimesh_get_buffer);
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("immediate_create"), &VisualServer::immediate_create);
ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &VisualServer::immediate_begin, DEFVAL(RID()));
@ -2151,12 +2152,6 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_2D);
BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_3D);
BIND_ENUM_CONSTANT(MULTIMESH_COLOR_NONE);
BIND_ENUM_CONSTANT(MULTIMESH_COLOR_8BIT);
BIND_ENUM_CONSTANT(MULTIMESH_COLOR_FLOAT);
BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_NONE);
BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_8BIT);
BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_FLOAT);
BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE);
BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS);

View file

@ -319,21 +319,7 @@ public:
MULTIMESH_TRANSFORM_3D,
};
enum MultimeshColorFormat {
MULTIMESH_COLOR_NONE,
MULTIMESH_COLOR_8BIT,
MULTIMESH_COLOR_FLOAT,
MULTIMESH_COLOR_MAX,
};
enum MultimeshCustomDataFormat {
MULTIMESH_CUSTOM_DATA_NONE,
MULTIMESH_CUSTOM_DATA_8BIT,
MULTIMESH_CUSTOM_DATA_FLOAT,
MULTIMESH_CUSTOM_DATA_MAX,
};
virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, MultimeshColorFormat p_color_format, MultimeshCustomDataFormat p_data_format = MULTIMESH_CUSTOM_DATA_NONE) = 0;
virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
@ -350,7 +336,8 @@ public:
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) = 0;
virtual void multimesh_set_buffer(RID p_multimesh, const PoolVector<float> &p_buffer) = 0;
virtual PoolVector<float> multimesh_get_buffer(RID p_multimesh) const = 0;
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
@ -1100,8 +1087,6 @@ VARIANT_ENUM_CAST(VisualServer::CanvasOccluderPolygonCullMode);
VARIANT_ENUM_CAST(VisualServer::RenderInfo);
VARIANT_ENUM_CAST(VisualServer::Features);
VARIANT_ENUM_CAST(VisualServer::MultimeshTransformFormat);
VARIANT_ENUM_CAST(VisualServer::MultimeshColorFormat);
VARIANT_ENUM_CAST(VisualServer::MultimeshCustomDataFormat);
VARIANT_ENUM_CAST(VisualServer::LightOmniShadowMode);
VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowMode);
VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowDepthRangeMode);