Skip to content

Commit

Permalink
Added stencil support to VisualShader
Browse files Browse the repository at this point in the history
  • Loading branch information
apples committed Aug 23, 2023
1 parent be2f6cf commit 8dd46d0
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 0 deletions.
129 changes: 129 additions & 0 deletions scene/resources/visual_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,35 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
}
_queue_update();
return true;
} else if (prop_name == "stencil/enabled") {
stencil_enabled = bool(p_value);
_queue_update();
notify_property_list_changed();
return true;
} else if (prop_name == "stencil/reference") {
stencil_reference = int(p_value);
_queue_update();
return true;
} else if (prop_name.begins_with("stencil_flags/")) {
StringName flag = prop_name.get_slicec('/', 1);
bool enable = p_value;
if (enable) {
stencil_flags.insert(flag);
} else {
stencil_flags.erase(flag);
}
_queue_update();
return true;
} else if (prop_name.begins_with("stencil_modes/")) {
String mode_name = prop_name.get_slicec('/', 1);
int value = p_value;
if (value == 0) {
stencil_modes.erase(mode_name); // It's default anyway, so don't store it.
} else {
stencil_modes[mode_name] = value;
}
_queue_update();
return true;
} else if (prop_name.begins_with("varyings/")) {
String var_name = prop_name.get_slicec('/', 1);
Varying value = Varying();
Expand Down Expand Up @@ -1503,6 +1532,24 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = 0;
}
return true;
} else if (prop_name == "stencil/enabled") {
r_ret = stencil_enabled;
return true;
} else if (prop_name == "stencil/reference") {
r_ret = stencil_reference;
return true;
} else if (prop_name.begins_with("stencil_flags/")) {
StringName flag = prop_name.get_slicec('/', 1);
r_ret = stencil_flags.has(flag);
return true;
} else if (prop_name.begins_with("stencil_modes/")) {
String mode_name = prop_name.get_slicec('/', 1);
if (stencil_modes.has(mode_name)) {
r_ret = stencil_modes[mode_name];
} else {
r_ret = 0;
}
return true;
} else if (prop_name.begins_with("varyings/")) {
String var_name = prop_name.get_slicec('/', 1);
if (varyings.has(var_name)) {
Expand Down Expand Up @@ -1604,6 +1651,47 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("flags"), E)));
}

const Vector<ShaderLanguage::ModeInfo> &smodes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(shader_mode));

if (smodes.size() > 0) {
p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("stencil"), PNAME("enabled"))));

uint32_t stencil_prop_usage = stencil_enabled ? PROPERTY_USAGE_DEFAULT : PROPERTY_USAGE_STORAGE;

p_list->push_back(PropertyInfo(Variant::INT, vformat("%s/%s", PNAME("stencil"), PNAME("reference")), PROPERTY_HINT_RANGE, "0,255,1", stencil_prop_usage));

HashMap<String, String> stencil_enums;
HashSet<String> stencil_toggles;

for (int i = 0; i < smodes.size(); i++) {
const ShaderLanguage::ModeInfo &info = smodes[i];

if (!info.options.is_empty()) {
const String begin = String(info.name);

for (int j = 0; j < info.options.size(); j++) {
const String option = String(info.options[j]).capitalize();

if (!stencil_enums.has(begin)) {
stencil_enums[begin] = option;
} else {
stencil_enums[begin] += "," + option;
}
}
} else {
stencil_toggles.insert(String(info.name));
}
}

for (const KeyValue<String, String> &E : stencil_enums) {
p_list->push_back(PropertyInfo(Variant::INT, vformat("%s/%s", PNAME("stencil_modes"), E.key), PROPERTY_HINT_ENUM, E.value, stencil_prop_usage));
}

for (const String &E : stencil_toggles) {
p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("stencil_flags"), E), PROPERTY_HINT_NONE, "", stencil_prop_usage));
}
}

for (const KeyValue<String, Varying> &E : varyings) {
p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", PNAME("varyings"), E.key)));
}
Expand Down Expand Up @@ -2256,6 +2344,47 @@ void VisualShader::_update_shader() const {
global_code += "render_mode " + render_mode + ";\n\n";
}

const Vector<ShaderLanguage::ModeInfo> &smodes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(shader_mode));

if (smodes.size() > 0 && stencil_enabled) {
String stencil_mode;

Vector<String> flag_names;

// Add enum modes first.
for (int i = 0; i < smodes.size(); i++) {
const ShaderLanguage::ModeInfo &info = smodes[i];
const String temp = String(info.name);

if (!info.options.is_empty()) {
if (stencil_modes.has(temp) && stencil_modes[temp] < info.options.size()) {
if (!stencil_mode.is_empty()) {
stencil_mode += ", ";
}
stencil_mode += temp + "_" + info.options[stencil_modes[temp]];
}
} else if (stencil_flags.has(temp)) {
flag_names.push_back(temp);
}
}

// Add flags afterward.
for (int i = 0; i < flag_names.size(); i++) {
if (!stencil_mode.is_empty()) {
stencil_mode += ", ";
}
stencil_mode += flag_names[i];
}

// Add reference value.
if (!stencil_mode.is_empty()) {
stencil_mode += ", ";
}
stencil_mode += itos(stencil_reference);

global_code += "stencil_mode " + stencil_mode + ";\n\n";
}

static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };

String global_expressions;
Expand Down
5 changes: 5 additions & 0 deletions scene/resources/visual_shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ class VisualShader : public Shader {
HashMap<String, int> modes;
HashSet<StringName> flags;

bool stencil_enabled = false;
HashMap<String, int> stencil_modes;
HashSet<StringName> stencil_flags;
int stencil_reference = 1;

HashMap<String, Varying> varyings;
List<Varying> varyings_list;

Expand Down

0 comments on commit 8dd46d0

Please sign in to comment.