Completed material/2D shader support (missing SCREEN_TEXTURE)

This commit is contained in:
Juan Linietsky 2019-07-21 11:31:30 -03:00
parent 50e9befb88
commit 8bbbb97336
29 changed files with 3607 additions and 532 deletions

View file

@ -354,8 +354,6 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
}
r_gen_code.texture_uniforms.resize(max_texture_uniforms);
r_gen_code.texture_hints.resize(max_texture_uniforms);
r_gen_code.texture_types.resize(max_texture_uniforms);
Vector<int> uniform_sizes;
Vector<int> uniform_alignments;
@ -380,9 +378,15 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (SL::is_sampler_type(E->get().type)) {
r_gen_code.vertex_global += ucode;
r_gen_code.fragment_global += ucode;
r_gen_code.texture_uniforms.write[E->get().texture_order] = _mkid(E->key());
r_gen_code.texture_hints.write[E->get().texture_order] = E->get().hint;
r_gen_code.texture_types.write[E->get().texture_order] = E->get().type;
GeneratedCode::Texture texture;
texture.name = _mkid(E->key());
texture.hint = E->get().hint;
texture.type = E->get().type;
texture.filter = E->get().filter;
texture.repeat = E->get().repeat;
r_gen_code.texture_uniforms.write[E->get().texture_order] = texture;
} else {
if (!uses_uniforms) {

View file

@ -51,9 +51,15 @@ public:
struct GeneratedCode {
Vector<CharString> defines;
Vector<StringName> texture_uniforms;
Vector<ShaderLanguage::DataType> texture_types;
Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
struct Texture {
StringName name;
ShaderLanguage::DataType type;
ShaderLanguage::ShaderNode::Uniform::Hint hint;
ShaderLanguage::ShaderNode::Uniform::Filter filter;
ShaderLanguage::ShaderNode::Uniform::Repeat repeat;
};
Vector<Texture> texture_uniforms;
Vector<uint32_t> uniform_offsets;
uint32_t uniform_total_size;

View file

@ -4119,13 +4119,13 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
} break;
case UNIFORM_TYPE_UNIFORM_BUFFER: {
ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(),
"Uniform buffer (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
"Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
Buffer *buffer = uniform_buffer_owner.getornull(uniform.ids[0]);
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Uniform buffer (binding: " + itos(uniform.binding) + ") is invalid.");
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(),
"Uniform buffer (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
"Uniform buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
write.dstArrayElement = 0;
write.descriptorCount = 1;
@ -4137,13 +4137,13 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
} break;
case UNIFORM_TYPE_STORAGE_BUFFER: {
ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(),
"Storage buffer (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
"Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
Buffer *buffer = storage_buffer_owner.getornull(uniform.ids[0]);
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer (binding: " + itos(uniform.binding) + ") is invalid.");
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(),
"Storage buffer (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
"Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
write.dstArrayElement = 0;
write.descriptorCount = 1;

View file

@ -86,7 +86,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(VkDebugU
free(message);
abort();
// abort();
// Don't bail out, but keep going.
return false;
}
@ -416,8 +416,7 @@ Error VulkanContext::_create_physical_device() {
// Query fine-grained feature support for this device.
// If app has specific feature requirements it should check supported
// features based on this query
VkPhysicalDeviceFeatures physDevFeatures;
vkGetPhysicalDeviceFeatures(gpu, &physDevFeatures);
vkGetPhysicalDeviceFeatures(gpu, &physical_device_features);
#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
{ \
@ -456,7 +455,7 @@ Error VulkanContext::_create_device() {
.ppEnabledLayerNames = NULL,
.enabledExtensionCount = enabled_extension_count,
.ppEnabledExtensionNames = (const char *const *)extension_names,
.pEnabledFeatures = NULL, // If specific features are required, pass them in here
.pEnabledFeatures = &physical_device_features, // If specific features are required, pass them in here
};
if (separate_present_queue) {
queues[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;

View file

@ -39,6 +39,7 @@ class VulkanContext {
int frame_index;
VkFence fences[FRAME_LAG];
VkPhysicalDeviceMemoryProperties memory_properties;
VkPhysicalDeviceFeatures physical_device_features;
typedef struct {
VkImage image;

View file

@ -1179,17 +1179,17 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::draw_multiline_colors, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::draw_circle);
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT), DEFVAL(TEXTURE_REPEAT_PARENT));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT), DEFVAL(TEXTURE_REPEAT_PARENT));
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "normal_map", "specular_map", "clip_uv", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(true), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT), DEFVAL(TEXTURE_REPEAT_PARENT));
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE));
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "normal_map", "specular_map", "clip_uv", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(true), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE));
ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box);
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_primitive, DEFVAL(Variant()), DEFVAL(1.0), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT), DEFVAL(TEXTURE_REPEAT_PARENT));
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT), DEFVAL(TEXTURE_REPEAT_PARENT));
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_colored_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT), DEFVAL(TEXTURE_REPEAT_PARENT));
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_primitive, DEFVAL(Variant()), DEFVAL(1.0), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE));
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE));
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_colored_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE));
ClassDB::bind_method(D_METHOD("draw_string", "font", "position", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("draw_char", "font", "position", "char", "next", "modulate"), &CanvasItem::draw_char, DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map", "specular_map", "transform", "modulate", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT), DEFVAL(TEXTURE_REPEAT_PARENT));
ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_multimesh, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT), DEFVAL(TEXTURE_REPEAT_PARENT));
ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map", "specular_map", "transform", "modulate", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE));
ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture", "normal_map", "specular_map", "specular_shinness", "texture_filter", "texture_repeat"), &CanvasItem::draw_multimesh, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE));
ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform);
ClassDB::bind_method(D_METHOD("draw_set_transform_matrix", "xform"), &CanvasItem::draw_set_transform_matrix);
@ -1239,8 +1239,8 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
ADD_GROUP("Texture", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Parent Node,Nearest,Linear,MipmapLinear,MipmapNearest"), "set_texture_filter", "get_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Parent Node,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "ParentNode,Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "ParentNode,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
ADD_GROUP("Material", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial"), "set_material", "get_material");
@ -1260,14 +1260,16 @@ void CanvasItem::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_ENTER_CANVAS);
BIND_CONSTANT(NOTIFICATION_EXIT_CANVAS);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_PARENT);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_PARENT_NODE);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR_WITH_MIPMAPS);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR_WITH_MIPMAPS);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_MAX);
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_PARENT);
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_PARENT_NODE);
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_DISABLED);
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_ENABLED);
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MIRROR);
@ -1341,7 +1343,7 @@ void CanvasItem::_update_texture_filter_changed(bool p_propagate) {
return;
}
if (texture_filter == TEXTURE_FILTER_PARENT) {
if (texture_filter == TEXTURE_FILTER_PARENT_NODE) {
CanvasItem *parent_item = get_parent_item();
if (parent_item) {
texture_filter_cache = parent_item->texture_filter_cache;
@ -1364,7 +1366,7 @@ void CanvasItem::_update_texture_filter_changed(bool p_propagate) {
if (p_propagate) {
for (List<CanvasItem *>::Element *E = children_items.front(); E; E = E->next()) {
if (!E->get()->toplevel && E->get()->texture_filter == TEXTURE_FILTER_PARENT) {
if (!E->get()->toplevel && E->get()->texture_filter == TEXTURE_FILTER_PARENT_NODE) {
E->get()->_update_texture_filter_changed(true);
}
}
@ -1390,7 +1392,7 @@ void CanvasItem::_update_texture_repeat_changed(bool p_propagate) {
return;
}
if (texture_repeat == TEXTURE_REPEAT_PARENT) {
if (texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
CanvasItem *parent_item = get_parent_item();
if (parent_item) {
texture_repeat_cache = parent_item->texture_repeat_cache;
@ -1411,7 +1413,7 @@ void CanvasItem::_update_texture_repeat_changed(bool p_propagate) {
update();
if (p_propagate) {
for (List<CanvasItem *>::Element *E = children_items.front(); E; E = E->next()) {
if (!E->get()->toplevel && E->get()->texture_repeat == TEXTURE_REPEAT_PARENT) {
if (!E->get()->toplevel && E->get()->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
E->get()->_update_texture_repeat_changed(true);
}
}
@ -1451,8 +1453,8 @@ CanvasItem::CanvasItem() :
notify_local_transform = false;
notify_transform = false;
light_mask = 1;
texture_repeat = TEXTURE_REPEAT_PARENT;
texture_filter = TEXTURE_FILTER_PARENT;
texture_repeat = TEXTURE_REPEAT_PARENT_NODE;
texture_filter = TEXTURE_FILTER_PARENT_NODE;
texture_filter_cache = VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
texture_repeat_cache = VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;

View file

@ -167,16 +167,18 @@ class CanvasItem : public Node {
public:
enum TextureFilter {
TEXTURE_FILTER_PARENT,
TEXTURE_FILTER_PARENT_NODE,
TEXTURE_FILTER_NEAREST,
TEXTURE_FILTER_LINEAR,
TEXTURE_FILTER_LINEAR_WITH_MIPMAPS,
TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS,
TEXTURE_FILTER_LINEAR_WITH_MIPMAPS,
TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC,
TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC,
TEXTURE_FILTER_MAX
};
enum TextureRepeat {
TEXTURE_REPEAT_PARENT,
TEXTURE_REPEAT_PARENT_NODE,
TEXTURE_REPEAT_DISABLED,
TEXTURE_REPEAT_ENABLED,
TEXTURE_REPEAT_MIRROR,
@ -329,16 +331,16 @@ public:
void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, float p_width = 1.0);
void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color);
void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT);
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT);
void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), bool p_clip_uv = false, TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT);
void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT_NODE, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT_NODE);
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT_NODE, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT_NODE);
void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), bool p_clip_uv = false, TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT_NODE, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT_NODE);
void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect);
void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), float p_width = 1, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT);
void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>(), const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT);
void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>(), const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT);
void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), float p_width = 1, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT_NODE, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT_NODE);
void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>(), const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT_NODE, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT_NODE);
void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>(), const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT_NODE, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT_NODE);
void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture2D> &p_texture, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT);
void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture2D> &p_texture, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT);
void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture2D> &p_texture, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT_NODE, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT_NODE);
void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture2D> &p_texture, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), TextureFilter p_texture_filter = TEXTURE_FILTER_PARENT_NODE, TextureRepeat p_texture_repeat = TEXTURE_REPEAT_PARENT_NODE);
void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate = Color(1, 1, 1), int p_clip_w = -1);
float draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", const Color &p_modulate = Color(1, 1, 1));

