mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 04:06:14 +00:00
Completed material/2D shader support (missing SCREEN_TEXTURE)
This commit is contained in:
parent
50e9befb88
commit
8bbbb97336
@ -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) {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -39,6 +39,7 @@ class VulkanContext {
|
||||
int frame_index;
|
||||
VkFence fences[FRAME_LAG];
|
||||
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||
VkPhysicalDeviceFeatures physical_device_features;
|
||||
|
||||
typedef struct {
|
||||
VkImage image;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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() {}
|
||||
};
|
||||
|
@ -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 *¤t_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 *¤t_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);
|
||||
}
|
||||
|
@ -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 *¤t_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 *¤t_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);
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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
|
||||
|
1003
servers/visual/rasterizer/shader_compiler_rd.cpp
Normal file
1003
servers/visual/rasterizer/shader_compiler_rd.cpp
Normal file
File diff suppressed because it is too large
Load Diff
92
servers/visual/rasterizer/shader_compiler_rd.h
Normal file
92
servers/visual/rasterizer/shader_compiler_rd.h
Normal 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
|
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 &)
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 &)
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user