summaryrefslogtreecommitdiff
path: root/servers/visual
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual')
-rw-r--r--servers/visual/rasterizer.h3
-rw-r--r--servers/visual/shader_language.cpp136
-rw-r--r--servers/visual/shader_language.h22
-rw-r--r--servers/visual/shader_types.cpp3
-rw-r--r--servers/visual/visual_server_raster.h1
-rw-r--r--servers/visual/visual_server_scene.cpp74
-rw-r--r--servers/visual/visual_server_wrap_mt.h1
7 files changed, 213 insertions, 27 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 187a0b180b..0784fb1049 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -335,6 +335,9 @@ public:
virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) = 0;
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
+ virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0;
+ virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0;
+
virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 0684cb1701..c7b02c92f7 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -79,7 +79,11 @@ String ShaderLanguage::get_operator_text(Operator p_op) {
"|",
"^",
"~",
- "++"
+ "++",
+ "--",
+ "?",
+ ":",
+ "++",
"--",
"()",
"construct",
@@ -3116,6 +3120,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
tk = _get_token();
+ VariableDeclarationNode *vardecl = alloc_node<VariableDeclarationNode>();
+ vardecl->datatype=type;
+ vardecl->precision=precision;
+
+ p_block->statements.push_back(vardecl);
+
while (true) {
if (tk.type != TK_IDENTIFIER) {
@@ -3133,8 +3143,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
var.type = type;
var.precision = precision;
var.line = tk_line;
+
p_block->variables[name] = var;
+ VariableDeclarationNode::Declaration decl;
+
+ decl.name=name;
+ decl.initializer=NULL;
+
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
@@ -3143,22 +3159,19 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
if (!n)
return ERR_PARSE_ERROR;
- OperatorNode *assign = alloc_node<OperatorNode>();
- VariableNode *vnode = alloc_node<VariableNode>();
- vnode->name = name;
- vnode->datatype_cache = type;
- assign->arguments.push_back(vnode);
- assign->arguments.push_back(n);
- assign->op = OP_ASSIGN;
- p_block->statements.push_back(assign);
- tk = _get_token();
+ decl.initializer = n;
- if (!_validate_operator(assign)) {
- _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(type) + "'");
+ if (var.type!=n->get_datatype()) {
+ _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'");
return ERR_PARSE_ERROR;
+
}
+ tk = _get_token();
+
}
+ vardecl->declarations.push_back(decl);
+
if (tk.type == TK_COMMA) {
tk = _get_token();
//another variable
@@ -3221,7 +3234,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
//if () {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after if");
+ _set_error("Expected '(' after while");
return ERR_PARSE_ERROR;
}
@@ -3243,7 +3256,64 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
cf->blocks.push_back(block);
p_block->statements.push_back(cf);
- Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue);
+ Error err = _parse_block(block, p_builtin_types, true, true, true);
+ if (err)
+ return err;
+ } else if (tk.type == TK_CF_FOR) {
+ //if () {}
+ tk = _get_token();
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after for");
+ return ERR_PARSE_ERROR;
+ }
+
+ ControlFlowNode *cf = alloc_node<ControlFlowNode>();
+ cf->flow_op = FLOW_OP_FOR;
+
+ BlockNode *init_block = alloc_node<BlockNode>();
+ init_block->parent_block = p_block;
+ init_block->single_statement=true;
+ cf->blocks.push_back(init_block);
+ if (_parse_block(init_block,p_builtin_types,true,false,false)!=OK) {
+ return ERR_PARSE_ERROR;
+ }
+
+ Node *n = _parse_and_reduce_expression(init_block, p_builtin_types);
+ if (!n)
+ return ERR_PARSE_ERROR;
+
+ if (n->get_datatype()!=TYPE_BOOL) {
+ _set_error("Middle expression is expected to be boolean.");
+ return ERR_PARSE_ERROR;
+
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ _set_error("Expected ';' after middle expression");
+ return ERR_PARSE_ERROR;
+ }
+
+ cf->expressions.push_back(n);
+
+ n = _parse_and_reduce_expression(init_block, p_builtin_types);
+ if (!n)
+ return ERR_PARSE_ERROR;
+
+ cf->expressions.push_back(n);
+
+ tk = _get_token();
+ if (tk.type != TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' after third expression");
+ return ERR_PARSE_ERROR;
+ }
+
+ BlockNode *block = alloc_node<BlockNode>();
+ block->parent_block = p_block;
+ cf->blocks.push_back(block);
+ p_block->statements.push_back(cf);
+
+ Error err = _parse_block(block, p_builtin_types, true, true, true);
if (err)
return err;
@@ -3320,6 +3390,44 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
}
p_block->statements.push_back(flow);
+ } else if (tk.type == TK_CF_BREAK) {
+
+
+ if (!p_can_break) {
+ //all is good
+ _set_error("Breaking is not allowed here");
+ }
+
+ ControlFlowNode *flow = alloc_node<ControlFlowNode>();
+ flow->flow_op = FLOW_OP_BREAK;
+
+ pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ //all is good
+ _set_error("Expected ';' after break");
+ }
+
+ p_block->statements.push_back(flow);
+ } else if (tk.type == TK_CF_CONTINUE) {
+
+
+ if (!p_can_break) {
+ //all is good
+ _set_error("Contiuning is not allowed here");
+ }
+
+ ControlFlowNode *flow = alloc_node<ControlFlowNode>();
+ flow->flow_op = FLOW_OP_CONTINUE;
+
+ pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ //all is good
+ _set_error("Expected ';' after continue");
+ }
+
+ p_block->statements.push_back(flow);
} else {
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index f00b4c5a97..50f5cebeaa 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -266,6 +266,7 @@ public:
TYPE_FUNCTION,
TYPE_BLOCK,
TYPE_VARIABLE,
+ TYPE_VARIABLE_DECLARATION,
TYPE_CONSTANT,
TYPE_OPERATOR,
TYPE_CONTROL_FLOW,
@@ -315,6 +316,25 @@ public:
}
};
+ struct VariableDeclarationNode : public Node {
+
+ DataPrecision precision;
+ DataType datatype;
+
+ struct Declaration {
+
+ StringName name;
+ Node *initializer;
+ };
+
+ Vector<Declaration> declarations;
+ virtual DataType get_datatype() const { return datatype; }
+
+ VariableDeclarationNode() {
+ type = TYPE_VARIABLE_DECLARATION;
+ }
+ };
+
struct ConstantNode : public Node {
DataType datatype;
@@ -346,10 +366,12 @@ public:
Map<StringName, Variable> variables;
List<Node *> statements;
+ bool single_statement;
BlockNode() {
type = TYPE_BLOCK;
parent_block = NULL;
parent_function = NULL;
+ single_statement=false;
}
};
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index ef0d063f83..91c5d430f5 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -102,6 +102,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
@@ -137,7 +138,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded");
shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert");
- shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_half_lambert");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert_wrap");
shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_oren_nayar");
shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_burley");
shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_toon");
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 3953bc5f48..7c7ce46268 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -795,6 +795,7 @@ public:
BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
BIND2(light_directional_set_blend_splits, RID, bool)
+ BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
/* PROBE API */
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 0d70b7fc0e..e791f7b443 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -886,12 +886,55 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
float max_distance = p_cam_projection.get_z_far();
float shadow_max = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
- if (shadow_max > 0) {
+ if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
max_distance = MIN(shadow_max, max_distance);
}
max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
+ float min_distance = MIN(p_cam_projection.get_z_near(),max_distance);
- float range = max_distance - p_cam_projection.get_z_near();
+ VS::LightDirectionalShadowDepthRangeMode depth_range_mode = VSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
+
+ if (depth_range_mode==VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) {
+ //optimize min/max
+ Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
+ int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
+ Plane base(p_cam_transform.origin,-p_cam_transform.basis.get_axis(2));
+ //check distance max and min
+
+ bool found_items=false;
+ float z_max=-1e20;
+ float z_min=1e20;
+
+ for(int i=0;i<cull_count;i++) {
+
+ Instance *instance = instance_shadow_cull_result[i];
+ if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+ continue;
+ }
+
+ float max,min;
+ instance->transformed_aabb.project_range_in_plane(base, min, max);
+
+ if (max>z_max) {
+ z_max=max;
+ }
+
+ if (min<z_min) {
+ z_min=min;
+ }
+
+ found_items=true;
+ }
+
+ if (found_items) {
+ min_distance=MAX(min_distance,z_min);
+ max_distance=MIN(max_distance,z_max);
+ }
+
+ }
+
+
+ float range = max_distance - min_distance;
int splits = 0;
switch (VSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
@@ -902,9 +945,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
float distances[5];
- distances[0] = p_cam_projection.get_z_near();
+ distances[0] = min_distance;
for (int i = 0; i < splits; i++) {
- distances[i + 1] = p_cam_projection.get_z_near() + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
+ distances[i + 1] = min_distance + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
};
distances[splits] = max_distance;
@@ -984,8 +1027,6 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
{
//camera viewport stuff
- //this trick here is what stabilizes the shadow (make potential jaggies to not move)
- //at the cost of some wasted resolution. Still the quality increase is very well worth it
Vector3 center;
@@ -1006,7 +1047,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
radius = d;
}
- radius *= texture_size / (texture_size - 2.0); //add a texel by each side, so stepified texture will always fit
+ radius *= texture_size / (texture_size - 2.0); //add a texel by each side
if (i == 0) {
first_radius = radius;
@@ -1021,12 +1062,19 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
z_max_cam = z_vec.dot(center) + radius;
z_min_cam = z_vec.dot(center) - radius;
- float unit = radius * 2.0 / texture_size;
+ if (depth_range_mode==VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
+ //this trick here is what stabilizes the shadow (make potential jaggies to not move)
+ //at the cost of some wasted resolution. Still the quality increase is very well worth it
+
+ float unit = radius * 2.0 / texture_size;
+
+ x_max_cam = Math::stepify(x_max_cam, unit);
+ x_min_cam = Math::stepify(x_min_cam, unit);
+ y_max_cam = Math::stepify(y_max_cam, unit);
+ y_min_cam = Math::stepify(y_min_cam, unit);
+ }
+
- x_max_cam = Math::stepify(x_max_cam, unit);
- x_min_cam = Math::stepify(x_min_cam, unit);
- y_max_cam = Math::stepify(y_max_cam, unit);
- y_min_cam = Math::stepify(y_min_cam, unit);
}
//now that we now all ranges, we can proceed to make the light frustum planes, for culling octree
@@ -1069,6 +1117,8 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
}
{
+
+
CameraMatrix ortho_camera;
real_t half_x = (x_max_cam - x_min_cam) * 0.5;
real_t half_y = (y_max_cam - y_min_cam) * 0.5;
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index f24049be92..5cf941b93d 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -233,6 +233,7 @@ public:
FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
FUNC2(light_directional_set_blend_splits, RID, bool)
+ FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
/* PROBE API */