View file

@ -35,6 +35,31 @@
Rasterizer *(*Rasterizer::_create_func)() = NULL;
void RasterizerScene::InstanceDependency::instance_notify_changed(bool p_aabb, bool p_dependencies) {
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependency_changed(p_aabb, p_dependencies);
}
}
void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted) {
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependency_deleted(p_deleted);
}
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependencies.erase(this);
}
}
RasterizerScene::InstanceDependency::~InstanceDependency() {
#ifdef DEBUG_ENABLED
if (instances.size()) {
WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing.");
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependencies.erase(this);
}
}
#endif
}
Rasterizer *Rasterizer::create() {
return _create_func();

View file

@ -34,6 +34,7 @@
#include "core/math/camera_matrix.h"
#include "servers/visual_server.h"
#include "core/pair.h"
#include "core/self_list.h"
class RasterizerScene {
@ -85,6 +86,20 @@ public:
virtual VS::EnvironmentBG environment_get_background(RID p_env) = 0;
virtual int environment_get_canvas_max_layer(RID p_env) = 0;
struct InstanceBase;
struct InstanceDependency {
void instance_notify_changed(bool p_aabb, bool p_dependencies);
void instance_notify_deleted(RID p_deleted);
~InstanceDependency();
private:
friend class InstanceBase;
Map<InstanceBase *, uint32_t> instances;
};
struct InstanceBase {
VS::InstanceType base_type;
@ -97,6 +112,7 @@ public:
int depth_layer;
uint32_t layer_mask;
uint32_t instance_version;
//RID sampled_light;
@ -124,8 +140,48 @@ public:
RID lightmap;
Vector<Color> lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader
virtual void base_removed() = 0;
virtual void base_changed(bool p_aabb, bool p_materials) = 0;
virtual void dependency_deleted(RID p_dependency) = 0;
virtual void dependency_changed(bool p_aabb, bool p_dependencies) = 0;
Set<InstanceDependency *> dependencies;
void instance_increase_version() {
instance_version++;
}
void update_dependency(InstanceDependency *p_dependency) {
dependencies.insert(p_dependency);
p_dependency->instances[this] = instance_version;
}
void clean_up_dependencies() {
List<Pair<InstanceDependency *, Map<InstanceBase *, uint32_t>::Element *> > to_clean_up;
for (Set<InstanceDependency *>::Element *E = dependencies.front(); E; E = E->next()) {
InstanceDependency *dep = E->get();
Map<InstanceBase *, uint32_t>::Element *F = dep->instances.find(this);
ERR_CONTINUE(!F);
if (F->get() != instance_version) {
Pair<InstanceDependency *, Map<InstanceBase *, uint32_t>::Element *> p;
p.first = dep;
p.second = F;
to_clean_up.push_back(p);
}
}
while (to_clean_up.size()) {
to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second);
to_clean_up.pop_front();
}
}
void clear_dependencies() {
for (Set<InstanceDependency *>::Element *E = dependencies.front(); E; E = E->next()) {
InstanceDependency *dep = E->get();
dep->instances.erase(this);
}
dependencies.clear();
}
InstanceBase() :
dependency_item(this) {
@ -135,10 +191,15 @@ public:
visible = true;
depth_layer = 0;
layer_mask = 1;
instance_version = 0;
baked_light = false;
redraw_if_visible = false;
lightmap_capture = NULL;
}
virtual ~InstanceBase() {
clear_dependencies();
}
};
virtual RID light_instance_create(RID p_light) = 0;
@ -241,7 +302,6 @@ public:
virtual void material_set_render_priority(RID p_material, int priority) = 0;
virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
virtual RID material_get_shader(RID p_shader_material) const = 0;
virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0;
virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0;
@ -251,8 +311,7 @@ public:
virtual bool material_is_animated(RID p_material) = 0;
virtual bool material_casts_shadows(RID p_material) = 0;
virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0;
/* MESH API */
@ -413,11 +472,8 @@ public:
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0;
virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void skeleton_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
/* GI PROBE API */
@ -578,6 +634,7 @@ public:
virtual String get_video_adapter_vendor() const = 0;
static RasterizerStorage *base_singleton;
RasterizerStorage();
virtual ~RasterizerStorage() {}
};

View file

