mirror of
https://github.com/godotengine/godot
synced 2024-09-05 05:58:29 +00:00
Alpha Hash and Alpha2Coverage Implementation
This commit is contained in:
parent
0b910cd8b7
commit
e5d7c7d5fc
|
@ -193,6 +193,20 @@ static inline unsigned int nearest_shift(unsigned int p_number) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// constexpr function to find the floored log2 of a number
|
||||
template <typename T>
|
||||
constexpr T floor_log2(T x) {
|
||||
return x < 2 ? x : 1 + floor_log2(x >> 1);
|
||||
}
|
||||
|
||||
// Get the number of bits needed to represent the number.
|
||||
// IE, if you pass in 8, you will get 4.
|
||||
// If you want to know how many bits are needed to store 8 values however, pass in (8 - 1).
|
||||
template <typename T>
|
||||
constexpr T get_num_bits(T x) {
|
||||
return floor_log2(x);
|
||||
}
|
||||
|
||||
// Swap 16, 32 and 64 bits value for endianness.
|
||||
#if defined(__GNUC__)
|
||||
#define BSWAP16(x) __builtin_bswap16(x)
|
||||
|
|
|
@ -81,6 +81,15 @@
|
|||
<member name="albedo_texture" type="Texture2D" setter="set_texture" getter="get_texture">
|
||||
Texture to multiply by [member albedo_color]. Used for basic texturing of objects.
|
||||
</member>
|
||||
<member name="alpha_antialiasing_edge" type="float" setter="set_alpha_antialiasing_edge" getter="get_alpha_antialiasing_edge">
|
||||
Threshold at which antialiasing will by applied on the alpha channel.
|
||||
</member>
|
||||
<member name="alpha_antialiasing_mode" type="int" setter="set_alpha_antialiasing" getter="get_alpha_antialiasing" enum="BaseMaterial3D.AlphaAntiAliasing">
|
||||
The type of alpha antialiasing to apply. See [enum AlphaAntiAliasing].
|
||||
</member>
|
||||
<member name="alpha_hash_scale" type="float" setter="set_alpha_hash_scale" getter="get_alpha_hash_scale">
|
||||
The hashing scale for Alpha Hash. Recommended values between [code]0[/code] and [code]2[/code].
|
||||
</member>
|
||||
<member name="alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold">
|
||||
Threshold at which the alpha scissor will discard values.
|
||||
</member>
|
||||
|
@ -486,10 +495,13 @@
|
|||
<constant name="TRANSPARENCY_ALPHA_SCISSOR" value="2" enum="Transparency">
|
||||
The material will cut off all values below a threshold, the rest will remain opaque.
|
||||
</constant>
|
||||
<constant name="TRANSPARENCY_ALPHA_DEPTH_PRE_PASS" value="3" enum="Transparency">
|
||||
<constant name="TRANSPARENCY_ALPHA_HASH" value="3" enum="Transparency">
|
||||
The material will cut off all values below a spatially-deterministic threshold, the rest will remain opaque.
|
||||
</constant>
|
||||
<constant name="TRANSPARENCY_ALPHA_DEPTH_PRE_PASS" value="4" enum="Transparency">
|
||||
The material will use the texture's alpha value for transparency, but will still be rendered in the pre-pass.
|
||||
</constant>
|
||||
<constant name="TRANSPARENCY_MAX" value="4" enum="Transparency">
|
||||
<constant name="TRANSPARENCY_MAX" value="5" enum="Transparency">
|
||||
Represents the size of the [enum Transparency] enum.
|
||||
</constant>
|
||||
<constant name="SHADING_MODE_UNSHADED" value="0" enum="ShadingMode">
|
||||
|
@ -555,6 +567,15 @@
|
|||
<constant name="BLEND_MODE_MUL" value="3" enum="BlendMode">
|
||||
The color of the object is multiplied by the background.
|
||||
</constant>
|
||||
<constant name="ALPHA_ANTIALIASING_OFF" value="0" enum="AlphaAntiAliasing">
|
||||
Disables Alpha AntiAliasing for the material.
|
||||
</constant>
|
||||
<constant name="ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE" value="1" enum="AlphaAntiAliasing">
|
||||
Enables AlphaToCoverage. Alpha values in the material are passed to the AntiAliasing sample mask.
|
||||
</constant>
|
||||
<constant name="ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE" value="2" enum="AlphaAntiAliasing">
|
||||
Enables AlphaToCoverage and forces all non-zero alpha values to [code]1[/code]. Alpha values in the material are passed to the AntiAliasing sample mask.
|
||||
</constant>
|
||||
<constant name="DEPTH_DRAW_OPAQUE_ONLY" value="0" enum="DepthDrawMode">
|
||||
Default depth draw mode. Depth is drawn only for opaque objects.
|
||||
</constant>
|
||||
|
|
|
@ -324,7 +324,6 @@ void BaseMaterial3D::init_shaders() {
|
|||
shader_names->rim_texture_channel = "rim_texture_channel";
|
||||
shader_names->heightmap_texture_channel = "heightmap_texture_channel";
|
||||
shader_names->refraction_texture_channel = "refraction_texture_channel";
|
||||
shader_names->alpha_scissor_threshold = "alpha_scissor_threshold";
|
||||
|
||||
shader_names->transmittance_color = "transmittance_color";
|
||||
shader_names->transmittance_curve = "transmittance_curve";
|
||||
|
@ -349,6 +348,12 @@ void BaseMaterial3D::init_shaders() {
|
|||
shader_names->texture_names[TEXTURE_DETAIL_ALBEDO] = "texture_detail_albedo";
|
||||
shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal";
|
||||
shader_names->texture_names[TEXTURE_ORM] = "texture_orm";
|
||||
|
||||
shader_names->alpha_scissor_threshold = "alpha_scissor_threshold";
|
||||
shader_names->alpha_hash_scale = "alpha_hash_scale";
|
||||
|
||||
shader_names->alpha_antialiasing_edge = "alpha_antialiasing_edge";
|
||||
shader_names->albedo_texture_size = "albedo_texture_size";
|
||||
}
|
||||
|
||||
Ref<StandardMaterial3D> BaseMaterial3D::materials_for_2d[BaseMaterial3D::MAX_MATERIALS_FOR_2D];
|
||||
|
@ -435,6 +440,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
case BLEND_MODE_MUL:
|
||||
code += "blend_mul";
|
||||
break;
|
||||
case BLEND_MODE_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
|
||||
DepthDrawMode ddm = depth_draw_mode;
|
||||
|
@ -452,10 +459,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
case DEPTH_DRAW_DISABLED:
|
||||
code += ",depth_draw_never";
|
||||
break;
|
||||
}
|
||||
|
||||
if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) {
|
||||
code += ",depth_prepass_alpha";
|
||||
case DEPTH_DRAW_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
|
||||
switch (cull_mode) {
|
||||
|
@ -468,6 +473,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
case CULL_DISABLED:
|
||||
code += ",cull_disabled";
|
||||
break;
|
||||
case CULL_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
switch (diffuse_mode) {
|
||||
case DIFFUSE_BURLEY:
|
||||
|
@ -485,6 +492,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
case DIFFUSE_TOON:
|
||||
code += ",diffuse_toon";
|
||||
break;
|
||||
case DIFFUSE_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
switch (specular_mode) {
|
||||
case SPECULAR_SCHLICK_GGX:
|
||||
|
@ -502,6 +511,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
case SPECULAR_DISABLED:
|
||||
code += ",specular_disabled";
|
||||
break;
|
||||
case SPECULAR_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
if (features[FEATURE_SUBSURFACE_SCATTERING] && flags[FLAG_SUBSURFACE_MODE_SKIN]) {
|
||||
code += ",sss_mode_skin";
|
||||
|
@ -525,6 +536,23 @@ void BaseMaterial3D::_update_shader() {
|
|||
if (flags[FLAG_USE_SHADOW_TO_OPACITY]) {
|
||||
code += ",shadow_to_opacity";
|
||||
}
|
||||
|
||||
if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) {
|
||||
code += ",depth_prepass_alpha";
|
||||
}
|
||||
|
||||
// Although its technically possible to do alpha antialiasing without using alpha hash or alpha scissor,
|
||||
// it is restricted in the base material because it has no use, and abusing it with regular Alpha blending can
|
||||
// saturate the MSAA mask
|
||||
if (transparency == TRANSPARENCY_ALPHA_HASH || transparency == TRANSPARENCY_ALPHA_SCISSOR) {
|
||||
// alpha antialiasing is only useful in ALPHA_HASH or ALPHA_SCISSOR
|
||||
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
|
||||
code += ",alpha_to_coverage";
|
||||
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
|
||||
code += ",alpha_to_coverage_and_one";
|
||||
}
|
||||
}
|
||||
|
||||
code += ";\n";
|
||||
|
||||
code += "uniform vec4 albedo : hint_color;\n";
|
||||
|
@ -541,8 +569,18 @@ void BaseMaterial3D::_update_shader() {
|
|||
code += "uniform float distance_fade_max;\n";
|
||||
}
|
||||
|
||||
// alpha scissor is only valid if there is not antialiasing edge
|
||||
// alpha hash is valid whenever, but not with alpha scissor
|
||||
if (transparency == TRANSPARENCY_ALPHA_SCISSOR) {
|
||||
code += "uniform float alpha_scissor_threshold;\n";
|
||||
} else if (transparency == TRANSPARENCY_ALPHA_HASH) {
|
||||
code += "uniform float alpha_hash_scale;\n";
|
||||
}
|
||||
// if alpha antialiasing isn't off, add in the edge variable
|
||||
if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF &&
|
||||
(transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH)) {
|
||||
code += "uniform float alpha_antialiasing_edge;\n";
|
||||
code += "uniform ivec2 albedo_texture_size;\n";
|
||||
}
|
||||
|
||||
code += "uniform float point_size : hint_range(0,128);\n";
|
||||
|
@ -568,6 +606,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
case TEXTURE_CHANNEL_GRAYSCALE: {
|
||||
code += "uniform sampler2D texture_roughness : hint_roughness_gray," + texfilter_str + ";\n";
|
||||
} break;
|
||||
case TEXTURE_CHANNEL_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
|
||||
code += "uniform float specular;\n";
|
||||
|
@ -731,6 +771,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
code += "\tUV /= vec2(h_frames, v_frames);\n";
|
||||
code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n";
|
||||
} break;
|
||||
case BILLBOARD_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
|
||||
if (flags[FLAG_FIXED_SIZE]) {
|
||||
|
@ -903,6 +945,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
case TEXTURE_CHANNEL_GRAYSCALE: {
|
||||
code += "\tvec4 roughness_texture_channel = vec4(0.333333,0.333333,0.333333,0.0);\n";
|
||||
} break;
|
||||
case TEXTURE_CHANNEL_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
|
||||
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
|
||||
|
@ -970,10 +1014,17 @@ void BaseMaterial3D::_update_shader() {
|
|||
code += "\tALBEDO *= 1.0 - ref_amount;\n";
|
||||
code += "\tALPHA = 1.0;\n";
|
||||
|
||||
} else if (transparency == TRANSPARENCY_ALPHA || transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) {
|
||||
} else if (transparency != TRANSPARENCY_DISABLED || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) {
|
||||
code += "\tALPHA = albedo.a * albedo_tex.a;\n";
|
||||
}
|
||||
if (transparency == TRANSPARENCY_ALPHA_HASH) {
|
||||
code += "\tALPHA_HASH_SCALE = alpha_hash_scale;\n";
|
||||
} else if (transparency == TRANSPARENCY_ALPHA_SCISSOR) {
|
||||
code += "\tif (albedo.a * albedo_tex.a < alpha_scissor_threshold) discard;\n";
|
||||
code += "\tALPHA_SCISSOR_THRESHOLD = alpha_scissor_threshold;\n";
|
||||
}
|
||||
if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF && (transparency == TRANSPARENCY_ALPHA_HASH || transparency == TRANSPARENCY_ALPHA_SCISSOR)) {
|
||||
code += "\tALPHA_ANTIALIASING_EDGE = alpha_antialiasing_edge;\n";
|
||||
code += "\tALPHA_TEXTURE_COORDINATE = UV * vec2(albedo_texture_size);\n";
|
||||
}
|
||||
|
||||
if (proximity_fade_enabled) {
|
||||
|
@ -1143,6 +1194,8 @@ void BaseMaterial3D::_update_shader() {
|
|||
case BLEND_MODE_MUL: {
|
||||
code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb*detail_tex.rgb,detail_tex.a);\n";
|
||||
} break;
|
||||
case BLEND_MODE_MAX:
|
||||
break; // Internal value, skip.
|
||||
}
|
||||
|
||||
code += "\tvec3 detail_norm = mix(NORMALMAP,detail_norm_tex.rgb,detail_tex.a);\n";
|
||||
|
@ -1424,6 +1477,20 @@ BaseMaterial3D::Transparency BaseMaterial3D::get_transparency() const {
|
|||
return transparency;
|
||||
}
|
||||
|
||||
void BaseMaterial3D::set_alpha_antialiasing(AlphaAntiAliasing p_alpha_aa) {
|
||||
if (alpha_antialiasing_mode == p_alpha_aa) {
|
||||
return;
|
||||
}
|
||||
|
||||
alpha_antialiasing_mode = p_alpha_aa;
|
||||
_queue_shader_change();
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
BaseMaterial3D::AlphaAntiAliasing BaseMaterial3D::get_alpha_antialiasing() const {
|
||||
return alpha_antialiasing_mode;
|
||||
}
|
||||
|
||||
void BaseMaterial3D::set_shading_mode(ShadingMode p_shading_mode) {
|
||||
if (shading_mode == p_shading_mode) {
|
||||
return;
|
||||
|
@ -1530,6 +1597,10 @@ void BaseMaterial3D::set_texture(TextureParam p_param, const Ref<Texture2D> &p_t
|
|||
textures[p_param] = p_texture;
|
||||
RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
|
||||
RS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid);
|
||||
if (p_texture.is_valid() && p_param == TEXTURE_ALBEDO) {
|
||||
RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo_texture_size,
|
||||
Vector2i(p_texture->get_width(), p_texture->get_height()));
|
||||
}
|
||||
_change_notify();
|
||||
_queue_shader_change();
|
||||
}
|
||||
|
@ -1605,10 +1676,34 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
|
|||
property.usage = 0;
|
||||
}
|
||||
|
||||
// you can only enable anti-aliasing (in mataerials) on alpha scissor and alpha hash
|
||||
const bool can_select_aa = (transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH);
|
||||
// alpha anti aliasiasing is only enabled when you can select aa
|
||||
const bool alpha_aa_enabled = (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) && can_select_aa;
|
||||
|
||||
// alpha scissor slider isn't needed when alpha antialiasing is enabled
|
||||
if (property.name == "alpha_scissor_threshold" && transparency != TRANSPARENCY_ALPHA_SCISSOR) {
|
||||
property.usage = 0;
|
||||
}
|
||||
|
||||
// alpha hash scale slider is only needed if transparency is alpha hash
|
||||
if (property.name == "alpha_hash_scale" && transparency != TRANSPARENCY_ALPHA_HASH) {
|
||||
property.usage = 0;
|
||||
}
|
||||
|
||||
if (property.name == "alpha_antialiasing_mode" && !can_select_aa) {
|
||||
property.usage = 0;
|
||||
}
|
||||
|
||||
// we cant choose an antialiasing mode if alpha isnt possible
|
||||
if (property.name == "alpha_antialiasing_edge" && !alpha_aa_enabled) {
|
||||
property.usage = 0;
|
||||
}
|
||||
|
||||
if (property.name == "blend_mode" && alpha_aa_enabled) {
|
||||
property.usage = 0;
|
||||
}
|
||||
|
||||
if ((property.name == "heightmap_min_layers" || property.name == "heightmap_max_layers") && !deep_parallax) {
|
||||
property.usage = 0;
|
||||
}
|
||||
|
@ -1845,6 +1940,24 @@ float BaseMaterial3D::get_alpha_scissor_threshold() const {
|
|||
return alpha_scissor_threshold;
|
||||
}
|
||||
|
||||
void BaseMaterial3D::set_alpha_hash_scale(float p_scale) {
|
||||
alpha_hash_scale = p_scale;
|
||||
RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_hash_scale, p_scale);
|
||||
}
|
||||
|
||||
float BaseMaterial3D::get_alpha_hash_scale() const {
|
||||
return alpha_hash_scale;
|
||||
}
|
||||
|
||||
void BaseMaterial3D::set_alpha_antialiasing_edge(float p_edge) {
|
||||
alpha_antialiasing_edge = p_edge;
|
||||
RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_antialiasing_edge, p_edge);
|
||||
}
|
||||
|
||||
float BaseMaterial3D::get_alpha_antialiasing_edge() const {
|
||||
return alpha_antialiasing_edge;
|
||||
}
|
||||
|
||||
void BaseMaterial3D::set_grow(float p_grow) {
|
||||
grow = p_grow;
|
||||
RS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow);
|
||||
|
@ -2033,6 +2146,12 @@ void BaseMaterial3D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_transparency", "transparency"), &BaseMaterial3D::set_transparency);
|
||||
ClassDB::bind_method(D_METHOD("get_transparency"), &BaseMaterial3D::get_transparency);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_alpha_antialiasing", "alpha_aa"), &BaseMaterial3D::set_alpha_antialiasing);
|
||||
ClassDB::bind_method(D_METHOD("get_alpha_antialiasing"), &BaseMaterial3D::get_alpha_antialiasing);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_alpha_antialiasing_edge", "edge"), &BaseMaterial3D::set_alpha_antialiasing_edge);
|
||||
ClassDB::bind_method(D_METHOD("get_alpha_antialiasing_edge"), &BaseMaterial3D::get_alpha_antialiasing_edge);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_shading_mode", "shading_mode"), &BaseMaterial3D::set_shading_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_shading_mode"), &BaseMaterial3D::get_shading_mode);
|
||||
|
||||
|
@ -2186,6 +2305,9 @@ void BaseMaterial3D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &BaseMaterial3D::set_alpha_scissor_threshold);
|
||||
ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &BaseMaterial3D::get_alpha_scissor_threshold);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_alpha_hash_scale", "threshold"), &BaseMaterial3D::set_alpha_hash_scale);
|
||||
ClassDB::bind_method(D_METHOD("get_alpha_hash_scale"), &BaseMaterial3D::get_alpha_hash_scale);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_grow_enabled", "enable"), &BaseMaterial3D::set_grow_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_grow_enabled"), &BaseMaterial3D::is_grow_enabled);
|
||||
|
||||
|
@ -2217,8 +2339,11 @@ void BaseMaterial3D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_distance_fade_min_distance"), &BaseMaterial3D::get_distance_fade_min_distance);
|
||||
|
||||
ADD_GROUP("Transparency", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,AlphaScissor,DepthPrePass"), "set_transparency", "get_transparency");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth PrePass"), "set_transparency", "get_transparency");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never"), "set_depth_draw_mode", "get_depth_draw_mode");
|
||||
|
@ -2414,6 +2539,7 @@ void BaseMaterial3D::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(TRANSPARENCY_DISABLED);
|
||||
BIND_ENUM_CONSTANT(TRANSPARENCY_ALPHA);
|
||||
BIND_ENUM_CONSTANT(TRANSPARENCY_ALPHA_SCISSOR);
|
||||
BIND_ENUM_CONSTANT(TRANSPARENCY_ALPHA_HASH);
|
||||
BIND_ENUM_CONSTANT(TRANSPARENCY_ALPHA_DEPTH_PRE_PASS);
|
||||
BIND_ENUM_CONSTANT(TRANSPARENCY_MAX);
|
||||
|
||||
|
@ -2441,6 +2567,10 @@ void BaseMaterial3D::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(BLEND_MODE_SUB);
|
||||
BIND_ENUM_CONSTANT(BLEND_MODE_MUL);
|
||||
|
||||
BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_OFF);
|
||||
BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
|
||||
BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
|
||||
|
||||
BIND_ENUM_CONSTANT(DEPTH_DRAW_OPAQUE_ONLY);
|
||||
BIND_ENUM_CONSTANT(DEPTH_DRAW_ALWAYS);
|
||||
BIND_ENUM_CONSTANT(DEPTH_DRAW_DISABLED);
|
||||
|
@ -2506,7 +2636,6 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
|
|||
element(this) {
|
||||
orm = p_orm;
|
||||
// Initialize to the same values as the shader
|
||||
transparency = TRANSPARENCY_DISABLED;
|
||||
shading_mode = SHADING_MODE_PER_PIXEL;
|
||||
set_albedo(Color(1.0, 1.0, 1.0, 1.0));
|
||||
set_specular(0.5);
|
||||
|
@ -2539,9 +2668,14 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
|
|||
set_particles_anim_h_frames(1);
|
||||
set_particles_anim_v_frames(1);
|
||||
set_particles_anim_loop(false);
|
||||
set_alpha_scissor_threshold(0.98);
|
||||
emission_op = EMISSION_OP_ADD;
|
||||
|
||||
set_transparency(TRANSPARENCY_DISABLED);
|
||||
set_alpha_antialiasing(ALPHA_ANTIALIASING_OFF);
|
||||
set_alpha_scissor_threshold(0.05);
|
||||
set_alpha_hash_scale(1.0);
|
||||
set_alpha_antialiasing_edge(0.3);
|
||||
|
||||
proximity_fade_enabled = false;
|
||||
distance_fade = DISTANCE_FADE_DISABLED;
|
||||
set_proximity_fade_distance(1);
|
||||
|
@ -2582,10 +2716,8 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
|
|||
features[i] = false;
|
||||
}
|
||||
|
||||
current_key.key0 = 0;
|
||||
current_key.key1 = 0;
|
||||
current_key.invalid_key = 1;
|
||||
texture_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS;
|
||||
|
||||
_queue_shader_change();
|
||||
}
|
||||
|
||||
|
@ -2633,6 +2765,12 @@ bool StandardMaterial3D::_set(const StringName &p_name, const Variant &p_value)
|
|||
set_transparency(TRANSPARENCY_ALPHA_SCISSOR);
|
||||
}
|
||||
return true;
|
||||
} else if (p_name == "params_use_alpha_hash") {
|
||||
bool use_hash = p_value;
|
||||
if (use_hash) {
|
||||
set_transparency(TRANSPARENCY_ALPHA_HASH);
|
||||
}
|
||||
return true;
|
||||
} else if (p_name == "params_depth_draw_mode") {
|
||||
int mode = p_value;
|
||||
if (mode == 3) {
|
||||
|
@ -2667,6 +2805,8 @@ bool StandardMaterial3D::_set(const StringName &p_name, const Variant &p_value)
|
|||
{ "params_grow", "grow" },
|
||||
{ "params_grow_amount", "grow_amount" },
|
||||
{ "params_alpha_scissor_threshold", "alpha_scissor_threshold" },
|
||||
{ "params_alpha_hash_scale", "alpha_hash_scale" },
|
||||
{ "params_alpha_antialiasing_edge", "alpha_antialiasing_edge" },
|
||||
|
||||
{ "depth_scale", "heightmap_scale" },
|
||||
{ "depth_deep_parallax", "heightmap_deep_parallax" },
|
||||
|
|
|
@ -145,17 +145,26 @@ public:
|
|||
|
||||
enum DetailUV {
|
||||
DETAIL_UV_1,
|
||||
DETAIL_UV_2
|
||||
DETAIL_UV_2,
|
||||
DETAIL_UV_MAX
|
||||
};
|
||||
|
||||
enum Transparency {
|
||||
TRANSPARENCY_DISABLED,
|
||||
TRANSPARENCY_ALPHA,
|
||||
TRANSPARENCY_ALPHA_SCISSOR,
|
||||
TRANSPARENCY_ALPHA_HASH,
|
||||
TRANSPARENCY_ALPHA_DEPTH_PRE_PASS,
|
||||
TRANSPARENCY_MAX,
|
||||
};
|
||||
|
||||
enum AlphaAntiAliasing {
|
||||
ALPHA_ANTIALIASING_OFF,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE,
|
||||
ALPHA_ANTIALIASING_MAX
|
||||
};
|
||||
|
||||
enum ShadingMode {
|
||||
SHADING_MODE_UNSHADED,
|
||||
SHADING_MODE_PER_PIXEL,
|
||||
|
@ -184,18 +193,21 @@ public:
|
|||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_MAX
|
||||
};
|
||||
|
||||
enum DepthDrawMode {
|
||||
DEPTH_DRAW_OPAQUE_ONLY,
|
||||
DEPTH_DRAW_ALWAYS,
|
||||
DEPTH_DRAW_DISABLED,
|
||||
DEPTH_DRAW_MAX
|
||||
};
|
||||
|
||||
enum CullMode {
|
||||
CULL_BACK,
|
||||
CULL_FRONT,
|
||||
CULL_DISABLED
|
||||
CULL_DISABLED,
|
||||
CULL_MAX
|
||||
};
|
||||
|
||||
enum Flags {
|
||||
|
@ -227,6 +239,7 @@ public:
|
|||
DIFFUSE_LAMBERT_WRAP,
|
||||
DIFFUSE_OREN_NAYAR,
|
||||
DIFFUSE_TOON,
|
||||
DIFFUSE_MAX
|
||||
};
|
||||
|
||||
enum SpecularMode {
|
||||
|
@ -235,6 +248,7 @@ public:
|
|||
SPECULAR_PHONG,
|
||||
SPECULAR_TOON,
|
||||
SPECULAR_DISABLED,
|
||||
SPECULAR_MAX
|
||||
};
|
||||
|
||||
enum BillboardMode {
|
||||
|
@ -242,6 +256,7 @@ public:
|
|||
BILLBOARD_ENABLED,
|
||||
BILLBOARD_FIXED_Y,
|
||||
BILLBOARD_PARTICLES,
|
||||
BILLBOARD_MAX
|
||||
};
|
||||
|
||||
enum TextureChannel {
|
||||
|
@ -249,12 +264,14 @@ public:
|
|||
TEXTURE_CHANNEL_GREEN,
|
||||
TEXTURE_CHANNEL_BLUE,
|
||||
TEXTURE_CHANNEL_ALPHA,
|
||||
TEXTURE_CHANNEL_GRAYSCALE
|
||||
TEXTURE_CHANNEL_GRAYSCALE,
|
||||
TEXTURE_CHANNEL_MAX
|
||||
};
|
||||
|
||||
enum EmissionOperator {
|
||||
EMISSION_OP_ADD,
|
||||
EMISSION_OP_MULTIPLY
|
||||
EMISSION_OP_MULTIPLY,
|
||||
EMISSION_OP_MAX
|
||||
};
|
||||
|
||||
enum DistanceFadeMode {
|
||||
|
@ -262,43 +279,47 @@ public:
|
|||
DISTANCE_FADE_PIXEL_ALPHA,
|
||||
DISTANCE_FADE_PIXEL_DITHER,
|
||||
DISTANCE_FADE_OBJECT_DITHER,
|
||||
DISTANCE_FADE_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
union MaterialKey {
|
||||
struct {
|
||||
uint64_t feature_mask : FEATURE_MAX;
|
||||
uint64_t detail_uv : 1;
|
||||
uint64_t blend_mode : 2;
|
||||
uint64_t depth_draw_mode : 2;
|
||||
uint64_t cull_mode : 2;
|
||||
uint64_t flags : FLAG_MAX;
|
||||
uint64_t detail_blend_mode : 2;
|
||||
uint64_t diffuse_mode : 3;
|
||||
uint64_t specular_mode : 3;
|
||||
uint64_t invalid_key : 1;
|
||||
uint64_t deep_parallax : 1;
|
||||
uint64_t billboard_mode : 2;
|
||||
uint64_t grow : 1;
|
||||
uint64_t proximity_fade : 1;
|
||||
uint64_t distance_fade : 2;
|
||||
uint64_t emission_op : 1;
|
||||
uint64_t texture_filter : 3;
|
||||
uint64_t transparency : 2;
|
||||
uint64_t shading_mode : 2;
|
||||
uint64_t roughness_channel : 3;
|
||||
};
|
||||
struct MaterialKey {
|
||||
// enum values
|
||||
uint64_t texture_filter : get_num_bits(TEXTURE_FILTER_MAX - 1);
|
||||
uint64_t detail_uv : get_num_bits(DETAIL_UV_MAX - 1);
|
||||
uint64_t transparency : get_num_bits(TRANSPARENCY_MAX - 1);
|
||||
uint64_t alpha_antialiasing_mode : get_num_bits(ALPHA_ANTIALIASING_MAX - 1);
|
||||
uint64_t shading_mode : get_num_bits(SHADING_MODE_MAX - 1);
|
||||
uint64_t blend_mode : get_num_bits(BLEND_MODE_MAX - 1);
|
||||
uint64_t depth_draw_mode : get_num_bits(DEPTH_DRAW_MAX - 1);
|
||||
uint64_t cull_mode : get_num_bits(CULL_MAX - 1);
|
||||
uint64_t diffuse_mode : get_num_bits(DIFFUSE_MAX - 1);
|
||||
uint64_t specular_mode : get_num_bits(SPECULAR_MAX - 1);
|
||||
uint64_t billboard_mode : get_num_bits(BILLBOARD_MAX - 1);
|
||||
uint64_t detail_blend_mode : get_num_bits(BLEND_MODE_MAX - 1);
|
||||
uint64_t roughness_channel : get_num_bits(TEXTURE_CHANNEL_MAX - 1);
|
||||
uint64_t emission_op : get_num_bits(EMISSION_OP_MAX - 1);
|
||||
uint64_t distance_fade : get_num_bits(DISTANCE_FADE_MAX - 1);
|
||||
|
||||
struct {
|
||||
uint64_t key0;
|
||||
uint64_t key1;
|
||||
};
|
||||
// flag bitfield
|
||||
uint64_t feature_mask : FEATURE_MAX - 1;
|
||||
uint64_t flags : FLAG_MAX - 1;
|
||||
|
||||
// booleans
|
||||
uint64_t deep_parallax : 1;
|
||||
uint64_t grow : 1;
|
||||
uint64_t proximity_fade : 1;
|
||||
|
||||
MaterialKey() {
|
||||
memset(this, 0, sizeof(MaterialKey));
|
||||
}
|
||||
|
||||
bool operator==(const MaterialKey &p_key) const {
|
||||
return (key0 == p_key.key0) && (key1 == p_key.key1);
|
||||
return memcmp(this, &p_key, sizeof(MaterialKey)) == 0;
|
||||
}
|
||||
|
||||
bool operator<(const MaterialKey &p_key) const {
|
||||
return (key0 == p_key.key0) ? (key1 < p_key.key1) : (key0 < p_key.key0);
|
||||
return memcmp(this, &p_key, sizeof(MaterialKey)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -313,13 +334,7 @@ private:
|
|||
|
||||
_FORCE_INLINE_ MaterialKey _compute_key() const {
|
||||
MaterialKey mk;
|
||||
mk.key0 = 0;
|
||||
mk.key1 = 0;
|
||||
for (int i = 0; i < FEATURE_MAX; i++) {
|
||||
if (features[i]) {
|
||||
mk.feature_mask |= ((uint64_t)1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
mk.detail_uv = detail_uv;
|
||||
mk.blend_mode = blend_mode;
|
||||
mk.depth_draw_mode = depth_draw_mode;
|
||||
|
@ -328,20 +343,28 @@ private:
|
|||
mk.transparency = transparency;
|
||||
mk.shading_mode = shading_mode;
|
||||
mk.roughness_channel = roughness_texture_channel;
|
||||
mk.detail_blend_mode = detail_blend_mode;
|
||||
mk.diffuse_mode = diffuse_mode;
|
||||
mk.specular_mode = specular_mode;
|
||||
mk.billboard_mode = billboard_mode;
|
||||
mk.deep_parallax = deep_parallax;
|
||||
mk.grow = grow_enabled;
|
||||
mk.proximity_fade = proximity_fade_enabled;
|
||||
mk.distance_fade = distance_fade;
|
||||
mk.emission_op = emission_op;
|
||||
mk.alpha_antialiasing_mode = alpha_antialiasing_mode;
|
||||
|
||||
for (int i = 0; i < FEATURE_MAX; i++) {
|
||||
if (features[i]) {
|
||||
mk.feature_mask |= ((uint64_t)1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < FLAG_MAX; i++) {
|
||||
if (flags[i]) {
|
||||
mk.flags |= ((uint64_t)1 << i);
|
||||
}
|
||||
}
|
||||
mk.detail_blend_mode = detail_blend_mode;
|
||||
mk.diffuse_mode = diffuse_mode;
|
||||
mk.specular_mode = specular_mode;
|
||||
mk.billboard_mode = billboard_mode;
|
||||
mk.deep_parallax = deep_parallax ? 1 : 0;
|
||||
mk.grow = grow_enabled;
|
||||
mk.proximity_fade = proximity_fade_enabled;
|
||||
mk.distance_fade = distance_fade;
|
||||
mk.emission_op = emission_op;
|
||||
|
||||
return mk;
|
||||
}
|
||||
|
@ -392,9 +415,14 @@ private:
|
|||
StringName rim_texture_channel;
|
||||
StringName heightmap_texture_channel;
|
||||
StringName refraction_texture_channel;
|
||||
StringName alpha_scissor_threshold;
|
||||
|
||||
StringName texture_names[TEXTURE_MAX];
|
||||
|
||||
StringName alpha_scissor_threshold;
|
||||
StringName alpha_hash_scale;
|
||||
|
||||
StringName alpha_antialiasing_edge;
|
||||
StringName albedo_texture_size;
|
||||
};
|
||||
|
||||
static Mutex material_mutex;
|
||||
|
@ -433,6 +461,8 @@ private:
|
|||
float refraction;
|
||||
float point_size;
|
||||
float alpha_scissor_threshold;
|
||||
float alpha_hash_scale;
|
||||
float alpha_antialiasing_edge;
|
||||
bool grow_enabled;
|
||||
float ao_light_affect;
|
||||
float grow;
|
||||
|
@ -482,6 +512,8 @@ private:
|
|||
TextureChannel ao_texture_channel;
|
||||
TextureChannel refraction_texture_channel;
|
||||
|
||||
AlphaAntiAliasing alpha_antialiasing_mode;
|
||||
|
||||
bool features[FEATURE_MAX];
|
||||
|
||||
Ref<Texture2D> textures[TEXTURE_MAX];
|
||||
|
@ -584,6 +616,12 @@ public:
|
|||
void set_transparency(Transparency p_transparency);
|
||||
Transparency get_transparency() const;
|
||||
|
||||
void set_alpha_antialiasing(AlphaAntiAliasing p_alpha_aa);
|
||||
AlphaAntiAliasing get_alpha_antialiasing() const;
|
||||
|
||||
void set_alpha_antialiasing_edge(float p_edge);
|
||||
float get_alpha_antialiasing_edge() const;
|
||||
|
||||
void set_shading_mode(ShadingMode p_shading_mode);
|
||||
ShadingMode get_shading_mode() const;
|
||||
|
||||
|
@ -660,6 +698,9 @@ public:
|
|||
void set_alpha_scissor_threshold(float p_threshold);
|
||||
float get_alpha_scissor_threshold() const;
|
||||
|
||||
void set_alpha_hash_scale(float p_scale);
|
||||
float get_alpha_hash_scale() const;
|
||||
|
||||
void set_on_top_of_alpha();
|
||||
|
||||
void set_proximity_fade(bool p_enable);
|
||||
|
@ -707,6 +748,7 @@ VARIANT_ENUM_CAST(BaseMaterial3D::TextureParam)
|
|||
VARIANT_ENUM_CAST(BaseMaterial3D::TextureFilter)
|
||||
VARIANT_ENUM_CAST(BaseMaterial3D::ShadingMode)
|
||||
VARIANT_ENUM_CAST(BaseMaterial3D::Transparency)
|
||||
VARIANT_ENUM_CAST(BaseMaterial3D::AlphaAntiAliasing)
|
||||
VARIANT_ENUM_CAST(BaseMaterial3D::DetailUV)
|
||||
VARIANT_ENUM_CAST(BaseMaterial3D::Feature)
|
||||
VARIANT_ENUM_CAST(BaseMaterial3D::BlendMode)
|
||||
|
|
|
@ -51,6 +51,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
int blend_mode = BLEND_MODE_MIX;
|
||||
int depth_testi = DEPTH_TEST_ENABLED;
|
||||
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
int cull = CULL_BACK;
|
||||
|
||||
uses_point_size = false;
|
||||
|
@ -82,6 +83,9 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
|
|||
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["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
|
||||
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
|
||||
|
||||
actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED);
|
||||
actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
|
||||
actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
|
||||
|
@ -154,6 +158,11 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
//blend modes
|
||||
|
||||
// if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage
|
||||
if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) {
|
||||
blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE;
|
||||
}
|
||||
|
||||
RD::PipelineColorBlendState::Attachment blend_attachment;
|
||||
|
||||
switch (blend_mode) {
|
||||
|
@ -199,6 +208,15 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
|
|||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
uses_blend_alpha = true; //force alpha used because of blend
|
||||
} break;
|
||||
case BLEND_MODE_ALPHA_TO_COVERAGE: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
RD::PipelineColorBlendState blend_state_blend;
|
||||
|
@ -245,8 +263,17 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
|
||||
if (uses_alpha || uses_blend_alpha) {
|
||||
// only allow these flags to go through if we have some form of msaa
|
||||
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
multisample_state.enable_alpha_to_one = true;
|
||||
}
|
||||
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
|
||||
blend_state = blend_state_blend;
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE) {
|
||||
|
@ -286,7 +313,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
|
|||
}
|
||||
|
||||
RID shader_variant = scene_singleton->shader.scene_shader.version_get_shader(version, k);
|
||||
pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, RD::PipelineMultisampleState(), depth_stencil, blend_state, 0);
|
||||
pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2725,6 +2752,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
|
|||
actions.renames["POINT_SIZE"] = "gl_PointSize";
|
||||
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
|
||||
|
||||
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
|
||||
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
|
||||
actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge";
|
||||
actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate";
|
||||
|
||||
//builtins
|
||||
|
||||
actions.renames["TIME"] = "scene_data.time";
|
||||
|
@ -2793,6 +2825,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
|
|||
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
|
||||
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
|
||||
|
||||
actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n";
|
||||
actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
|
||||
actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n";
|
||||
actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE";
|
||||
|
||||
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
|
||||
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
|
||||
actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n";
|
||||
|
|
|
@ -83,6 +83,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_ALPHA_TO_COVERAGE
|
||||
};
|
||||
|
||||
enum DepthDraw {
|
||||
|
@ -110,6 +111,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
|
||||
};
|
||||
|
||||
enum AlphaAntiAliasing {
|
||||
ALPHA_ANTIALIASING_OFF,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
||||
};
|
||||
|
||||
bool valid;
|
||||
RID version;
|
||||
uint32_t vertex_input_mask;
|
||||
|
@ -132,6 +139,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
|||
bool uses_point_size;
|
||||
bool uses_alpha;
|
||||
bool uses_blend_alpha;
|
||||
bool uses_alpha_clip;
|
||||
bool uses_depth_pre_pass;
|
||||
bool uses_discard;
|
||||
bool uses_roughness;
|
||||
|
|
|
@ -361,6 +361,65 @@ layout(location = 0) out vec4 frag_color;
|
|||
|
||||
#endif // RENDER DEPTH
|
||||
|
||||
#ifdef ALPHA_HASH_USED
|
||||
|
||||
float hash_2d(vec2 p) {
|
||||
return fract(1.0e4 * sin(17.0 * p.x + 0.1 * p.y) *
|
||||
(0.1 + abs(sin(13.0 * p.y + p.x))));
|
||||
}
|
||||
|
||||
float hash_3d(vec3 p) {
|
||||
return hash_2d(vec2(hash_2d(p.xy), p.z));
|
||||
}
|
||||
|
||||
float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
|
||||
vec3 dx = dFdx(pos);
|
||||
vec3 dy = dFdx(pos);
|
||||
float delta_max_sqr = max(length(dx), length(dy));
|
||||
float pix_scale = 1.0 / (hash_scale * delta_max_sqr);
|
||||
|
||||
vec2 pix_scales =
|
||||
vec2(exp2(floor(log2(pix_scale))), exp2(ceil(log2(pix_scale))));
|
||||
|
||||
vec2 a_thresh = vec2(hash_3d(floor(pix_scales.x * pos.xyz)),
|
||||
hash_3d(floor(pix_scales.y * pos.xyz)));
|
||||
|
||||
float lerp_factor = fract(log2(pix_scale));
|
||||
|
||||
float a_interp = (1.0 - lerp_factor) * a_thresh.x + lerp_factor * a_thresh.y;
|
||||
|
||||
float min_lerp = min(lerp_factor, 1.0 - lerp_factor);
|
||||
|
||||
vec3 cases = vec3(a_interp * a_interp / (2.0 * min_lerp * (1.0 - min_lerp)),
|
||||
(a_interp - 0.5 * min_lerp) / (1.0 - min_lerp),
|
||||
1.0 - ((1.0 - a_interp) * (1.0 - a_interp) /
|
||||
(2.0 * min_lerp * (1.0 - min_lerp))));
|
||||
|
||||
float alpha_hash_threshold =
|
||||
(lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z;
|
||||
|
||||
return clamp(alpha_hash_threshold, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif // ALPHA_HASH_USED
|
||||
|
||||
#ifdef ALPHA_ANTIALIASING_EDGE_USED
|
||||
|
||||
float calc_mip_level(vec2 texture_coord) {
|
||||
vec2 dx = dFdx(texture_coord);
|
||||
vec2 dy = dFdy(texture_coord);
|
||||
float delta_max_sqr = max(dot(dx, dx), dot(dy, dy));
|
||||
return max(0.0, 0.5 * log2(delta_max_sqr));
|
||||
}
|
||||
|
||||
float compute_alpha_antialiasing_edge(float input_alpha, vec2 texture_coord, float alpha_edge) {
|
||||
input_alpha *= 1.0 + max(0, calc_mip_level(texture_coord)) * 0.25; // 0.25 mip scale, magic number
|
||||
input_alpha = (input_alpha - alpha_edge) / max(fwidth(input_alpha), 0.0001) + 0.5;
|
||||
return clamp(input_alpha, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif // ALPHA_ANTIALIASING_USED
|
||||
|
||||
// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
|
||||
// We're dividing this factor off because the overall term we'll end up looks like
|
||||
// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
|
||||
|
@ -1709,10 +1768,6 @@ void main() {
|
|||
|
||||
float alpha = 1.0;
|
||||
|
||||
#if defined(ALPHA_SCISSOR_USED)
|
||||
float alpha_scissor = 0.5;
|
||||
#endif
|
||||
|
||||
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
|
||||
vec3 binormal = normalize(binormal_interp);
|
||||
vec3 tangent = normalize(tangent_interp);
|
||||
|
@ -1749,6 +1804,19 @@ void main() {
|
|||
|
||||
float sss_strength = 0.0;
|
||||
|
||||
#ifdef ALPHA_SCISSOR_USED
|
||||
float alpha_scissor_threshold = 1.0;
|
||||
#endif // ALPHA_SCISSOR_USED
|
||||
|
||||
#ifdef ALPHA_HASH_USED
|
||||
float alpha_hash_scale = 1.0;
|
||||
#endif // ALPHA_HASH_USED
|
||||
|
||||
#ifdef ALPHA_ANTIALIASING_EDGE_USED
|
||||
float alpha_antialiasing_edge = 0.0;
|
||||
vec2 alpha_texture_coordinate = vec2(0.0, 0.0);
|
||||
#endif // ALPHA_ANTIALIASING_EDGE_USED
|
||||
|
||||
{
|
||||
/* clang-format off */
|
||||
|
||||
|
@ -1757,7 +1825,7 @@ FRAGMENT_SHADER_CODE
|
|||
/* clang-format on */
|
||||
}
|
||||
|
||||
#if defined(LIGHT_TRANSMITTANCE_USED)
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
#ifdef SSS_MODE_SKIN
|
||||
transmittance_color.a = sss_strength;
|
||||
#else
|
||||
|
@ -1765,25 +1833,43 @@ FRAGMENT_SHADER_CODE
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(USE_SHADOW_TO_OPACITY)
|
||||
#ifndef USE_SHADOW_TO_OPACITY
|
||||
|
||||
#if defined(ALPHA_SCISSOR_USED)
|
||||
if (alpha < alpha_scissor) {
|
||||
#ifdef ALPHA_SCISSOR_USED
|
||||
if (alpha < alpha_scissor_threshold) {
|
||||
discard;
|
||||
}
|
||||
#endif // ALPHA_SCISSOR_USED
|
||||
|
||||
#ifdef USE_OPAQUE_PREPASS
|
||||
// alpha hash can be used in unison with alpha antialiasing
|
||||
#ifdef ALPHA_HASH_USED
|
||||
if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) {
|
||||
discard;
|
||||
}
|
||||
#endif // ALPHA_HASH_USED
|
||||
|
||||
// If we are not edge antialiasing, we need to remove the output alpha channel from scissor and hash
|
||||
#if (defined(ALPHA_SCISSOR_USED) || defined(ALPHA_HASH_USED)) && !defined(ALPHA_ANTIALIASING_EDGE_USED)
|
||||
alpha = 1.0;
|
||||
#endif
|
||||
|
||||
#ifdef ALPHA_ANTIALIASING_EDGE_USED
|
||||
// If alpha scissor is used, we must further the edge threshold, otherwise we wont get any edge feather
|
||||
#ifdef ALPHA_SCISSOR_USED
|
||||
alpha_antialiasing_edge = clamp(alpha_scissor_threshold + alpha_antialiasing_edge, 0.0, 1.0);
|
||||
#endif
|
||||
alpha = compute_alpha_antialiasing_edge(alpha, alpha_texture_coordinate, alpha_antialiasing_edge);
|
||||
#endif // ALPHA_ANTIALIASING_EDGE_USED
|
||||
|
||||
#ifdef USE_OPAQUE_PREPASS
|
||||
if (alpha < opaque_prepass_threshold) {
|
||||
discard;
|
||||
}
|
||||
|
||||
#endif // USE_OPAQUE_PREPASS
|
||||
|
||||
#endif // !USE_SHADOW_TO_OPACITY
|
||||
|
||||
#if defined(NORMALMAP_USED)
|
||||
#ifdef NORMALMAP_USED
|
||||
|
||||
normalmap.xy = normalmap.xy * 2.0 - 1.0;
|
||||
normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
|
||||
|
@ -1792,7 +1878,7 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#endif
|
||||
|
||||
#if defined(LIGHT_ANISOTROPY_USED)
|
||||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
|
||||
if (anisotropy > 0.01) {
|
||||
//rotation matrix
|
||||
|
|
|
@ -134,6 +134,11 @@ ShaderTypes::ShaderTypes() {
|
|||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["IRRADIANCE"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].can_discard = true;
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR_THRESHOLD"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_HASH_SCALE"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_ANTIALIASING_EDGE"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_TEXTURE_COORDINATE"] = ShaderLanguage::TYPE_VEC2;
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
|
@ -206,6 +211,9 @@ ShaderTypes::ShaderTypes() {
|
|||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("vertex_lighting");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage_and_one");
|
||||
|
||||
/************ CANVAS ITEM **************************/
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
|
|
Loading…
Reference in a new issue