@ -1,5 +1,7 @@
#include "rasterizer_canvas_rd.h"
#include "core/math/math_funcs.h"
#include "core/project_settings.h"
void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
p_mat4[0] = p_transform.elements[0][0];
@ -82,7 +84,7 @@ RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap,
RID texture = storage->texture_get_rd_texture(p_texture);
if (!texture.is_valid()) {
//use default white texture
texture = default_textures.white_texture;
texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE);
}
u.ids.push_back(texture);
uniform_set.push_back(u);
@ -95,7 +97,7 @@ RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap,
RID texture = storage->texture_get_rd_texture(p_normalmap);
if (!texture.is_valid()) {
//use default normal texture
texture = default_textures.normal_texture;
texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL);
}
u.ids.push_back(texture);
uniform_set.push_back(u);
@ -108,7 +110,7 @@ RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap,
RID texture = storage->texture_get_rd_texture(p_specular);
if (!texture.is_valid()) {
//use default white texture
texture = default_textures.white_texture;
texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE);
}
u.ids.push_back(texture);
uniform_set.push_back(u);
@ -118,7 +120,7 @@ RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap,
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 4;
RID sampler = default_samplers.samplers[p_filter][p_repeat];
RID sampler = storage->sampler_rd_get_default(p_filter, p_repeat);
ERR_FAIL_COND_V(sampler.is_null(), RID());
u.ids.push_back(sampler);
uniform_set.push_back(u);
@ -128,7 +130,7 @@ RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap,
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
u.binding = 5;
u.ids.push_back(default_textures.default_multimesh_tb);
u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
uniform_set.push_back(u);
}
@ -488,7 +490,7 @@ Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD:
}
////////////////////
void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights) {
void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
//create an empty push constant
@ -566,99 +568,20 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT;
}
if (light_count) {
//validate and update lighs if they are being used
bool invalid_uniform = state_data->light_uniform_set.is_valid() && !RD::get_singleton()->uniform_set_is_valid(state_data->light_uniform_set);
if (state_data->light_uniform_set.is_null() || invalid_uniform || light_uniform_set_dirty) {
//recreate uniform set
if (state_data->light_uniform_set.is_valid() && !invalid_uniform) {
RD::get_singleton()->free(state_data->light_uniform_set);
}
state_data->light_uniform_set = RID();
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 0;
u.ids.push_back(state.lights_uniform_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u_lights;
u_lights.type = RD::UNIFORM_TYPE_TEXTURE;
u_lights.binding = 1;
RD::Uniform u_shadows;
u_shadows.type = RD::UNIFORM_TYPE_TEXTURE;
u_shadows.binding = 2;
//lights
for (uint32_t i = 0; i < state.max_lights_per_item; i++) {
if (i < light_count) {
CanvasLight *cl = canvas_light_owner.getornull(light_cache[i]->light_internal);
ERR_CONTINUE(!cl);
RID rd_texture;
if (cl->texture.is_valid()) {
rd_texture = storage->texture_get_rd_texture(cl->texture);
}
if (rd_texture.is_valid()) {
u_lights.ids.push_back(rd_texture);
} else {
u_lights.ids.push_back(default_textures.white_texture);
}
if (cl->shadow.texture.is_valid()) {
u_shadows.ids.push_back(cl->shadow.texture);
} else {
u_shadows.ids.push_back(default_textures.black_texture);
}
} else {
u_lights.ids.push_back(default_textures.white_texture);
u_shadows.ids.push_back(default_textures.black_texture);
}
}
uniforms.push_back(u_lights);
uniforms.push_back(u_shadows);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 3;
u.ids.push_back(state.shadow_sampler);
uniforms.push_back(u);
}
state_data->light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader_light, 3);
}
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, state_data->light_uniform_set, 3);
light_mode = PIPELINE_LIGHT_MODE_ENABLED;
} else {
light_mode = PIPELINE_LIGHT_MODE_DISABLED;
}
{
//state uniform
bool invalid_uniform = state_data->state_uniform_set.is_valid() && !RD::get_singleton()->uniform_set_is_valid(state_data->state_uniform_set);
if (state_data->state_uniform_set.is_null() || invalid_uniform) {
if (state_data->state_uniform_set.is_valid() && !invalid_uniform) {
RD::get_singleton()->free(state_data->state_uniform_set);
}
state_data->state_uniform_set = RID();
RID &canvas_item_state = light_count ? state_data->state_uniform_set_with_light : state_data->state_uniform_set;
bool invalid_uniform = canvas_item_state.is_valid() && !RD::get_singleton()->uniform_set_is_valid(canvas_item_state);
if (canvas_item_state.is_null() || invalid_uniform || (light_count > 0 && light_uniform_set_dirty)) {
//re create canvas state
Vector<RD::Uniform> uniforms;
if (state_data->state_uniform_set_with_light.is_valid() && !invalid_uniform) {
RD::get_singleton()->free(canvas_item_state);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
@ -672,14 +595,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
} else {
//bind default
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 0;
u.ids.push_back(state.canvas_state_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
@ -697,19 +612,86 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
}
}
state_data->state_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 2);
//validate and update lighs if they are being used
if (light_count > 0) {
//recreate uniform set
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 3;
u.ids.push_back(state.lights_uniform_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u_lights;
u_lights.type = RD::UNIFORM_TYPE_TEXTURE;
u_lights.binding = 4;
RD::Uniform u_shadows;
u_shadows.type = RD::UNIFORM_TYPE_TEXTURE;
u_shadows.binding = 5;
//lights
for (uint32_t i = 0; i < state.max_lights_per_item; i++) {
if (i < light_count) {
CanvasLight *cl = canvas_light_owner.getornull(light_cache[i]->light_internal);
ERR_CONTINUE(!cl);
RID rd_texture;
if (cl->texture.is_valid()) {
rd_texture = storage->texture_get_rd_texture(cl->texture);
}
if (rd_texture.is_valid()) {
u_lights.ids.push_back(rd_texture);
} else {
u_lights.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
}
if (cl->shadow.texture.is_valid()) {
u_shadows.ids.push_back(cl->shadow.texture);
} else {
u_shadows.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK));
}
} else {
u_lights.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
u_shadows.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK));
}
}
uniforms.push_back(u_lights);
uniforms.push_back(u_shadows);
}
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 6;
u.ids.push_back(state.shadow_sampler);
uniforms.push_back(u);
}
canvas_item_state = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader_light, 2);
} else {
canvas_item_state = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 2);
}
}
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, state_data->state_uniform_set, 2);
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, canvas_item_state, 2);
}
PipelineVariants *pipeline_variants = &shader.pipeline_variants;
light_mode = light_count > 0 ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED;
PipelineVariants *pipeline_variants = p_pipeline_variants;
bool reclip = false;
const Item::Command *c = p_item->commands;
while (c) {
push_constant.flags = base_flags; //reset on each command for sanity
push_constant.specular_shininess = 0xFFFFFFFF;
@ -1341,6 +1323,10 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, clear_colors);
RID prev_material;
PipelineVariants *pipeline_variants = &shader.pipeline_variants;
for (int i = 0; i < p_item_count; i++) {
Item *ci = items[i];
@ -1360,7 +1346,34 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
}
}
_render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights);
if (ci->material != prev_material) {
MaterialData *material_data;
if (ci->material.is_valid()) {
material_data = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
print_line("has material data");
}
if (material_data) {
if (material_data->shader_data->version.is_valid()) {
pipeline_variants = &material_data->shader_data->pipeline_variants;
if (material_data->uniform_set.is_valid()) {
print_line("bound uniform set");
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, 1);
}
} else {
pipeline_variants = &shader.pipeline_variants;
}
} else {
pipeline_variants = &shader.pipeline_variants;
}
}
print_line("go render");
_render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants);
prev_material = ci->material;
}
RD::get_singleton()->draw_list_end();
@ -1397,6 +1410,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
state_buffer.canvas_modulate[2] = p_modulate.b;
state_buffer.canvas_modulate[3] = p_modulate.a;
state_buffer.time = state.time;
RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true);
}
@ -1462,28 +1476,48 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
}
//fill the list until rendering is possible.
bool material_screen_texture_found = false;
Item *ci = p_item_list;
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
while (ci) {
if (ci->copy_back_buffer) {
backbuffer_copy = true;
if (ci->copy_back_buffer->full) {
back_buffer_rect = Rect2();
} else {
back_buffer_rect = ci->copy_back_buffer->rect;
}
}
if (!material_screen_texture_found && ci->material.is_valid()) {
MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
if (md->shader_data->uses_screen_texture) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
}
}
if (backbuffer_copy) {
//render anything pending, including clearing if no items
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
backbuffer_copy = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
}
items[item_count++] = ci;
bool backbuffer_copy = ci->copy_back_buffer; // || shader uses SCREEN_TEXTURE
if (!ci->next || backbuffer_copy || item_count == MAX_RENDER_ITEMS - 1) {
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
//then reset
item_count = 0;
}
if (ci->copy_back_buffer) {
if (ci->copy_back_buffer->full) {
//_copy_texscreen(Rect2());
} else {
//_copy_texscreen(ci->copy_back_buffer->rect);
}
}
ci = ci->next;
}
}
@ -1734,6 +1768,382 @@ void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, VS::Canv
oc->cull_mode = p_mode;
}
void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
//compile
print_line("shader set code?");
code = p_code;
valid = false;
ubo_size = 0;
uniforms.clear();
uses_screen_texture = false;
uses_material_samplers = false;
if (code == String()) {
return; //just invalid, but no error
}
ShaderCompilerRD::GeneratedCode gen_code;
int light_mode = LIGHT_MODE_NORMAL;
int blend_mode = BLEND_MODE_MIX;
bool uses_screen_texture = false;
ShaderCompilerRD::IdentifierActions actions;
actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD);
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA);
actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED);
actions.render_mode_values["unshaded"] = Pair<int *, int>(&light_mode, LIGHT_MODE_UNSHADED);
actions.render_mode_values["light_only"] = Pair<int *, int>(&light_mode, LIGHT_MODE_LIGHT_ONLY);
actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
actions.uniforms = &uniforms;
RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton;
Error err = canvas_singleton->shader.compiler.compile(VS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
ERR_FAIL_COND(err != OK);
if (version.is_null()) {
version = canvas_singleton->shader.canvas_shader.version_create();
}
if (gen_code.texture_uniforms.size() || uses_screen_texture) { //requires the samplers
gen_code.defines.push_back("\n#define USE_MATERIAL_SAMPLERS\n");
uses_material_samplers = true;
}
#if 0
print_line("**compiling shader:");
print_line("**defines:\n");
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
print_line("\n**vertex_code:\n" + gen_code.vertex);
print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
print_line("\n**fragment_code:\n" + gen_code.fragment);
print_line("\n**light_code:\n" + gen_code.light);
#endif
canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines);
ubo_size = gen_code.uniform_total_size;
ubo_offsets = gen_code.uniform_offsets;
texture_uniforms = gen_code.texture_uniforms;
//update them pipelines
RD::PipelineColorBlendState::Attachment attachment;
switch (blend_mode) {
case BLEND_MODE_DISABLED: {
// nothing to do here, disabled by default
} break;
case BLEND_MODE_MIX: {
attachment.enable_blend = true;
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.color_blend_op = RD::BLEND_OP_ADD;
attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
} break;
case BLEND_MODE_ADD: {
attachment.enable_blend = true;
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.color_blend_op = RD::BLEND_OP_ADD;
attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
} break;
case BLEND_MODE_SUB: {
attachment.enable_blend = true;
attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT;
attachment.color_blend_op = RD::BLEND_OP_SUBTRACT;
attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
} break;
case BLEND_MODE_MUL: {
attachment.enable_blend = true;
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.color_blend_op = RD::BLEND_OP_ADD;
attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR;
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO;
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA;
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
} break;
case BLEND_MODE_PMALPHA: {
attachment.enable_blend = true;
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.color_blend_op = RD::BLEND_OP_ADD;
attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
} break;
}
RD::PipelineColorBlendState blend_state;
blend_state.attachments.push_back(attachment);
//update pipelines
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
RD::RENDER_PRIMITIVE_TRIANGLES,
RD::RENDER_PRIMITIVE_TRIANGLES,
RD::RENDER_PRIMITIVE_TRIANGLES,
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_POINTS,
RD::RENDER_PRIMITIVE_TRIANGLES,
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_POINTS,
};
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
{ //non lit
SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE,
SHADER_VARIANT_PRIMITIVE,
SHADER_VARIANT_PRIMITIVE_POINTS,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES_POINTS },
{ //lit
SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT,
SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT },
};
RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]);
pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
}
}
valid = true;
}
void RasterizerCanvasRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
if (!p_texture.is_valid()) {
default_texture_params.erase(p_name);
} else {
default_texture_params[p_name] = p_texture;
}
}
void RasterizerCanvasRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
if (E->get().texture_order >= 0) {
order[E->get().texture_order + 100000] = E->key();
} else {
order[E->get().order] = E->key();
}
}
for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
pi.name = E->get();
p_param_list->push_back(pi);
}
}
bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
return uniforms[p_param].texture_order >= 0;
}
bool RasterizerCanvasRD::ShaderData::is_animated() const {
return false;
}
bool RasterizerCanvasRD::ShaderData::casts_shadows() const {
return false;
}
Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
}
return Variant();
}
RasterizerCanvasRD::ShaderData::ShaderData() {
valid = false;
uses_screen_texture = false;
uses_material_samplers = false;
}
RasterizerCanvasRD::ShaderData::~ShaderData() {
RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton;
ERR_FAIL_COND(!canvas_singleton);
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
canvas_singleton->shader.canvas_shader.version_free(version);
}
}
RasterizerStorageRD::ShaderData *RasterizerCanvasRD::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
return shader_data;
}
void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton;
if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
p_uniform_dirty = true;
if (uniform_buffer.is_valid()) {
RD::get_singleton()->free(uniform_buffer);
uniform_buffer = RID();
}
ubo_data.resize(shader_data->ubo_size);
if (ubo_data.size()) {
uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
}
//clear previous uniform set
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
uniform_set = RID();
}
}
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
}
uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
if ((uint32_t)texture_cache.size() != tex_uniform_count) {
texture_cache.resize(tex_uniform_count);
p_textures_dirty = true;
//clear previous uniform set
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
uniform_set = RID();
}
}
if (p_textures_dirty && tex_uniform_count) {
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw());
}
if (shader_data->ubo_size == 0 && !shader_data->uses_material_samplers) {
// This material does not require an uniform set, so don't create it.
return;
}
if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
//no reason to update uniform set, only UBO (or nothing) was needed to update
return;
}
Vector<RD::Uniform> uniforms;
{
if (shader_data->uses_material_samplers) {
//needs samplers for the material (uses custom textures) create them
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 0;
u.ids.resize(12);
RID *ids_ptr = u.ids.ptrw();
ids_ptr[0] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
ids_ptr[1] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
ids_ptr[2] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
ids_ptr[3] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
ids_ptr[4] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
ids_ptr[5] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
ids_ptr[6] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
ids_ptr[7] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
ids_ptr[8] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
ids_ptr[9] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
ids_ptr[10] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
ids_ptr[11] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
uniforms.push_back(u);
}
if (shader_data->ubo_size) {
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 1;
u.ids.push_back(uniform_buffer);
uniforms.push_back(u);
}
const RID *textures = texture_cache.ptrw();
for (uint32_t i = 0; i < tex_uniform_count; i++) {
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2 + i;
u.ids.push_back(textures[i]);
uniforms.push_back(u);
}
}
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), 1);
}
RasterizerCanvasRD::MaterialData::~MaterialData() {
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
}
if (uniform_buffer.is_valid()) {
RD::get_singleton()->free(uniform_buffer);
}
}
RasterizerStorageRD::MaterialData *RasterizerCanvasRD::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
void RasterizerCanvasRD::set_time(double p_time) {
state.time = p_time;
}
void RasterizerCanvasRD::update() {
_dispose_bindings();
}
@ -1741,133 +2151,8 @@ void RasterizerCanvasRD::update() {
RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
storage = p_storage;
{ //create default textures
RD::TextureFormat tformat;
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
tformat.width = 4;
tformat.height = 4;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
tformat.type = RD::TEXTURE_TYPE_2D;
PoolVector<uint8_t> pv;
pv.resize(16 * 4);
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 255);
pv.set(i * 4 + 1, 255);
pv.set(i * 4 + 2, 255);
pv.set(i * 4 + 3, 255);
}
{
Vector<PoolVector<uint8_t> > vpv;
vpv.push_back(pv);
default_textures.white_texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
pv.set(i * 4 + 2, 0);
pv.set(i * 4 + 3, 255);
}
{
Vector<PoolVector<uint8_t> > vpv;
vpv.push_back(pv);
default_textures.black_texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 128);
pv.set(i * 4 + 1, 128);
pv.set(i * 4 + 2, 255);
pv.set(i * 4 + 3, 255);
}
{
Vector<PoolVector<uint8_t> > vpv;
vpv.push_back(pv);
default_textures.normal_texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 255);
pv.set(i * 4 + 1, 128);
pv.set(i * 4 + 2, 255);
pv.set(i * 4 + 3, 255);
}
{
Vector<PoolVector<uint8_t> > vpv;
vpv.push_back(pv);
default_textures.aniso_texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
pv.set(i * 4 + 2, 0);
pv.set(i * 4 + 3, 0);
}
default_textures.default_multimesh_tb = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv);
}
{ //create default samplers
for (int i = 1; i < VS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
for (int j = 1; j < VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
RD::SamplerState sampler_state;
switch (i) {
case VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
sampler_state.max_lod = 0;
} break;
case VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.max_lod = 0;
} break;
case VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
} break;
case VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS: {
sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
} break;
default: {
}
}
switch (j) {
case VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
} break;
case VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
} break;
case VS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
} break;
default: {
}
}
default_samplers.samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
}
}
default_samplers.default_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
default_samplers.default_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
}
@ -1963,6 +2248,66 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
}
}
{
//shader compiler
ShaderCompilerRD::DefaultIdentifierActions actions;
actions.renames["VERTEX"] = "vertex";
actions.renames["LIGHT_VERTEX"] = "light_vertex";
actions.renames["SHADOW_VERTEX"] = "shadow_vertex";
actions.renames["UV"] = "uv";
actions.renames["POINT_SIZE"] = "gl_PointSize";
actions.renames["WORLD_MATRIX"] = "world_matrix";
actions.renames["CANVAS_MATRIX"] = "canvas_data.canvas_transform";
actions.renames["SCREEN_MATRIX"] = "canvas_data.screen_transform";
actions.renames["TIME"] = "canvas_data.time";
actions.renames["AT_LIGHT_PASS"] = "false";
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
actions.renames["COLOR"] = "color";
actions.renames["NORMAL"] = "normal";
actions.renames["NORMALMAP"] = "normal_map";
actions.renames["NORMALMAP_DEPTH"] = "normal_depth";
actions.renames["TEXTURE"] = "color_texture";
actions.renames["TEXTURE_PIXEL_SIZE"] = "draw_data.color_texture_pixel_size";
actions.renames["NORMAL_TEXTURE"] = "normal_texture";
actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture";
actions.renames["SPECULAR_SHININESS"] = "specular_shininess";
actions.renames["SCREEN_UV"] = "screen_uv";
actions.renames["SCREEN_TEXTURE"] = "screen_texture";
actions.renames["SCREEN_PIXEL_SIZE"] = "canvas_data.screen_pixel_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
actions.renames["POINT_COORD"] = "gl_PointCoord";
actions.renames["LIGHT_POSITION"] = "light_pos";
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["LIGHT_ENERGY"] = "light_energy";
actions.renames["LIGHT"] = "light";
actions.renames["SHADOW_MODULATE"] = "shadow_modulate";
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
actions.usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV";
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n";
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.custom_samplers["TEXTURE"] = "texture_sampler";
actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler";
actions.custom_samplers["SPECULAR_SHININESS_TEXTURE"] = "texture_sampler";
actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; //mipmap and filter for screen texture
actions.sampler_array_name = "material_samplers";
actions.base_texture_binding_index = 2;
actions.texture_layout_set = 1;
actions.base_uniform_string = "material.";
shader.compiler.initialize(actions);
}
{ //shadow rendering
Vector<String> versions;
versions.push_back(String()); //no versions
@ -2122,6 +2467,12 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT);
}
//create functions for shader and material
storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_shader_funcs);
storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_material_funcs);
state.time = 0;
ERR_FAIL_COND(sizeof(PushConstant) != 128);
}
@ -2180,18 +2531,4 @@ RasterizerCanvasRD::~RasterizerCanvasRD() {
RD::get_singleton()->free(shader.quad_index_buffer);
//pipelines don't need freeing, they are all gone after shaders are gone
//samplers
for (int i = 1; i < VS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
for (int j = 1; j < VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
RD::get_singleton()->free(default_samplers.samplers[i][j]);
}
}
//textures
RD::get_singleton()->free(default_textures.white_texture);
RD::get_singleton()->free(default_textures.black_texture);
RD::get_singleton()->free(default_textures.normal_texture);
RD::get_singleton()->free(default_textures.aniso_texture);
RD::get_singleton()->free(default_textures.default_multimesh_tb);
}

View file

@ -4,6 +4,7 @@
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer/rasterizer_storage_rd.h"
#include "servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.h"
#include "servers/visual/rasterizer/shader_compiler_rd.h"
#include "servers/visual/rasterizer/shaders/canvas.glsl.gen.h"
#include "servers/visual/rasterizer/shaders/canvas_occlusion.glsl.gen.h"
#include "servers/visual/rendering_device.h"
@ -112,8 +113,77 @@ class RasterizerCanvasRD : public RasterizerCanvas {
RID default_skeleton_uniform_buffer;
RID default_skeleton_texture_buffer;
ShaderCompilerRD compiler;
} shader;
struct ShaderData : public RasterizerStorageRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
BLEND_MODE_PMALPHA,
BLEND_MODE_DISABLED,
};
enum LightMode {
LIGHT_MODE_NORMAL,
LIGHT_MODE_UNSHADED,
LIGHT_MODE_LIGHT_ONLY
};
bool valid;
RID version;
PipelineVariants pipeline_variants;
String path;
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String code;
Map<StringName, RID> default_texture_params;
bool uses_screen_texture;
bool uses_material_samplers;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
ShaderData();
virtual ~ShaderData();
};
RasterizerStorageRD::ShaderData *_create_shader_func();
static RasterizerStorageRD::ShaderData *_create_shader_funcs() {
return static_cast<RasterizerCanvasRD *>(singleton)->_create_shader_func();
}
struct MaterialData : public RasterizerStorageRD::MaterialData {
ShaderData *shader_data;
RID uniform_buffer;
RID uniform_set;
Vector<RID> texture_cache;
Vector<uint8_t> ubo_data;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~MaterialData();
};
RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
return static_cast<RasterizerCanvasRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
/**************************/
/**** TEXTURE BINDINGS ****/
/**************************/
@ -168,18 +238,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
RID _create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh);
void _dispose_bindings();
struct {
RID white_texture;
RID black_texture;
RID normal_texture;
RID aniso_texture;
RID default_multimesh_tb;
} default_textures;
struct {
RID samplers[VS::CANVAS_ITEM_TEXTURE_FILTER_MAX][VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
VS::CanvasItemTextureFilter default_filter;
VS::CanvasItemTextureRepeat default_repeat;
} default_samplers;
@ -293,7 +353,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
LightCache light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM];
uint32_t light_cache_count;
RID light_uniform_set;
RID state_uniform_set_with_light;
RID state_uniform_set;
ItemStateData() {
@ -305,8 +365,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
}
~ItemStateData() {
if (light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(light_uniform_set)) {
RD::get_singleton()->free(light_uniform_set);
if (state_uniform_set_with_light.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set_with_light)) {
RD::get_singleton()->free(state_uniform_set_with_light);
}
if (state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set)) {
RD::get_singleton()->free(state_uniform_set);
@ -322,6 +382,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
float screen_transform[16];
float canvas_normal_transform[16];
float canvas_modulate[4];
float time;
float pad[3];
//uint32_t light_count;
//uint32_t pad[3];
};
@ -334,6 +396,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
uint32_t max_lights_per_render;
uint32_t max_lights_per_item;
double time;
} state;
struct PushConstant {
@ -368,7 +432,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
Item *items[MAX_RENDER_ITEMS];
Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list, uint32_t &flags);
void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights);
void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants);
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
@ -401,6 +465,7 @@ public:
void draw_window_margins(int *p_margins, RID *p_margin_textures) {}
void set_time(double p_time);
void update();
bool free(RID p_rid);
RasterizerCanvasRD(RasterizerStorageRD *p_storage);

View file

@ -46,9 +46,12 @@ void RasterizerRD::blit_render_targets_to_screen(int p_screen, const BlitToScree
}
void RasterizerRD::begin_frame(double frame_step) {
time += frame_step;
canvas->set_time(time);
}
void RasterizerRD::end_frame(bool p_swap_buffers) {
RD::get_singleton()->finalize_frame();
#warning not swapping buffers likely not an option for now, find another way
OS::get_singleton()->swap_buffers(); //probably should pass some bool to avoid display?
@ -130,6 +133,7 @@ void RasterizerRD::finalize() {
}
RasterizerRD::RasterizerRD() {
time = 0;
storage = memnew(RasterizerStorageRD);
canvas = memnew(RasterizerCanvasRD(storage));
scene = memnew(RasterizerSceneForwardRD);

View file

@ -20,6 +20,8 @@ protected:
Map<RID, RID> render_target_descriptors;
double time;
public:
RasterizerStorage *get_storage() { return storage; }
RasterizerCanvas *get_canvas() { return canvas; }

File diff suppressed because it is too large Load diff

View file

@ -3,9 +3,52 @@
#include "core/rid_owner.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer/shader_compiler_rd.h"
#include "servers/visual/rendering_device.h"
class RasterizerStorageRD : public RasterizerStorage {
public:
enum ShaderType {
SHADER_TYPE_2D,
SHADER_TYPE_3D,
SHADER_TYPE_PARTICLES,
SHADER_TYPE_MAX
};
struct ShaderData {
virtual void set_code(const String &p_Code) = 0;
virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0;
virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
virtual bool is_param_texture(const StringName &p_param) const = 0;
virtual bool is_animated() const = 0;
virtual bool casts_shadows() const = 0;
virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
virtual ~ShaderData() {}
};
typedef ShaderData *(*ShaderDataRequestFunction)();
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);
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
virtual ~MaterialData() {}
};
typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
enum DefaultRDTexture {
DEFAULT_RD_TEXTURE_WHITE,
DEFAULT_RD_TEXTURE_BLACK,
DEFAULT_RD_TEXTURE_NORMAL,
DEFAULT_RD_TEXTURE_ANISO,
DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
DEFAULT_RD_TEXTURE_MAX
};
private:
/* TEXTURE API */
struct Texture {
@ -68,6 +111,48 @@ public:
Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
RID default_rd_samplers[VS::CANVAS_ITEM_TEXTURE_FILTER_MAX][VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
/* SHADER */
struct Material;
struct Shader {
ShaderData *data;
String code;
ShaderType type;
Map<StringName, RID> default_texture_parameter;
Set<Material *> owners;
};
ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
mutable RID_Owner<Shader> shader_owner;
/* Material */
struct Material {
RID self;
MaterialData *data;
Shader *shader;
//shortcut to shader data and type
ShaderType shader_type;
bool update_requested;
bool uniform_dirty;
bool texture_dirty;
Material *update_next;
Map<StringName, Variant> params;
int32_t priority;
RID next_pass;
RasterizerScene::InstanceDependency instance_dependency;
};
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
mutable RID_Owner<Material> material_owner;
Material *material_update_list;
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
void _update_queued_materials();
/* RENDER TARGET */
struct RenderTarget {
@ -164,6 +249,13 @@ public:
return Size2i(tex->width_2d, tex->height_2d);
}
_FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
return default_rd_textures[p_texture];
}
_FORCE_INLINE_ RID sampler_rd_get_default(VS::CanvasItemTextureFilter p_filter, VS::CanvasItemTextureRepeat p_repeat) {
return default_rd_samplers[p_filter][p_repeat];
}
/* SKY API */
struct RDSurface {
@ -189,63 +281,44 @@ public:
/* SHADER API */
enum ShaderType {
SHADER_TYPE_2D,
SHADER_TYPE_3D,
SHADER_TYPE_3D_POST_PROCESS,
SHADER_TYPE_PARTICLES
};
RID shader_create();
class ShaderData {
public:
virtual void set_code(const String &p_Code) = 0;
virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0;
virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
virtual bool is_animated() const = 0;
virtual bool casts_shadows() const = 0;
virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
virtual ~ShaderData() {}
};
void shader_set_code(RID p_shader, const String &p_code);
String shader_get_code(RID p_shader) const;
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
typedef ShaderData *(ShaderDataRequestFunction)();
RID shader_create() { return RID(); }
void shader_set_code(RID p_shader, const String &p_code) {}
String shader_get_code(RID p_shader) const { return ""; }
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {}
void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {}
RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { return RID(); }
Variant shader_get_param_default(RID p_material, const StringName &p_param) const { return Variant(); }
void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;
Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
/* COMMON MATERIAL API */
struct MaterialData {
RID material_create();
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
virtual void update_parameters(const Map<StringName, Variant> &p_parameters) = 0;
virtual ~MaterialData() {}
};
typedef MaterialData *(MaterialDataRequestFunction)(ShaderData *);
void material_set_shader(RID p_material, RID p_shader);
RID material_create() { return RID(); }
void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value);
Variant material_get_param(RID p_material, const StringName &p_param) const;
void material_set_shader(RID p_shader_material, RID p_shader) {}
RID material_get_shader(RID p_shader_material) const { return RID(); }
void material_set_next_pass(RID p_material, RID p_next_material);
void material_set_render_priority(RID p_material, int priority);
void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {}
Variant material_get_param(RID p_material, const StringName &p_param) const { return Variant(); }
bool material_is_animated(RID p_material);
bool material_casts_shadows(RID p_material);
void material_set_next_pass(RID p_material, RID p_next_material) {}
void material_set_render_priority(RID p_material, int priority) {}
void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance);
bool material_is_animated(RID p_material) { return false; }
bool material_casts_shadows(RID p_material) { return false; }
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {}
void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {}
_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) {
return NULL;
} else {
return material->data;
}
}
/* MESH API */
@ -498,11 +571,8 @@ public:
float reflection_probe_get_origin_max_distance(RID p_probe) const { return 0.0; }
bool reflection_probe_renders_shadows(RID p_probe) const { return false; }
void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {}
void instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {}
void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {}
void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {}
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {}
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {}
/* GI PROBE API */
@ -551,59 +621,14 @@ public:
void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) {}
/* LIGHTMAP CAPTURE */
struct Instantiable {
SelfList<RasterizerScene::InstanceBase>::List instance_list;
_FORCE_INLINE_ void instance_change_notify(bool p_aabb = true, bool p_materials = true) {
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
while (instances) {
instances->self()->base_changed(p_aabb, p_materials);
instances = instances->next();
}
}
_FORCE_INLINE_ void instance_remove_deps() {
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
while (instances) {
SelfList<RasterizerScene::InstanceBase> *next = instances->next();
instances->self()->base_removed();
instances = next;
}
}
Instantiable() {}
virtual ~Instantiable() {
}
};
struct LightmapCapture : public Instantiable {
PoolVector<LightmapCaptureOctree> octree;
AABB bounds;
Transform cell_xform;
int cell_subdiv;
float energy;
LightmapCapture() {
energy = 1.0;
cell_subdiv = 1;
}
};
mutable RID_PtrOwner<LightmapCapture> lightmap_capture_data_owner;
void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {}
AABB lightmap_capture_get_bounds(RID p_capture) const { return AABB(); }
void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) {}
RID lightmap_capture_create() {
LightmapCapture *capture = memnew(LightmapCapture);
return lightmap_capture_data_owner.make_rid(capture);
return RID();
}
PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const {
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND_V(!capture, PoolVector<uint8_t>());
return PoolVector<uint8_t>();
}
void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {}
@ -613,9 +638,7 @@ public:
void lightmap_capture_set_energy(RID p_capture, float p_energy) {}
float lightmap_capture_get_energy(RID p_capture) const { return 0.0; }
const PoolVector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const {
const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
ERR_FAIL_COND_V(!capture, NULL);
return &capture->octree;
return NULL;
}
/* PARTICLES */
@ -686,7 +709,7 @@ public:
bool has_os_feature(const String &p_feature) const { return false; }
void update_dirty_resources() {}
void update_dirty_resources();
void set_debug_generate_wireframes(bool p_generate) {}
@ -700,8 +723,8 @@ public:
static RasterizerStorage *base_singleton;
RasterizerStorageRD(){};
~RasterizerStorageRD() {}
RasterizerStorageRD();
~RasterizerStorageRD();
};
#endif // RASTERIZER_STORAGE_RD_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,92 @@
#ifndef SHADER_COMPILER_RD_H
#define SHADER_COMPILER_RD_H
#include "core/pair.h"
#include "servers/visual/shader_language.h"
#include "servers/visual/shader_types.h"
#include "servers/visual_server.h"
class ShaderCompilerRD {
public:
struct IdentifierActions {
Map<StringName, Pair<int *, int> > render_mode_values;
Map<StringName, bool *> render_mode_flags;
Map<StringName, bool *> usage_flag_pointers;
Map<StringName, bool *> write_flag_pointers;
Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms;
};
struct GeneratedCode {
Vector<String> defines;
struct Texture {
StringName name;
ShaderLanguage::DataType type;
ShaderLanguage::ShaderNode::Uniform::Hint hint;
ShaderLanguage::TextureFilter filter;
ShaderLanguage::TextureRepeat repeat;
};
Vector<Texture> texture_uniforms;
Vector<uint32_t> uniform_offsets;
uint32_t uniform_total_size;
String uniforms;
String vertex_global;
String vertex;
String fragment_global;
String fragment;
String light;
bool uses_fragment_time;
bool uses_vertex_time;
};
struct DefaultIdentifierActions {
Map<StringName, String> renames;
Map<StringName, String> render_mode_defines;
Map<StringName, String> usage_defines;
Map<StringName, String> custom_samplers;
ShaderLanguage::TextureFilter default_filter;
ShaderLanguage::TextureRepeat default_repeat;
String sampler_array_name;
int base_texture_binding_index;
int texture_layout_set;
String base_uniform_string;
};
private:
ShaderLanguage parser;
String _get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat);
void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added);
String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning);
const ShaderLanguage::ShaderNode *shader;
const ShaderLanguage::FunctionNode *function;
StringName current_func_name;
StringName vertex_name;
StringName fragment_name;
StringName light_name;
StringName time_name;
Set<StringName> texture_functions;
Set<StringName> used_name_defines;
Set<StringName> used_flag_pointers;
Set<StringName> used_rmode_defines;
Set<StringName> internal_functions;
DefaultIdentifierActions actions;
public:
Error compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
void initialize(DefaultIdentifierActions p_actions);
ShaderCompilerRD();
};
#endif // SHADERCOMPILERRD_H

View file

@ -243,7 +243,11 @@ void ShaderRD::_compile_version(Version *p_version) {
RD::ShaderStageSource stage;
stage.shader_source = builder.as_string();
stage.shader_stage = RD::SHADER_STAGE_FRAGMENT;
#if 0
if (stage.shader_stage == RD::SHADER_STAGE_FRAGMENT && p_version->uniforms.length()) {
print_line(stage.shader_source.get_with_code_lines());
}
#endif
stages.push_back(stage);
}
@ -285,6 +289,8 @@ void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const S
version->fragment_light = p_fragment_light.utf8();
version->fragment_globals = p_fragment_globals.utf8();
version->fragment_code = p_fragment_code.utf8();
version->uniforms = p_uniforms.utf8();
version->custom_defines.clear();
for (int i = 0; i < p_custom_defines.size(); i++) {
version->custom_defines.push_back(p_custom_defines[i].utf8());

View file

@ -31,10 +31,13 @@ layout(location=3) out vec2 pixel_size_interp;
#endif
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 1, binding = 1, std140) uniform MaterialUniforms {
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
} material;
#endif
/* clang-format off */
VERTEX_SHADER_GLOBALS
@ -207,6 +210,7 @@ VERTEX_SHADER_CODE
#endif
#endif
vertex = (canvas_data.canvas_transform * vec4(vertex,0.0,1.0)).xy;
vertex_interp = vertex;
@ -243,33 +247,41 @@ layout(location=3) in vec2 pixel_size_interp;
layout(location = 0) out vec4 frag_color;
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 1, binding = 1, std140) uniform MaterialUniforms {
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
} material;
#endif
/* clang-format off */
FRAGMENT_SHADER_GLOBALS
/* clang-format on */
#ifdef LIGHT_SHADER_CODE_USED
void light_compute(
inout vec4 light,
inout vec2 light_vec,
inout float light_height,
inout vec4 light_color,
vec2 light_uv,
inout vec4 shadow_color,
vec4 light_compute(
vec3 light_vertex,
vec3 light_position,
vec3 normal,
vec2 uv,
vec4 light_color,
float light_energy,
vec4 specular_shininess,
inout vec4 shadow_modulate,
vec2 screen_uv,
vec2 uv,
vec4 color) {
vec4 light = vec4(0.0);
/* clang-format off */
LIGHT_SHADER_CODE
/* clang-format on */
return light;
}
#endif
#ifdef USE_NINEPATCH
@ -391,8 +403,13 @@ void main() {
#if defined(SCREEN_UV_USED)
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
#else
vec2 screen_uv = vec2(0.0);
#endif
vec3 light_vertex = vec3(vertex,0.0);
vec2 shadow_vertex = vertex;
{
float normal_depth = 1.0;
@ -449,14 +466,25 @@ FRAGMENT_SHADER_CODE
light_base&=0xFF;
vec2 tex_uv = (vec4(vertex,0.0,1.0) * mat4(light_array.data[light_base].matrix[0],light_array.data[light_base].matrix[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
vec4 light_color = texture(sampler2D(light_textures[i],texture_sampler),tex_uv);
vec4 light_color = texture(sampler2D(light_textures[i],texture_sampler),tex_uv);
vec4 light_base_color = light_array.data[light_base].color;
#ifdef LIGHT_SHADER_CODE_USED
vec4 shadow_modulate = vec4(1.0);
vec3 light_position = vec3(light_array.data[light_base].position,light_array.data[light_base].height);
light_color.rgb*=light_base_color.rgb;
light_color = light_compute(light_vertex,light_position,normal,light_color,light_base_color.a,specular_shininess,shadow_modulate,screen_uv,color,uv);
#else
light_color.rgb*=light_base_color.rgb*light_base_color.a;
if (normal_used) {
vec3 light_pos = vec3(light_array.data[light_base].position,light_array.data[light_base].height);
vec3 pos = vec3(vertex,0.0);
vec3 pos = light_vertex;
vec3 light_vec = normalize(light_pos-pos);
float cNdotL = max(0.0,dot(normal,light_vec));
@ -480,7 +508,7 @@ FRAGMENT_SHADER_CODE
}
}
#endif
if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
//if outside the light texture, light color is zero
light_color.a = 0.0;
@ -488,7 +516,7 @@ FRAGMENT_SHADER_CODE
if (bool(light_array.data[light_base].flags&LIGHT_FLAGS_HAS_SHADOW)) {
vec2 shadow_pos = (vec4(vertex,0.0,1.0) * mat4(light_array.data[light_base].shadow_matrix[0],light_array.data[light_base].shadow_matrix[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
vec2 shadow_pos = (vec4(shadow_vertex,0.0,1.0) * mat4(light_array.data[light_base].shadow_matrix[0],light_array.data[light_base].shadow_matrix[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
vec2 pos_norm = normalize(shadow_pos);
vec2 pos_abs = abs(pos_norm);
@ -550,7 +578,11 @@ FRAGMENT_SHADER_CODE
shadow/=13.0;
}
light_color = mix(light_color,light_array.data[light_base].shadow_color,shadow);
vec4 shadow_color = light_array.data[light_base].shadow_color;
#ifdef LIGHT_SHADER_CODE_USED
shadow_color*=shadow_modulate;
#endif
light_color = mix(light_color,shadow_color,shadow);
}

View file

@ -59,9 +59,14 @@ layout(set = 0, binding = 5) uniform textureBuffer instancing_buffer;
/* SET1: Is reserved for the material */
//
/* SET2: Canvas Item State */
#ifdef USE_MATERIAL_SAMPLERS
layout(set = 1, binding = 0) uniform sampler material_samplers[12];
#endif
/* SET2: Canvas Item State (including lighting) */
layout(set = 2, binding = 0, std140) uniform CanvasData {
@ -69,6 +74,9 @@ layout(set = 2, binding = 0, std140) uniform CanvasData {
mat4 screen_transform;
mat4 canvas_normal_transform;
vec4 canvas_modulation;
vec2 screen_pixel_size;
float time;
float time_pad;
//uint light_count;
} canvas_data;
@ -80,9 +88,6 @@ layout(set = 2, binding = 2, std140) uniform SkeletonData {
} skeleton_data;
/* SET3: Lighting */
#ifdef USE_LIGHTING
#define LIGHT_FLAGS_BLEND_MASK (3<<16)
@ -112,13 +117,21 @@ struct Light {
float pad2;
};
layout(set = 3, binding = 0, std140) uniform LightData {
layout(set = 2, binding = 3, std140) uniform LightData {
Light data[MAX_LIGHTS];
} light_array;
layout(set = 3, binding = 1) uniform texture2D light_textures[MAX_LIGHT_TEXTURES];
layout(set = 3, binding = 2) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES];
layout(set = 2, binding = 4) uniform texture2D light_textures[MAX_LIGHT_TEXTURES];
layout(set = 2, binding = 5) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES];
layout(set = 3, binding = 3) uniform sampler shadow_sampler;
layout(set = 2, binding = 6) uniform sampler shadow_sampler;
#endif
/* SET3: Render Target Data */
#ifdef SCREEN_TEXTURE_USED
layout(set = 3, binding = 1) uniform texture2D screen_texture;
#endif

View file

@ -207,6 +207,14 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"HINT_BLACK_ALBEDO_TEXTURE",
"HINT_COLOR",
"HINT_RANGE",
"FILTER_NEAREST",
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
"FILTER_LINEAR_MIPMAP",
"FILTER_NEAREST_MIPMAP_ANISO",
"FILTER_LINEAR_MIPMAP_ANISO",
"REPEAT_ENABLE",
"REPEAT_DISABLE",
"SHADER_TYPE",
"CURSOR",
"ERROR",
@ -304,8 +312,15 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
{ TK_HINT_COLOR, "hint_color" },
{ TK_HINT_RANGE, "hint_range" },
{ TK_FILTER_NEAREST, "filter_nearest" },
{ TK_FILTER_LINEAR, "filter_linear" },
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
{ TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap" },
{ TK_FILTER_NEAREST_MIPMAP_ANISO, "filter_nearest_mipmap_aniso" },
{ TK_FILTER_LINEAR_MIPMAP_ANISO, "filter_linear_mipmap_aniso" },
{ TK_REPEAT_ENABLE, "repeat_enable" },
{ TK_REPEAT_DISABLE, "repeat_disable" },
{ TK_SHADER_TYPE, "shader_type" },
{ TK_ERROR, NULL }
};
@ -2558,6 +2573,132 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
return Variant();
}
PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform &p_uniform) {
PropertyInfo pi;
switch (p_uniform.type) {
case ShaderLanguage::TYPE_VOID: pi.type = Variant::NIL; break;
case ShaderLanguage::TYPE_BOOL: pi.type = Variant::BOOL; break;
case ShaderLanguage::TYPE_BVEC2:
pi.type = Variant::INT;
pi.hint = PROPERTY_HINT_FLAGS;
pi.hint_string = "x,y";
break;
case ShaderLanguage::TYPE_BVEC3:
pi.type = Variant::INT;
pi.hint = PROPERTY_HINT_FLAGS;
pi.hint_string = "x,y,z";
break;
case ShaderLanguage::TYPE_BVEC4:
pi.type = Variant::INT;
pi.hint = PROPERTY_HINT_FLAGS;
pi.hint_string = "x,y,z,w";
break;
case ShaderLanguage::TYPE_UINT:
case ShaderLanguage::TYPE_INT: {
pi.type = Variant::INT;
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
pi.hint = PROPERTY_HINT_RANGE;
pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]);
}
} break;
case ShaderLanguage::TYPE_IVEC2:
case ShaderLanguage::TYPE_IVEC3:
case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC2:
case ShaderLanguage::TYPE_UVEC3:
case ShaderLanguage::TYPE_UVEC4: {
pi.type = Variant::POOL_INT_ARRAY;
} break;
case ShaderLanguage::TYPE_FLOAT: {
pi.type = Variant::REAL;
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
pi.hint = PROPERTY_HINT_RANGE;
pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
}
} break;
case ShaderLanguage::TYPE_VEC2: pi.type = Variant::VECTOR2; break;
case ShaderLanguage::TYPE_VEC3: pi.type = Variant::VECTOR3; break;
case ShaderLanguage::TYPE_VEC4: {
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
pi.type = Variant::COLOR;
} else {
pi.type = Variant::PLANE;
}
} break;
case ShaderLanguage::TYPE_MAT2: pi.type = Variant::TRANSFORM2D; break;
case ShaderLanguage::TYPE_MAT3: pi.type = Variant::BASIS; break;
case ShaderLanguage::TYPE_MAT4: pi.type = Variant::TRANSFORM; break;
case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: {
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture2D";
} break;
case ShaderLanguage::TYPE_SAMPLER2DARRAY:
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "TextureArray";
} break;
case ShaderLanguage::TYPE_SAMPLER3D:
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D: {
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture3D";
} break;
case ShaderLanguage::TYPE_SAMPLERCUBE: {
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "CubeMap";
} break;
}
return pi;
}
uint32_t ShaderLanguage::get_type_size(DataType p_type) {
switch (p_type) {
case TYPE_BOOL:
case TYPE_INT:
case TYPE_UINT:
case TYPE_FLOAT: return 4;
case TYPE_BVEC2:
case TYPE_IVEC2:
case TYPE_UVEC2:
case TYPE_VEC2: return 8;
case TYPE_BVEC3:
case TYPE_IVEC3:
case TYPE_UVEC3:
case TYPE_VEC3: return 12;
case TYPE_BVEC4:
case TYPE_IVEC4:
case TYPE_UVEC4:
case TYPE_VEC4: return 16;
case TYPE_MAT2: return 8;
case TYPE_MAT3: return 12;
case TYPE_MAT4: return 16;
case TYPE_SAMPLER2D:
case TYPE_ISAMPLER2D:
case TYPE_USAMPLER2D:
case TYPE_SAMPLER2DARRAY:
case TYPE_ISAMPLER2DARRAY:
case TYPE_USAMPLER2DARRAY:
case TYPE_SAMPLER3D:
case TYPE_ISAMPLER3D:
case TYPE_USAMPLER3D:
case TYPE_SAMPLERCUBE: return 4; //not really, but useful for indices
}
return 0;
}
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
Set<String> kws;
@ -2795,6 +2936,78 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
return false;
}
bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) {
for (int i = 0; shader->functions.size(); i++) {
if (shader->functions[i].name == p_name) {
ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false);
FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument];
if (arg->tex_builtin_check) {
_set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other).");
return false;
} else if (arg->tex_argument_check) {
//was checked, verify that filter and repeat are the same
if (arg->tex_argument_filter == p_filter && arg->tex_argument_repeat == p_repeat) {
return true;
} else {
_set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using textures that differ in either filter or repeat setting.");
return false;
}
} else {
arg->tex_argument_check = true;
arg->tex_argument_filter = p_filter;
arg->tex_argument_repeat = p_repeat;
for (Map<StringName, Set<int> >::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) {
for (Set<int>::Element *F = E->get().front(); F; F = F->next()) {
if (!_propagate_function_call_sampler_uniform_settings(E->key(), F->get(), p_filter, p_repeat)) {
return false;
}
}
}
return true;
}
}
}
ERR_FAIL_V(false); //bug? function not found
}
bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin) {
for (int i = 0; shader->functions.size(); i++) {
if (shader->functions[i].name == p_name) {
ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false);
FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument];
if (arg->tex_argument_check) {
_set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other).");
return false;
} else if (arg->tex_builtin_check) {
//was checked, verify that the built-in is the same
if (arg->tex_builtin == p_builtin) {
return true;
} else {
_set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using different built-ins. Only calling with the same built-in is supported.");
return false;
}
} else {
arg->tex_builtin_check = true;
arg->tex_builtin = p_builtin;
for (Map<StringName, Set<int> >::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) {
for (Set<int>::Element *F = E->get().front(); F; F = F->next()) {
if (!_propagate_function_call_sampler_builtin_reference(E->key(), F->get(), p_builtin)) {
return false;
}
}
}
return true;
}
}
}
ERR_FAIL_V(false); //bug? function not found
}
ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
Vector<Expression> expression;
@ -2944,6 +3157,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
//test if function was parsed first
int function_index = -1;
for (int i = 0; i < shader->functions.size(); i++) {
if (shader->functions[i].name == name) {
//add to current function as dependency
@ -2953,6 +3167,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break;
}
}
//see if texture arguments must connect
function_index = i;
break;
}
}
@ -2974,6 +3191,71 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
completion_class = TAG_GLOBAL; // reset sub-class
if (function_index >= 0) {
//connect texture arguments, so we can cache in the
//argument what type of filter and repeat to use
FunctionNode *call_function = shader->functions[function_index].function;
if (call_function) {
//get current base function
FunctionNode *base_function = NULL;
{
BlockNode *b = p_block;
while (b) {
if (b->parent_function) {
base_function = b->parent_function;
break;
} else {
b = b->parent_block;
}
}
}
ERR_FAIL_COND_V(!base_function, NULL); //bug, wtf
for (int i = 0; i < call_function->arguments.size(); i++) {
int argidx = i + 1;
if (argidx < func->arguments.size() && is_sampler_type(call_function->arguments[i].type)) {
//let's see where our argument comes from
Node *n = func->arguments[argidx];
ERR_CONTINUE(n->type != Node::TYPE_VARIABLE); //bug? this should always be a variable
VariableNode *vn = static_cast<VariableNode *>(n);
StringName varname = vn->name;
if (shader->uniforms.has(varname)) {
//being sampler, this either comes from a uniform
ShaderNode::Uniform *u = &shader->uniforms[varname];
ERR_CONTINUE(u->type != call_function->arguments[i].type); //this should have been validated previously
//propagate
if (!_propagate_function_call_sampler_uniform_settings(name, i, u->filter, u->repeat)) {
return NULL;
}
} else if (p_builtin_types.has(varname)) {
//a built-in
if (!_propagate_function_call_sampler_builtin_reference(name, i, varname)) {
return NULL;
}
} else {
//or this comes from an argument, but nothing else can be a sampler
bool found = false;
for (int j = 0; j < base_function->arguments.size(); j++) {
if (base_function->arguments[j].name == varname) {
if (!base_function->arguments[j].tex_argument_connect.has(call_function->name)) {
base_function->arguments.write[j].tex_argument_connect[call_function->name] = Set<int>();
}
base_function->arguments.write[j].tex_argument_connect[call_function->name].insert(i);
found = true;
break;
}
}
ERR_CONTINUE(!found);
}
}
}
}
}
expr = func;
} else {
@ -4980,7 +5262,22 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Expected ','");
return ERR_PARSE_ERROR;
}
} else if (tk.type == TK_FILTER_LINEAR) {
uniform2.filter = FILTER_LINEAR;
} else if (tk.type == TK_FILTER_NEAREST) {
uniform2.filter = FILTER_NEAREST;
} else if (tk.type == TK_FILTER_NEAREST_MIPMAP) {
uniform2.filter = FILTER_NEAREST_MIPMAP;
} else if (tk.type == TK_FILTER_LINEAR_MIPMAP) {
uniform2.filter = FILTER_LINEAR_MIPMAP;
} else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISO) {
uniform2.filter = FILTER_NEAREST_MIPMAP_ANISO;
} else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISO) {
uniform2.filter = FILTER_LINEAR_MIPMAP_ANISO;
} else if (tk.type == TK_REPEAT_DISABLE) {
uniform2.repeat = REPEAT_DISABLE;
} else if (tk.type == TK_REPEAT_ENABLE) {
uniform2.repeat = REPEAT_ENABLE;
} else {
_set_error("Expected valid type hint after ':'.");
}
@ -5293,6 +5590,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
arg.name = pname;
arg.precision = pprecision;
arg.qualifier = qualifier;
arg.tex_argument_check = false;
arg.tex_builtin_check = false;
arg.tex_argument_filter = FILTER_DEFAULT;
arg.tex_argument_repeat = REPEAT_DEFAULT;
func_node->arguments.push_back(arg);

View file

@ -155,6 +155,14 @@ public:
TK_HINT_BLACK_ALBEDO_TEXTURE,
TK_HINT_COLOR,
TK_HINT_RANGE,
TK_FILTER_NEAREST,
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
TK_FILTER_LINEAR_MIPMAP,
TK_FILTER_NEAREST_MIPMAP_ANISO,
TK_FILTER_LINEAR_MIPMAP_ANISO,
TK_REPEAT_ENABLE,
TK_REPEAT_DISABLE,
TK_SHADER_TYPE,
TK_CURSOR,
TK_ERROR,
@ -284,6 +292,22 @@ public:
TAG_ARRAY,
};
enum TextureFilter {
FILTER_NEAREST,
FILTER_LINEAR,
FILTER_NEAREST_MIPMAP,
FILTER_LINEAR_MIPMAP,
FILTER_NEAREST_MIPMAP_ANISO,
FILTER_LINEAR_MIPMAP_ANISO,
FILTER_DEFAULT,
};
enum TextureRepeat {
REPEAT_DISABLE,
REPEAT_ENABLE,
REPEAT_DEFAULT,
};
struct Node {
Node *next;
@ -485,11 +509,20 @@ public:
};
struct FunctionNode : public Node {
struct Argument {
ArgumentQualifier qualifier;
StringName name;
DataType type;
DataPrecision precision;
//for passing textures as arguments
bool tex_argument_check;
TextureFilter tex_argument_filter;
TextureRepeat tex_argument_repeat;
bool tex_builtin_check;
StringName tex_builtin;
Map<StringName, Set<int> > tex_argument_connect;
};
StringName name;
@ -555,6 +588,8 @@ public:
DataPrecision precision;
Vector<ConstantNode::Value> default_value;
Hint hint;
TextureFilter filter;
TextureRepeat repeat;
float hint_range[3];
Uniform() :
@ -562,7 +597,9 @@ public:
texture_order(0),
type(TYPE_VOID),
precision(PRECISION_DEFAULT),
hint(HINT_NONE) {
hint(HINT_NONE),
filter(FILTER_DEFAULT),
repeat(REPEAT_DEFAULT) {
hint_range[0] = 0.0f;
hint_range[1] = 1.0f;
hint_range[2] = 0.001f;
@ -631,6 +668,8 @@ public:
static bool is_scalar_type(DataType p_type);
static bool is_sampler_type(DataType p_type);
static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
static PropertyInfo uniform_to_property_info(const ShaderNode::Uniform &p_uniform);
static uint32_t get_type_size(DataType p_type);
static void get_keyword_list(List<String> *r_keywords);
static void get_builtin_funcs(List<String> *r_keywords);
@ -750,6 +789,8 @@ private:
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);

View file

@ -202,14 +202,17 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["EXTRA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CANVAS_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SCREEN_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SHADOW_VERTEX"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["LIGHT_VERTEX"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
@ -219,6 +222,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SPECULAR_SHININESS_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
@ -229,18 +234,17 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VERTEX"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_MODULATE"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VEC"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_VEC"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_HEIGHT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true;

View file

@ -209,7 +209,6 @@ public:
BIND0R(RID, material_create)
BIND2(material_set_shader, RID, RID)
BIND1RC(RID, material_get_shader, RID)
BIND3(material_set_param, RID, const StringName &, const Variant &)
BIND2RC(Variant, material_get_param, RID, const StringName &)

View file

@ -304,12 +304,12 @@ void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p
/* INSTANCING API */
void VisualServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_materials) {
void VisualServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
if (p_update_aabb)
p_instance->update_aabb = true;
if (p_update_materials)
p_instance->update_materials = true;
if (p_update_dependencies)
p_instance->update_dependencies = true;
if (p_instance->update_item.in_list())
return;
@ -338,8 +338,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
if (instance->base_type != VS::INSTANCE_NONE) {
//free anything related to that base
VSG::storage->instance_remove_dependency(instance->base, instance);
if (instance->base_type == VS::INSTANCE_GI_PROBE) {
//if gi probe is baking, wait until done baking, else race condition may happen when removing it
//from octree
@ -421,12 +419,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
}
instance->blend_values.clear();
for (int i = 0; i < instance->materials.size(); i++) {
if (instance->materials[i].is_valid()) {
VSG::storage->material_remove_instance_owner(instance->materials[i], instance);
}
}
instance->materials.clear();
}
@ -493,13 +485,13 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
}
}
VSG::storage->instance_add_dependency(p_base, instance);
instance->base = p_base;
if (scenario)
_instance_queue_update(instance, true, true);
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
VSG::storage->base_update_dependency(p_base, instance);
}
_instance_queue_update(instance, true, true);
}
void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
@ -635,21 +627,15 @@ void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surf
ERR_FAIL_COND(!instance);
if (instance->base_type == VS::INSTANCE_MESH) {
//may not have been updated yet
instance->materials.resize(VSG::storage->mesh_get_surface_count(instance->base));
//may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case
instance->materials.resize(MAX(p_surface + 1, VSG::storage->mesh_get_surface_count(instance->base)));
}
ERR_FAIL_INDEX(p_surface, instance->materials.size());
if (instance->materials[p_surface].is_valid()) {
VSG::storage->material_remove_instance_owner(instance->materials[p_surface], instance);
}
instance->materials.write[p_surface] = p_material;
instance->base_changed(false, true);
if (instance->materials[p_surface].is_valid()) {
VSG::storage->material_add_instance_owner(instance->materials[p_surface], instance);
}
_instance_queue_update(instance, false, true);
}
void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) {
@ -753,17 +739,13 @@ void VisualServerScene::instance_attach_skeleton(RID p_instance, RID p_skeleton)
if (instance->skeleton == p_skeleton)
return;
if (instance->skeleton.is_valid()) {
VSG::storage->instance_remove_skeleton(instance->skeleton, instance);
}
instance->skeleton = p_skeleton;
if (instance->skeleton.is_valid()) {
VSG::storage->instance_add_skeleton(instance->skeleton, instance);
if (p_skeleton.is_valid()) {
//update the dependency now, so if cleared, we remove it
VSG::storage->skeleton_update_dependency(p_skeleton, instance);
}
_instance_queue_update(instance, true);
_instance_queue_update(instance, true, true);
}
void VisualServerScene::instance_set_exterior(RID p_instance, bool p_enabled) {
@ -875,22 +857,15 @@ void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instanc
ERR_FAIL_COND(!instance);
instance->cast_shadows = p_shadow_casting_setting;
instance->base_changed(false, true); // to actually compute if shadows are visible or not
_instance_queue_update(instance, false, true);
}
void VisualServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
if (instance->material_override.is_valid()) {
VSG::storage->material_remove_instance_owner(instance->material_override, instance);
}
instance->material_override = p_material;
instance->base_changed(false, true);
if (instance->material_override.is_valid()) {
VSG::storage->material_add_instance_owner(instance->material_override, instance);
}
_instance_queue_update(instance, false, true);
}
void VisualServerScene::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
@ -3291,17 +3266,22 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
_update_instance_aabb(p_instance);
}
if (p_instance->update_materials) {
if (p_instance->update_dependencies) {
p_instance->instance_increase_version();
if (p_instance->base.is_valid()) {
VSG::storage->base_update_dependency(p_instance->base, p_instance);
}
if (p_instance->material_override.is_valid()) {
VSG::storage->material_update_dependency(p_instance->material_override, p_instance);
}
if (p_instance->base_type == VS::INSTANCE_MESH) {
//remove materials no longer used and un-own them
int new_mat_count = VSG::storage->mesh_get_surface_count(p_instance->base);
for (int i = p_instance->materials.size() - 1; i >= new_mat_count; i--) {
if (p_instance->materials[i].is_valid()) {
VSG::storage->material_remove_instance_owner(p_instance->materials[i], p_instance);
}
}
p_instance->materials.resize(new_mat_count);
int new_blend_shape_count = VSG::storage->mesh_get_blend_shape_count(p_instance->base);
@ -3348,6 +3328,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (VSG::storage->material_is_animated(mat)) {
is_animated = true;
}
VSG::storage->material_update_dependency(mat, p_instance);
}
}
@ -3378,6 +3360,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (VSG::storage->material_is_animated(mat)) {
is_animated = true;
}
VSG::storage->material_update_dependency(mat, p_instance);
}
}
@ -3394,6 +3378,11 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (mat.is_valid() && VSG::storage->material_is_animated(mat)) {
is_animated = true;
}
if (mat.is_valid()) {
VSG::storage->material_update_dependency(mat, p_instance);
}
} else if (p_instance->base_type == VS::INSTANCE_PARTICLES) {
bool cast_shadows = false;
@ -3422,6 +3411,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (VSG::storage->material_is_animated(mat)) {
is_animated = true;
}
VSG::storage->material_update_dependency(mat, p_instance);
}
}
}
@ -3444,6 +3435,12 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
geom->material_is_animated = is_animated;
}
if (p_instance->skeleton.is_valid()) {
VSG::storage->skeleton_update_dependency(p_instance->skeleton, p_instance);
}
p_instance->clean_up_dependencies();
}
_instance_update_list.remove(&p_instance->update_item);
@ -3451,7 +3448,7 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
_update_instance(p_instance);
p_instance->update_aabb = false;
p_instance->update_materials = false;
p_instance->update_dependencies = false;
}
void VisualServerScene::update_dirty_instances() {

View file

@ -151,7 +151,7 @@ public:
//aabb stuff
bool update_aabb;
bool update_materials;
bool update_dependencies;
SelfList<Instance> update_item;
@ -174,14 +174,18 @@ public:
InstanceBaseData *base_data;
virtual void base_removed() {
singleton->instance_set_base(self, RID());
virtual void dependency_deleted(RID p_dependency) {
if (p_dependency == base) {
singleton->instance_set_base(self, RID());
} else if (p_dependency == skeleton) {
singleton->instance_attach_skeleton(self, RID());
} else {
singleton->_instance_queue_update(this, false, true);
}
}
virtual void base_changed(bool p_aabb, bool p_materials) {
singleton->_instance_queue_update(this, p_aabb, p_materials);
virtual void dependency_changed(bool p_aabb, bool p_dependencies) {
singleton->_instance_queue_update(this, p_aabb, p_dependencies);
}
Instance() :
@ -192,7 +196,7 @@ public:
scenario = NULL;
update_aabb = false;
update_materials = false;
update_dependencies = false;
extra_margin = 0;
@ -222,7 +226,7 @@ public:
};
SelfList<Instance>::List _instance_update_list;
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_materials = false);
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
struct InstanceGeometryData : public InstanceBaseData {

View file

@ -140,7 +140,6 @@ public:
FUNCRID(material)
FUNC2(material_set_shader, RID, RID)
FUNC1RC(RID, material_get_shader, RID)
FUNC3(material_set_param, RID, const StringName &, const Variant &)
FUNC2RC(Variant, material_get_param, RID, const StringName &)

View file

@ -1652,7 +1652,6 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("material_create"), &VisualServer::material_create);
ClassDB::bind_method(D_METHOD("material_set_shader", "shader_material", "shader"), &VisualServer::material_set_shader);
ClassDB::bind_method(D_METHOD("material_get_shader", "shader_material"), &VisualServer::material_get_shader);
ClassDB::bind_method(D_METHOD("material_set_param", "material", "parameter", "value"), &VisualServer::material_set_param);
ClassDB::bind_method(D_METHOD("material_get_param", "material", "parameter"), &VisualServer::material_get_param);
ClassDB::bind_method(D_METHOD("material_set_render_priority", "material", "priority"), &VisualServer::material_set_render_priority);
@ -2365,6 +2364,7 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false);
GLOBAL_DEF("rendering/quality/filters/max_anisotropy", 4);
}
VisualServer::~VisualServer() {

View file

@ -192,7 +192,6 @@ public:
virtual RID material_create() = 0;
virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
virtual RID material_get_shader(RID p_shader_material) const = 0;
virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0;
virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0;
@ -884,8 +883,10 @@ public:
CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item
CANVAS_ITEM_TEXTURE_FILTER_NEAREST,
CANVAS_ITEM_TEXTURE_FILTER_LINEAR,
CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS,
CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS,
CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS,
CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC,
CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC,
CANVAS_ITEM_TEXTURE_FILTER_MAX
};