mirror of
https://github.com/godotengine/godot.git
synced 2025-12-08 06:09:55 +00:00
Merge pull request #80710 from apples/7174-apples-stencil
Add stencil support to spatial materials
This commit is contained in:
commit
0497ae9947
29 changed files with 1531 additions and 174 deletions
|
|
@ -159,6 +159,10 @@
|
||||||
<member name="depth_draw_mode" type="int" setter="set_depth_draw_mode" getter="get_depth_draw_mode" enum="BaseMaterial3D.DepthDrawMode" default="0">
|
<member name="depth_draw_mode" type="int" setter="set_depth_draw_mode" getter="get_depth_draw_mode" enum="BaseMaterial3D.DepthDrawMode" default="0">
|
||||||
Determines when depth rendering takes place. See also [member transparency].
|
Determines when depth rendering takes place. See also [member transparency].
|
||||||
</member>
|
</member>
|
||||||
|
<member name="depth_test" type="int" setter="set_depth_test" getter="get_depth_test" enum="BaseMaterial3D.DepthTest" default="0" experimental="May be affected by future rendering pipeline changes.">
|
||||||
|
Determines which comparison operator is used when testing depth. See [enum DepthTest].
|
||||||
|
[b]Note:[/b] Changing [member depth_test] to a non-default value only has a visible effect when used on a transparent material, or a material that has [member depth_draw_mode] set to [constant DEPTH_DRAW_DISABLED].
|
||||||
|
</member>
|
||||||
<member name="detail_albedo" type="Texture2D" setter="set_texture" getter="get_texture">
|
<member name="detail_albedo" type="Texture2D" setter="set_texture" getter="get_texture">
|
||||||
Texture that specifies the color of the detail overlay. [member detail_albedo]'s alpha channel is used as a mask, even when the material is opaque. To use a dedicated texture as a mask, see [member detail_mask].
|
Texture that specifies the color of the detail overlay. [member detail_albedo]'s alpha channel is used as a mask, even when the material is opaque. To use a dedicated texture as a mask, see [member detail_mask].
|
||||||
[b]Note:[/b] [member detail_albedo] is [i]not[/i] modulated by [member albedo_color].
|
[b]Note:[/b] [member detail_albedo] is [i]not[/i] modulated by [member albedo_color].
|
||||||
|
|
@ -374,6 +378,24 @@
|
||||||
The method for rendering the specular blob.
|
The method for rendering the specular blob.
|
||||||
[b]Note:[/b] [member specular_mode] only applies to the specular blob. It does not affect specular reflections from the sky, screen-space reflections, [VoxelGI], SDFGI or [ReflectionProbe]s. To disable reflections from these sources as well, set [member metallic_specular] to [code]0.0[/code] instead.
|
[b]Note:[/b] [member specular_mode] only applies to the specular blob. It does not affect specular reflections from the sky, screen-space reflections, [VoxelGI], SDFGI or [ReflectionProbe]s. To disable reflections from these sources as well, set [member metallic_specular] to [code]0.0[/code] instead.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="stencil_color" type="Color" setter="set_stencil_effect_color" getter="get_stencil_effect_color" default="Color(0, 0, 0, 1)" experimental="May be affected by future rendering pipeline changes.">
|
||||||
|
The primary color of the stencil effect.
|
||||||
|
</member>
|
||||||
|
<member name="stencil_compare" type="int" setter="set_stencil_compare" getter="get_stencil_compare" enum="BaseMaterial3D.StencilCompare" default="0" experimental="May be affected by future rendering pipeline changes.">
|
||||||
|
The comparison operator to use for stencil masking operations. See [enum StencilCompare].
|
||||||
|
</member>
|
||||||
|
<member name="stencil_flags" type="int" setter="set_stencil_flags" getter="get_stencil_flags" default="0" experimental="May be affected by future rendering pipeline changes.">
|
||||||
|
The flags dictating how the stencil operation behaves. See [enum StencilFlags].
|
||||||
|
</member>
|
||||||
|
<member name="stencil_mode" type="int" setter="set_stencil_mode" getter="get_stencil_mode" enum="BaseMaterial3D.StencilMode" default="0" experimental="May be affected by future rendering pipeline changes.">
|
||||||
|
The stencil effect mode. See [enum StencilMode].
|
||||||
|
</member>
|
||||||
|
<member name="stencil_outline_thickness" type="float" setter="set_stencil_effect_outline_thickness" getter="get_stencil_effect_outline_thickness" default="0.01" experimental="May be affected by future rendering pipeline changes.">
|
||||||
|
The outline thickness for [constant STENCIL_MODE_OUTLINE].
|
||||||
|
</member>
|
||||||
|
<member name="stencil_reference" type="int" setter="set_stencil_reference" getter="get_stencil_reference" default="1" experimental="May be affected by future rendering pipeline changes.">
|
||||||
|
The stencil reference value (0-255). Typically a power of 2.
|
||||||
|
</member>
|
||||||
<member name="subsurf_scatter_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
|
<member name="subsurf_scatter_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
|
||||||
If [code]true[/code], subsurface scattering is enabled. Emulates light that penetrates an object's surface, is scattered, and then emerges. Subsurface scattering quality is controlled by [member ProjectSettings.rendering/environment/subsurface_scattering/subsurface_scattering_quality].
|
If [code]true[/code], subsurface scattering is enabled. Emulates light that penetrates an object's surface, is scattered, and then emerges. Subsurface scattering quality is controlled by [member ProjectSettings.rendering/environment/subsurface_scattering/subsurface_scattering_quality].
|
||||||
</member>
|
</member>
|
||||||
|
|
@ -661,6 +683,12 @@
|
||||||
<constant name="DEPTH_DRAW_DISABLED" value="2" enum="DepthDrawMode">
|
<constant name="DEPTH_DRAW_DISABLED" value="2" enum="DepthDrawMode">
|
||||||
Objects will not write their depth to the depth buffer, even during the depth prepass (if enabled).
|
Objects will not write their depth to the depth buffer, even during the depth prepass (if enabled).
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="DEPTH_TEST_DEFAULT" value="0" enum="DepthTest">
|
||||||
|
Depth test will discard the pixel if it is behind other pixels.
|
||||||
|
</constant>
|
||||||
|
<constant name="DEPTH_TEST_INVERTED" value="1" enum="DepthTest">
|
||||||
|
Depth test will discard the pixel if it is in front of other pixels. Useful for stencil effects.
|
||||||
|
</constant>
|
||||||
<constant name="CULL_BACK" value="0" enum="CullMode">
|
<constant name="CULL_BACK" value="0" enum="CullMode">
|
||||||
Default cull mode. The back of the object is culled when not visible. Back face triangles will be culled when facing the camera. This results in only the front side of triangles being drawn. For closed-surface meshes, this means that only the exterior of the mesh will be visible.
|
Default cull mode. The back of the object is culled when not visible. Back face triangles will be culled when facing the camera. This results in only the front side of triangles being drawn. For closed-surface meshes, this means that only the exterior of the mesh will be visible.
|
||||||
</constant>
|
</constant>
|
||||||
|
|
@ -818,5 +846,49 @@
|
||||||
<constant name="DISTANCE_FADE_OBJECT_DITHER" value="3" enum="DistanceFadeMode">
|
<constant name="DISTANCE_FADE_OBJECT_DITHER" value="3" enum="DistanceFadeMode">
|
||||||
Smoothly fades the object out based on the object's distance from the camera using a dithering approach. Dithering discards pixels based on a set pattern to smoothly fade without enabling transparency. On certain hardware, this can be faster than [constant DISTANCE_FADE_PIXEL_ALPHA] and [constant DISTANCE_FADE_PIXEL_DITHER].
|
Smoothly fades the object out based on the object's distance from the camera using a dithering approach. Dithering discards pixels based on a set pattern to smoothly fade without enabling transparency. On certain hardware, this can be faster than [constant DISTANCE_FADE_PIXEL_ALPHA] and [constant DISTANCE_FADE_PIXEL_DITHER].
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="STENCIL_MODE_DISABLED" value="0" enum="StencilMode">
|
||||||
|
Disables stencil operations.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_MODE_OUTLINE" value="1" enum="StencilMode">
|
||||||
|
Stencil preset which applies an outline to the object.
|
||||||
|
[b]Note:[/b] Requires a [member Material.next_pass] material which will be automatically applied. Any manual changes made to [member Material.next_pass] will be lost when the stencil properties are modified or the scene is reloaded. To safely apply a [member Material.next_pass] material on a material that uses stencil presets, use [member GeometryInstance3D.material_overlay] instead.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_MODE_XRAY" value="2" enum="StencilMode">
|
||||||
|
Stencil preset which shows a silhouette of the object behind walls.
|
||||||
|
[b]Note:[/b] Requires a [member Material.next_pass] material which will be automatically applied. Any manual changes made to [member Material.next_pass] will be lost when the stencil properties are modified or the scene is reloaded. To safely apply a [member Material.next_pass] material on a material that uses stencil presets, use [member GeometryInstance3D.material_overlay] instead.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_MODE_CUSTOM" value="3" enum="StencilMode">
|
||||||
|
Enables stencil operations without a preset.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_FLAG_READ" value="1" enum="StencilFlags">
|
||||||
|
The material will only be rendered where it passes a stencil comparison with existing stencil buffer values. See [enum StencilCompare].
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_FLAG_WRITE" value="2" enum="StencilFlags">
|
||||||
|
The material will write the reference value to the stencil buffer where it passes the depth test.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_FLAG_WRITE_DEPTH_FAIL" value="4" enum="StencilFlags">
|
||||||
|
The material will write the reference value to the stencil buffer where it fails the depth test.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_COMPARE_ALWAYS" value="0" enum="StencilCompare">
|
||||||
|
Always passes the stencil test.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_COMPARE_LESS" value="1" enum="StencilCompare">
|
||||||
|
Passes the stencil test when the reference value is less than the existing stencil value.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_COMPARE_EQUAL" value="2" enum="StencilCompare">
|
||||||
|
Passes the stencil test when the reference value is equal to the existing stencil value.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_COMPARE_LESS_OR_EQUAL" value="3" enum="StencilCompare">
|
||||||
|
Passes the stencil test when the reference value is less than or equal to the existing stencil value.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_COMPARE_GREATER" value="4" enum="StencilCompare">
|
||||||
|
Passes the stencil test when the reference value is greater than the existing stencil value.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_COMPARE_NOT_EQUAL" value="5" enum="StencilCompare">
|
||||||
|
Passes the stencil test when the reference value is not equal to the existing stencil value.
|
||||||
|
</constant>
|
||||||
|
<constant name="STENCIL_COMPARE_GREATER_OR_EQUAL" value="6" enum="StencilCompare">
|
||||||
|
Passes the stencil test when the reference value is greater than or equal to the existing stencil value.
|
||||||
|
</constant>
|
||||||
</constants>
|
</constants>
|
||||||
</class>
|
</class>
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,10 @@ void RasterizerGLES3::clear_depth(float p_depth) {
|
||||||
#endif // GLES_API_ENABLED
|
#endif // GLES_API_ENABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerGLES3::clear_stencil(int32_t p_stencil) {
|
||||||
|
glClearStencil(p_stencil);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CAN_DEBUG
|
#ifdef CAN_DEBUG
|
||||||
static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
|
static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
|
||||||
// These are ultimately annoying, so removing for now.
|
// These are ultimately annoying, so removing for now.
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ public:
|
||||||
|
|
||||||
static bool is_gles_over_gl() { return gles_over_gl; }
|
static bool is_gles_over_gl() { return gles_over_gl; }
|
||||||
static void clear_depth(float p_depth);
|
static void clear_depth(float p_depth);
|
||||||
|
static void clear_stencil(int32_t p_stencil);
|
||||||
|
|
||||||
static void make_current(bool p_gles_over_gl) {
|
static void make_current(bool p_gles_over_gl) {
|
||||||
gles_over_gl = p_gles_over_gl;
|
gles_over_gl = p_gles_over_gl;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include "drivers/gles3/effects/copy_effects.h"
|
#include "drivers/gles3/effects/copy_effects.h"
|
||||||
#include "drivers/gles3/effects/feed_effects.h"
|
#include "drivers/gles3/effects/feed_effects.h"
|
||||||
|
#include "drivers/gles3/storage/material_storage.h"
|
||||||
#include "rasterizer_gles3.h"
|
#include "rasterizer_gles3.h"
|
||||||
#include "storage/config.h"
|
#include "storage/config.h"
|
||||||
#include "storage/mesh_storage.h"
|
#include "storage/mesh_storage.h"
|
||||||
|
|
@ -223,10 +224,14 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
|
||||||
flags |= GeometryInstanceSurface::FLAG_USES_DOUBLE_SIDED_SHADOWS;
|
flags |= GeometryInstanceSurface::FLAG_USES_DOUBLE_SIDED_SHADOWS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED) {
|
if (p_material->shader_data->stencil_enabled) {
|
||||||
|
flags |= GeometryInstanceSurface::FLAG_USES_STENCIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test != GLES3::SceneShaderData::DEPTH_TEST_ENABLED) {
|
||||||
//material is only meant for alpha pass
|
//material is only meant for alpha pass
|
||||||
flags |= GeometryInstanceSurface::FLAG_PASS_ALPHA;
|
flags |= GeometryInstanceSurface::FLAG_PASS_ALPHA;
|
||||||
if (p_material->shader_data->uses_depth_prepass_alpha && !(p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED)) {
|
if (p_material->shader_data->uses_depth_prepass_alpha && !(p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test != GLES3::SceneShaderData::DEPTH_TEST_ENABLED)) {
|
||||||
flags |= GeometryInstanceSurface::FLAG_PASS_DEPTH;
|
flags |= GeometryInstanceSurface::FLAG_PASS_DEPTH;
|
||||||
flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW;
|
flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW;
|
||||||
}
|
}
|
||||||
|
|
@ -236,6 +241,17 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
|
||||||
flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW;
|
flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_material->shader_data->stencil_enabled) {
|
||||||
|
if (p_material->shader_data->stencil_flags & GLES3::SceneShaderData::STENCIL_FLAG_READ) {
|
||||||
|
// Stencil materials which read from the stencil buffer must be in the alpha pass.
|
||||||
|
// This is critical to preserve compatibility once we'll have the compositor.
|
||||||
|
if (!(flags & GeometryInstanceSurface::FLAG_PASS_ALPHA)) {
|
||||||
|
String shader_path = p_material->shader_data->path.is_empty() ? "" : "(" + p_material->shader_data->path + ")";
|
||||||
|
ERR_PRINT_ED(vformat("Attempting to use a shader %s that reads stencil but is not in the alpha queue. Ensure the material uses alpha blending or has depth_draw disabled or depth_test disabled.", shader_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GLES3::SceneMaterialData *material_shadow = nullptr;
|
GLES3::SceneMaterialData *material_shadow = nullptr;
|
||||||
void *surface_shadow = nullptr;
|
void *surface_shadow = nullptr;
|
||||||
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_world_coordinates && !p_material->shader_data->wireframe) {
|
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_world_coordinates && !p_material->shader_data->wireframe) {
|
||||||
|
|
@ -1233,6 +1249,7 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
|
||||||
scene_state.used_screen_texture = false;
|
scene_state.used_screen_texture = false;
|
||||||
scene_state.used_normal_texture = false;
|
scene_state.used_normal_texture = false;
|
||||||
scene_state.used_depth_texture = false;
|
scene_state.used_depth_texture = false;
|
||||||
|
scene_state.used_opaque_stencil = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Plane near_plane;
|
Plane near_plane;
|
||||||
|
|
@ -1426,6 +1443,9 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
|
||||||
if (surf->flags & GeometryInstanceSurface::FLAG_USES_DEPTH_TEXTURE) {
|
if (surf->flags & GeometryInstanceSurface::FLAG_USES_DEPTH_TEXTURE) {
|
||||||
scene_state.used_depth_texture = true;
|
scene_state.used_depth_texture = true;
|
||||||
}
|
}
|
||||||
|
if ((surf->flags & GeometryInstanceSurface::FLAG_USES_STENCIL) && !force_alpha && (surf->flags & (GeometryInstanceSurface::FLAG_PASS_DEPTH | GeometryInstanceSurface::FLAG_PASS_OPAQUE))) {
|
||||||
|
scene_state.used_opaque_stencil = true;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (p_pass_mode == PASS_MODE_SHADOW) {
|
} else if (p_pass_mode == PASS_MODE_SHADOW) {
|
||||||
if (surf->flags & GeometryInstanceSurface::FLAG_PASS_SHADOW) {
|
if (surf->flags & GeometryInstanceSurface::FLAG_PASS_SHADOW) {
|
||||||
|
|
@ -2184,7 +2204,7 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
|
||||||
scene_state.reset_gl_state();
|
scene_state.reset_gl_state();
|
||||||
scene_state.enable_gl_depth_test(true);
|
scene_state.enable_gl_depth_test(true);
|
||||||
scene_state.enable_gl_depth_draw(true);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_GREATER);
|
scene_state.set_gl_depth_func(GL_GREATER);
|
||||||
|
|
||||||
glColorMask(0, 0, 0, 0);
|
glColorMask(0, 0, 0, 0);
|
||||||
glDrawBuffers(0, nullptr);
|
glDrawBuffers(0, nullptr);
|
||||||
|
|
@ -2489,6 +2509,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
// Do depth prepass if it's explicitly enabled
|
// Do depth prepass if it's explicitly enabled
|
||||||
bool use_depth_prepass = config->use_depth_prepass;
|
bool use_depth_prepass = config->use_depth_prepass;
|
||||||
|
|
||||||
|
// Forcibly enable depth prepass if opaque stencil writes are used.
|
||||||
|
use_depth_prepass = use_depth_prepass || scene_state.used_opaque_stencil;
|
||||||
|
|
||||||
// Don't do depth prepass we are rendering overdraw
|
// Don't do depth prepass we are rendering overdraw
|
||||||
use_depth_prepass = use_depth_prepass && get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_OVERDRAW;
|
use_depth_prepass = use_depth_prepass && get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_OVERDRAW;
|
||||||
|
|
||||||
|
|
@ -2503,12 +2526,15 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
scene_state.enable_gl_depth_test(true);
|
scene_state.enable_gl_depth_test(true);
|
||||||
scene_state.enable_gl_depth_draw(true);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
scene_state.enable_gl_blend(false);
|
scene_state.enable_gl_blend(false);
|
||||||
glDepthFunc(GL_GEQUAL);
|
scene_state.set_gl_depth_func(GL_GEQUAL);
|
||||||
scene_state.enable_gl_scissor_test(false);
|
scene_state.enable_gl_scissor_test(false);
|
||||||
|
scene_state.enable_gl_stencil_test(false);
|
||||||
|
scene_state.set_gl_stencil_write_mask(255);
|
||||||
|
|
||||||
glColorMask(0, 0, 0, 0);
|
glColorMask(0, 0, 0, 0);
|
||||||
RasterizerGLES3::clear_depth(0.0);
|
RasterizerGLES3::clear_depth(0.0);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
RasterizerGLES3::clear_stencil(0);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
// Some desktop GL implementations fall apart when using Multiview with GL_NONE.
|
// Some desktop GL implementations fall apart when using Multiview with GL_NONE.
|
||||||
GLuint db = p_camera_data->view_count > 1 ? GL_COLOR_ATTACHMENT0 : GL_NONE;
|
GLuint db = p_camera_data->view_count > 1 ? GL_COLOR_ATTACHMENT0 : GL_NONE;
|
||||||
glDrawBuffers(1, &db);
|
glDrawBuffers(1, &db);
|
||||||
|
|
@ -2541,16 +2567,19 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
scene_state.enable_gl_scissor_test(false);
|
scene_state.enable_gl_scissor_test(false);
|
||||||
scene_state.enable_gl_depth_test(true);
|
scene_state.enable_gl_depth_test(true);
|
||||||
scene_state.enable_gl_depth_draw(true);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_GEQUAL);
|
scene_state.set_gl_depth_func(GL_GEQUAL);
|
||||||
|
|
||||||
{
|
{
|
||||||
GLuint db = GL_COLOR_ATTACHMENT0;
|
GLuint db = GL_COLOR_ATTACHMENT0;
|
||||||
glDrawBuffers(1, &db);
|
glDrawBuffers(1, &db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scene_state.enable_gl_stencil_test(false);
|
||||||
|
|
||||||
if (!fb_cleared) {
|
if (!fb_cleared) {
|
||||||
RasterizerGLES3::clear_depth(0.0);
|
RasterizerGLES3::clear_depth(0.0);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
RasterizerGLES3::clear_stencil(0);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to clear framebuffer unless:
|
// Need to clear framebuffer unless:
|
||||||
|
|
@ -2630,11 +2659,13 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
_render_list_template<PASS_MODE_COLOR>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_OPAQUE].elements.size());
|
_render_list_template<PASS_MODE_COLOR>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_OPAQUE].elements.size());
|
||||||
|
|
||||||
scene_state.enable_gl_depth_draw(false);
|
scene_state.enable_gl_depth_draw(false);
|
||||||
|
scene_state.enable_gl_stencil_test(false);
|
||||||
|
|
||||||
if (draw_sky || draw_sky_fog_only) {
|
if (draw_sky || draw_sky_fog_only) {
|
||||||
RENDER_TIMESTAMP("Render Sky");
|
RENDER_TIMESTAMP("Render Sky");
|
||||||
|
|
||||||
scene_state.enable_gl_depth_test(true);
|
scene_state.enable_gl_depth_test(true);
|
||||||
|
scene_state.set_gl_depth_func(GL_GEQUAL);
|
||||||
scene_state.enable_gl_blend(false);
|
scene_state.enable_gl_blend(false);
|
||||||
scene_state.set_gl_cull_mode(RS::CULL_MODE_BACK);
|
scene_state.set_gl_cull_mode(RS::CULL_MODE_BACK);
|
||||||
|
|
||||||
|
|
@ -2687,7 +2718,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
if (scene_state.used_depth_texture) {
|
if (scene_state.used_depth_texture) {
|
||||||
glBlitFramebuffer(0, 0, size.x, size.y,
|
glBlitFramebuffer(0, 0, size.x, size.y,
|
||||||
0, 0, size.x, size.y,
|
0, 0, size.x, size.y,
|
||||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
|
||||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 7);
|
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 7);
|
||||||
glBindTexture(GL_TEXTURE_2D, backbuffer_depth);
|
glBindTexture(GL_TEXTURE_2D, backbuffer_depth);
|
||||||
}
|
}
|
||||||
|
|
@ -2705,6 +2736,8 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
|
|
||||||
_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true);
|
_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true);
|
||||||
|
|
||||||
|
scene_state.enable_gl_stencil_test(false);
|
||||||
|
|
||||||
if (!flip_y) {
|
if (!flip_y) {
|
||||||
// Restore the default winding order.
|
// Restore the default winding order.
|
||||||
glFrontFace(GL_CCW);
|
glFrontFace(GL_CCW);
|
||||||
|
|
@ -2834,7 +2867,7 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||||
// Copy depth buffer
|
// Copy depth buffer
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_int);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_int);
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_rt);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_rt);
|
||||||
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
|
||||||
|
|
@ -2863,10 +2896,10 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||||
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
for (uint32_t v = 0; v < view_count; v++) {
|
||||||
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, read_color, 0, v);
|
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, read_color, 0, v);
|
||||||
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, read_depth, 0, v);
|
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, read_depth, 0, v);
|
||||||
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
|
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
|
||||||
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
|
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, write_depth, 0, v);
|
||||||
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, internal_size.x, internal_size.y, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, internal_size.x, internal_size.y, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2908,10 +2941,10 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
|
||||||
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
for (uint32_t v = 0; v < view_count; v++) {
|
||||||
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, read_depth, 0, v);
|
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, read_depth, 0, v);
|
||||||
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
|
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, write_depth, 0, v);
|
||||||
|
|
||||||
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3016,7 +3049,13 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
|
if constexpr (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
|
||||||
scene_state.enable_gl_depth_test(shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_ENABLED);
|
scene_state.enable_gl_depth_test(shader->depth_test != GLES3::SceneShaderData::DEPTH_TEST_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_ENABLED_INVERTED) {
|
||||||
|
scene_state.set_gl_depth_func(GL_LESS);
|
||||||
|
} else {
|
||||||
|
scene_state.set_gl_depth_func(GL_GEQUAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (p_pass_mode != PASS_MODE_SHADOW) {
|
if constexpr (p_pass_mode != PASS_MODE_SHADOW) {
|
||||||
|
|
@ -3044,6 +3083,47 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stencil.
|
||||||
|
if (shader->stencil_enabled) {
|
||||||
|
static const GLenum stencil_compare_table[GLES3::SceneShaderData::STENCIL_COMPARE_MAX] = {
|
||||||
|
GL_LESS,
|
||||||
|
GL_EQUAL,
|
||||||
|
GL_LEQUAL,
|
||||||
|
GL_GREATER,
|
||||||
|
GL_NOTEQUAL,
|
||||||
|
GL_GEQUAL,
|
||||||
|
GL_ALWAYS,
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum stencil_compare = stencil_compare_table[shader->stencil_compare];
|
||||||
|
GLuint stencil_compare_mask = 0;
|
||||||
|
GLuint stencil_write_mask = 0;
|
||||||
|
GLenum stencil_op_dpfail = GL_KEEP;
|
||||||
|
GLenum stencil_op_dppass = GL_KEEP;
|
||||||
|
|
||||||
|
if (shader->stencil_flags & GLES3::SceneShaderData::STENCIL_FLAG_READ) {
|
||||||
|
stencil_compare_mask = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shader->stencil_flags & GLES3::SceneShaderData::STENCIL_FLAG_WRITE) {
|
||||||
|
stencil_op_dppass = GL_REPLACE;
|
||||||
|
stencil_write_mask = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shader->stencil_flags & GLES3::SceneShaderData::STENCIL_FLAG_WRITE_DEPTH_FAIL) {
|
||||||
|
stencil_op_dpfail = GL_REPLACE;
|
||||||
|
stencil_write_mask = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_state.enable_gl_stencil_test(true);
|
||||||
|
scene_state.set_gl_stencil_func(stencil_compare, shader->stencil_reference, stencil_compare_mask);
|
||||||
|
scene_state.set_gl_stencil_write_mask(stencil_write_mask);
|
||||||
|
scene_state.set_gl_stencil_op(GL_KEEP, stencil_op_dpfail, stencil_op_dppass);
|
||||||
|
} else {
|
||||||
|
scene_state.enable_gl_stencil_test(false);
|
||||||
|
scene_state.set_gl_stencil_write_mask(255);
|
||||||
|
}
|
||||||
|
|
||||||
if constexpr (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
|
if constexpr (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
|
||||||
if (!uses_additive_lighting && pass == 1) {
|
if (!uses_additive_lighting && pass == 1) {
|
||||||
// Don't render additive passes if not using additive lighting.
|
// Don't render additive passes if not using additive lighting.
|
||||||
|
|
@ -3713,7 +3793,7 @@ void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider,
|
||||||
scene_state.reset_gl_state();
|
scene_state.reset_gl_state();
|
||||||
scene_state.enable_gl_depth_test(true);
|
scene_state.enable_gl_depth_test(true);
|
||||||
scene_state.enable_gl_depth_draw(true);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_GREATER);
|
scene_state.set_gl_depth_func(GL_GREATER);
|
||||||
|
|
||||||
glDrawBuffers(0, nullptr);
|
glDrawBuffers(0, nullptr);
|
||||||
|
|
||||||
|
|
@ -3759,7 +3839,7 @@ void RasterizerSceneGLES3::_render_uv2(const PagedArray<RenderGeometryInstance *
|
||||||
scene_state.reset_gl_state();
|
scene_state.reset_gl_state();
|
||||||
scene_state.enable_gl_depth_test(true);
|
scene_state.enable_gl_depth_test(true);
|
||||||
scene_state.enable_gl_depth_draw(true);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_GREATER);
|
scene_state.set_gl_depth_func(GL_GREATER);
|
||||||
|
|
||||||
TightLocalVector<GLenum> draw_buffers;
|
TightLocalVector<GLenum> draw_buffers;
|
||||||
draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
|
draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
|
||||||
|
|
@ -3852,7 +3932,7 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES
|
||||||
glViewport(0, 0, shadow_atlas_size, shadow_atlas_size);
|
glViewport(0, 0, shadow_atlas_size, shadow_atlas_size);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
scene_state.enable_gl_depth_draw(true);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_ALWAYS);
|
scene_state.set_gl_depth_func(GL_ALWAYS);
|
||||||
scene_state.set_gl_cull_mode(RS::CULL_MODE_DISABLED);
|
scene_state.set_gl_cull_mode(RS::CULL_MODE_DISABLED);
|
||||||
|
|
||||||
// Loop through quadrants and copy shadows over.
|
// Loop through quadrants and copy shadows over.
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "platform_gl.h"
|
||||||
#ifdef GLES3_ENABLED
|
#ifdef GLES3_ENABLED
|
||||||
|
|
||||||
#include "core/math/projection.h"
|
#include "core/math/projection.h"
|
||||||
|
|
@ -246,6 +247,7 @@ private:
|
||||||
FLAG_USES_DEPTH_TEXTURE = 4096,
|
FLAG_USES_DEPTH_TEXTURE = 4096,
|
||||||
FLAG_USES_NORMAL_TEXTURE = 8192,
|
FLAG_USES_NORMAL_TEXTURE = 8192,
|
||||||
FLAG_USES_DOUBLE_SIDED_SHADOWS = 16384,
|
FLAG_USES_DOUBLE_SIDED_SHADOWS = 16384,
|
||||||
|
FLAG_USES_STENCIL = 32768,
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
|
@ -462,6 +464,7 @@ private:
|
||||||
|
|
||||||
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
||||||
RS::CullMode cull_mode = RS::CULL_MODE_BACK;
|
RS::CullMode cull_mode = RS::CULL_MODE_BACK;
|
||||||
|
GLenum current_depth_function = GL_GEQUAL;
|
||||||
|
|
||||||
bool current_blend_enabled = false;
|
bool current_blend_enabled = false;
|
||||||
bool current_depth_draw_enabled = false;
|
bool current_depth_draw_enabled = false;
|
||||||
|
|
@ -483,6 +486,18 @@ private:
|
||||||
current_depth_draw_enabled = false;
|
current_depth_draw_enabled = false;
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
current_depth_test_enabled = false;
|
current_depth_test_enabled = false;
|
||||||
|
|
||||||
|
glDepthFunc(GL_GEQUAL);
|
||||||
|
current_depth_function = GL_GEQUAL;
|
||||||
|
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
current_stencil_test_enabled = false;
|
||||||
|
glStencilMask(255);
|
||||||
|
current_stencil_write_mask = 255;
|
||||||
|
glStencilFunc(GL_ALWAYS, 0, 255);
|
||||||
|
current_stencil_compare = GL_ALWAYS;
|
||||||
|
current_stencil_reference = 0;
|
||||||
|
current_stencil_compare_mask = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_gl_cull_mode(RS::CullMode p_mode) {
|
void set_gl_cull_mode(RS::CullMode p_mode) {
|
||||||
|
|
@ -540,10 +555,63 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_gl_depth_func(GLenum p_depth_func) {
|
||||||
|
if (current_depth_function != p_depth_func) {
|
||||||
|
glDepthFunc(p_depth_func);
|
||||||
|
current_depth_function = p_depth_func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_gl_stencil_test(bool p_enabled) {
|
||||||
|
if (current_stencil_test_enabled != p_enabled) {
|
||||||
|
if (p_enabled) {
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
}
|
||||||
|
current_stencil_test_enabled = p_enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_gl_stencil_func(GLenum p_compare, GLint p_reference, GLenum p_compare_mask) {
|
||||||
|
if (current_stencil_compare != p_compare || current_stencil_reference != p_reference || current_stencil_compare_mask != p_compare_mask) {
|
||||||
|
glStencilFunc(p_compare, p_reference, p_compare_mask);
|
||||||
|
current_stencil_compare = p_compare;
|
||||||
|
current_stencil_reference = p_reference;
|
||||||
|
current_stencil_compare_mask = p_compare_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_gl_stencil_write_mask(GLuint p_mask) {
|
||||||
|
if (current_stencil_write_mask != p_mask) {
|
||||||
|
glStencilMask(p_mask);
|
||||||
|
current_stencil_write_mask = p_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_gl_stencil_op(GLenum p_op_fail, GLenum p_op_dpfail, GLenum p_op_dppass) {
|
||||||
|
if (current_stencil_op_fail != p_op_fail || current_stencil_op_dpfail != p_op_dpfail || current_stencil_op_dppass != p_op_dppass) {
|
||||||
|
glStencilOp(p_op_fail, p_op_dpfail, p_op_dppass);
|
||||||
|
current_stencil_op_fail = p_op_fail;
|
||||||
|
current_stencil_op_dpfail = p_op_dpfail;
|
||||||
|
current_stencil_op_dppass = p_op_dppass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum current_stencil_compare = GL_ALWAYS;
|
||||||
|
GLuint current_stencil_compare_mask = 255;
|
||||||
|
GLuint current_stencil_write_mask = 255;
|
||||||
|
GLint current_stencil_reference = 0;
|
||||||
|
GLenum current_stencil_op_fail = GL_KEEP;
|
||||||
|
GLenum current_stencil_op_dpfail = GL_KEEP;
|
||||||
|
GLenum current_stencil_op_dppass = GL_KEEP;
|
||||||
|
bool current_stencil_test_enabled = false;
|
||||||
|
|
||||||
bool texscreen_copied = false;
|
bool texscreen_copied = false;
|
||||||
bool used_screen_texture = false;
|
bool used_screen_texture = false;
|
||||||
bool used_normal_texture = false;
|
bool used_normal_texture = false;
|
||||||
bool used_depth_texture = false;
|
bool used_depth_texture = false;
|
||||||
|
bool used_opaque_stencil = false;
|
||||||
|
|
||||||
LightData *omni_lights = nullptr;
|
LightData *omni_lights = nullptr;
|
||||||
LightData *spot_lights = nullptr;
|
LightData *spot_lights = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -2945,11 +2945,18 @@ void SceneShaderData::set_code(const String &p_code) {
|
||||||
|
|
||||||
// Actual enums set further down after compilation.
|
// Actual enums set further down after compilation.
|
||||||
int blend_modei = BLEND_MODE_MIX;
|
int blend_modei = BLEND_MODE_MIX;
|
||||||
int depth_testi = DEPTH_TEST_ENABLED;
|
int depth_test_disabledi = 0;
|
||||||
|
int depth_test_invertedi = 0;
|
||||||
int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF;
|
int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF;
|
||||||
int cull_modei = RS::CULL_MODE_BACK;
|
int cull_modei = RS::CULL_MODE_BACK;
|
||||||
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
||||||
|
|
||||||
|
int stencil_readi = 0;
|
||||||
|
int stencil_writei = 0;
|
||||||
|
int stencil_write_depth_faili = 0;
|
||||||
|
int stencil_comparei = STENCIL_COMPARE_ALWAYS;
|
||||||
|
int stencil_referencei = -1;
|
||||||
|
|
||||||
ShaderCompiler::IdentifierActions actions;
|
ShaderCompiler::IdentifierActions actions;
|
||||||
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
|
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
|
||||||
actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
|
actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
|
||||||
|
|
@ -2968,7 +2975,8 @@ void SceneShaderData::set_code(const String &p_code) {
|
||||||
actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
|
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);
|
actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
|
||||||
|
|
||||||
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
|
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_test_disabledi, 1);
|
||||||
|
actions.render_mode_values["depth_test_inverted"] = Pair<int *, int>(&depth_test_invertedi, 1);
|
||||||
|
|
||||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_DISABLED);
|
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_DISABLED);
|
||||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_FRONT);
|
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_FRONT);
|
||||||
|
|
@ -3018,6 +3026,20 @@ void SceneShaderData::set_code(const String &p_code) {
|
||||||
actions.usage_flag_pointers["BONE_INDICES"] = &uses_bones;
|
actions.usage_flag_pointers["BONE_INDICES"] = &uses_bones;
|
||||||
actions.usage_flag_pointers["BONE_WEIGHTS"] = &uses_weights;
|
actions.usage_flag_pointers["BONE_WEIGHTS"] = &uses_weights;
|
||||||
|
|
||||||
|
actions.stencil_mode_values["read"] = Pair<int *, int>(&stencil_readi, STENCIL_FLAG_READ);
|
||||||
|
actions.stencil_mode_values["write"] = Pair<int *, int>(&stencil_writei, STENCIL_FLAG_WRITE);
|
||||||
|
actions.stencil_mode_values["write_depth_fail"] = Pair<int *, int>(&stencil_write_depth_faili, STENCIL_FLAG_WRITE_DEPTH_FAIL);
|
||||||
|
|
||||||
|
actions.stencil_mode_values["compare_less"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_LESS);
|
||||||
|
actions.stencil_mode_values["compare_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_less_or_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_LESS_OR_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_greater"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_GREATER);
|
||||||
|
actions.stencil_mode_values["compare_not_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_NOT_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_greater_or_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_GREATER_OR_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_always"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_ALWAYS);
|
||||||
|
|
||||||
|
actions.stencil_reference = &stencil_referencei;
|
||||||
|
|
||||||
actions.uniforms = &uniforms;
|
actions.uniforms = &uniforms;
|
||||||
|
|
||||||
Error err = MaterialStorage::get_singleton()->shaders.compiler_scene.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
Error err = MaterialStorage::get_singleton()->shaders.compiler_scene.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
||||||
|
|
@ -3030,7 +3052,13 @@ void SceneShaderData::set_code(const String &p_code) {
|
||||||
blend_mode = BlendMode(blend_modei);
|
blend_mode = BlendMode(blend_modei);
|
||||||
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
|
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
|
||||||
depth_draw = DepthDraw(depth_drawi);
|
depth_draw = DepthDraw(depth_drawi);
|
||||||
depth_test = DepthTest(depth_testi);
|
if (depth_test_disabledi) {
|
||||||
|
depth_test = DEPTH_TEST_DISABLED;
|
||||||
|
} else if (depth_test_invertedi) {
|
||||||
|
depth_test = DEPTH_TEST_ENABLED_INVERTED;
|
||||||
|
} else {
|
||||||
|
depth_test = DEPTH_TEST_ENABLED;
|
||||||
|
}
|
||||||
cull_mode = RS::CullMode(cull_modei);
|
cull_mode = RS::CullMode(cull_modei);
|
||||||
|
|
||||||
vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL; // We can always read vertices and normals.
|
vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL; // We can always read vertices and normals.
|
||||||
|
|
@ -3052,6 +3080,11 @@ void SceneShaderData::set_code(const String &p_code) {
|
||||||
uses_vertex_time = gen_code.uses_vertex_time;
|
uses_vertex_time = gen_code.uses_vertex_time;
|
||||||
uses_fragment_time = gen_code.uses_fragment_time;
|
uses_fragment_time = gen_code.uses_fragment_time;
|
||||||
|
|
||||||
|
stencil_enabled = stencil_referencei != -1;
|
||||||
|
stencil_flags = stencil_readi | stencil_writei | stencil_write_depth_faili;
|
||||||
|
stencil_compare = StencilCompare(stencil_comparei);
|
||||||
|
stencil_reference = stencil_referencei;
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (uses_particle_trails) {
|
if (uses_particle_trails) {
|
||||||
WARN_PRINT_ONCE_ED("Particle trails are only available when using the Forward+ or Mobile renderers.");
|
WARN_PRINT_ONCE_ED("Particle trails are only available when using the Forward+ or Mobile renderers.");
|
||||||
|
|
@ -3118,7 +3151,7 @@ bool SceneShaderData::casts_shadows() const {
|
||||||
bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha;
|
bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha;
|
||||||
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
||||||
|
|
||||||
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
|
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test != DEPTH_TEST_ENABLED));
|
||||||
}
|
}
|
||||||
|
|
||||||
RS::ShaderNativeSourceCode SceneShaderData::get_native_source_code() const {
|
RS::ShaderNativeSourceCode SceneShaderData::get_native_source_code() const {
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,25 @@ struct SceneShaderData : public ShaderData {
|
||||||
|
|
||||||
enum DepthTest {
|
enum DepthTest {
|
||||||
DEPTH_TEST_DISABLED,
|
DEPTH_TEST_DISABLED,
|
||||||
DEPTH_TEST_ENABLED
|
DEPTH_TEST_ENABLED,
|
||||||
|
DEPTH_TEST_ENABLED_INVERTED,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StencilCompare {
|
||||||
|
STENCIL_COMPARE_LESS,
|
||||||
|
STENCIL_COMPARE_EQUAL,
|
||||||
|
STENCIL_COMPARE_LESS_OR_EQUAL,
|
||||||
|
STENCIL_COMPARE_GREATER,
|
||||||
|
STENCIL_COMPARE_NOT_EQUAL,
|
||||||
|
STENCIL_COMPARE_GREATER_OR_EQUAL,
|
||||||
|
STENCIL_COMPARE_ALWAYS,
|
||||||
|
STENCIL_COMPARE_MAX // not an actual operator, just the amount of operators
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StencilFlags {
|
||||||
|
STENCIL_FLAG_READ = 1,
|
||||||
|
STENCIL_FLAG_WRITE = 2,
|
||||||
|
STENCIL_FLAG_WRITE_DEPTH_FAIL = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AlphaAntiAliasing {
|
enum AlphaAntiAliasing {
|
||||||
|
|
@ -285,6 +303,11 @@ struct SceneShaderData : public ShaderData {
|
||||||
DepthTest depth_test;
|
DepthTest depth_test;
|
||||||
RS::CullMode cull_mode;
|
RS::CullMode cull_mode;
|
||||||
|
|
||||||
|
StencilCompare stencil_compare;
|
||||||
|
uint32_t stencil_flags;
|
||||||
|
int32_t stencil_reference;
|
||||||
|
bool stencil_enabled;
|
||||||
|
|
||||||
bool uses_point_size;
|
bool uses_point_size;
|
||||||
bool uses_alpha;
|
bool uses_alpha;
|
||||||
bool uses_alpha_clip;
|
bool uses_alpha_clip;
|
||||||
|
|
|
||||||
|
|
@ -63,14 +63,14 @@ void RenderSceneBuffersGLES3::_rt_attach_textures(GLuint p_color, GLuint p_depth
|
||||||
if (p_samples > 1) {
|
if (p_samples > 1) {
|
||||||
#if defined(ANDROID_ENABLED) || defined(WEB_ENABLED)
|
#if defined(ANDROID_ENABLED) || defined(WEB_ENABLED)
|
||||||
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, p_samples, 0, p_view_count);
|
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, p_samples, 0, p_view_count);
|
||||||
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, p_depth, 0, p_samples, 0, p_view_count);
|
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, p_depth, 0, p_samples, 0, p_view_count);
|
||||||
#else
|
#else
|
||||||
ERR_PRINT_ONCE("Multiview MSAA isn't supported on this platform.");
|
ERR_PRINT_ONCE("Multiview MSAA isn't supported on this platform.");
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, 0, p_view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, 0, p_view_count);
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, p_depth, 0, 0, p_view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, p_depth, 0, 0, p_view_count);
|
||||||
#else
|
#else
|
||||||
ERR_PRINT_ONCE("Multiview isn't supported on this platform.");
|
ERR_PRINT_ONCE("Multiview isn't supported on this platform.");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -79,13 +79,13 @@ void RenderSceneBuffersGLES3::_rt_attach_textures(GLuint p_color, GLuint p_depth
|
||||||
if (p_samples > 1) {
|
if (p_samples > 1) {
|
||||||
#ifdef ANDROID_ENABLED
|
#ifdef ANDROID_ENABLED
|
||||||
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0, p_samples);
|
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0, p_samples);
|
||||||
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0, p_samples);
|
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0, p_samples);
|
||||||
#else
|
#else
|
||||||
ERR_PRINT_ONCE("MSAA via EXT_multisampled_render_to_texture isn't supported on this platform.");
|
ERR_PRINT_ONCE("MSAA via EXT_multisampled_render_to_texture isn't supported on this platform.");
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -196,7 +196,8 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||||
ERR_FAIL_COND(view_count == 0);
|
ERR_FAIL_COND(view_count == 0);
|
||||||
|
|
||||||
bool use_internal_buffer = scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF || apply_color_adjustments_in_post;
|
bool use_internal_buffer = scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF || apply_color_adjustments_in_post;
|
||||||
uint32_t depth_format_size = 3;
|
GLenum depth_format = GL_DEPTH24_STENCIL8;
|
||||||
|
uint32_t depth_format_size = 4;
|
||||||
bool use_multiview = view_count > 1;
|
bool use_multiview = view_count > 1;
|
||||||
|
|
||||||
if ((!use_internal_buffer || internal3d.color != 0) && (msaa3d.mode == RS::VIEWPORT_MSAA_DISABLED || msaa3d.color != 0)) {
|
if ((!use_internal_buffer || internal3d.color != 0) && (msaa3d.mode == RS::VIEWPORT_MSAA_DISABLED || msaa3d.color != 0)) {
|
||||||
|
|
@ -230,9 +231,9 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||||
glBindTexture(texture_target, internal3d.depth);
|
glBindTexture(texture_target, internal3d.depth);
|
||||||
|
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, internal_size.x, internal_size.y, view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
glTexImage3D(texture_target, 0, depth_format, internal_size.x, internal_size.y, view_count, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
||||||
} else {
|
} else {
|
||||||
glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, internal_size.x, internal_size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
glTexImage2D(texture_target, 0, depth_format, internal_size.x, internal_size.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
@ -250,13 +251,13 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, internal3d.color, 0, 0, view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, internal3d.color, 0, 0, view_count);
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, internal3d.depth, 0, 0, view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, internal3d.depth, 0, 0, view_count);
|
||||||
} else {
|
} else {
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, internal3d.color, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, internal3d.color, 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texture_target, internal3d.depth, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texture_target, internal3d.depth, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
|
@ -299,15 +300,15 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||||
glGenRenderbuffers(1, &msaa3d.depth);
|
glGenRenderbuffers(1, &msaa3d.depth);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, msaa3d.depth);
|
glBindRenderbuffer(GL_RENDERBUFFER, msaa3d.depth);
|
||||||
|
|
||||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa3d.samples, GL_DEPTH_COMPONENT24, internal_size.x, internal_size.y);
|
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa3d.samples, depth_format, internal_size.x, internal_size.y);
|
||||||
GLES3::Utilities::get_singleton()->render_buffer_allocated_data(msaa3d.depth, internal_size.x * internal_size.y * view_count * 3 * msaa3d.samples, "MSAA 3D depth render buffer");
|
GLES3::Utilities::get_singleton()->render_buffer_allocated_data(msaa3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size * msaa3d.samples, "MSAA 3D depth render buffer");
|
||||||
|
|
||||||
// Create our MSAA 3D FBO.
|
// Create our MSAA 3D FBO.
|
||||||
glGenFramebuffers(1, &msaa3d.fbo);
|
glGenFramebuffers(1, &msaa3d.fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
|
||||||
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaa3d.color);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaa3d.color);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msaa3d.depth);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, msaa3d.depth);
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
|
@ -341,9 +342,9 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.depth);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.depth);
|
||||||
|
|
||||||
#ifdef ANDROID_ENABLED
|
#ifdef ANDROID_ENABLED
|
||||||
glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, GL_DEPTH_COMPONENT24, internal_size.x, internal_size.y, view_count, GL_TRUE);
|
glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, depth_format, internal_size.x, internal_size.y, view_count, GL_TRUE);
|
||||||
#else
|
#else
|
||||||
glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, GL_DEPTH_COMPONENT24, internal_size.x, internal_size.y, view_count, GL_TRUE);
|
glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, depth_format, internal_size.x, internal_size.y, view_count, GL_TRUE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLES3::Utilities::get_singleton()->texture_allocated_data(msaa3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size * msaa3d.samples, "MSAA 3D depth texture");
|
GLES3::Utilities::get_singleton()->texture_allocated_data(msaa3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size * msaa3d.samples, "MSAA 3D depth texture");
|
||||||
|
|
@ -353,7 +354,7 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
|
||||||
|
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, msaa3d.color, 0, 0, view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, msaa3d.color, 0, 0, view_count);
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, msaa3d.depth, 0, 0, view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, msaa3d.depth, 0, 0, view_count);
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
|
@ -474,7 +475,8 @@ void RenderSceneBuffersGLES3::check_backbuffer(bool p_need_color, bool p_need_de
|
||||||
|
|
||||||
bool use_multiview = view_count > 1 && GLES3::Config::get_singleton()->multiview_supported;
|
bool use_multiview = view_count > 1 && GLES3::Config::get_singleton()->multiview_supported;
|
||||||
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
|
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
|
||||||
uint32_t depth_format_size = 3;
|
GLenum depth_format = GL_DEPTH24_STENCIL8;
|
||||||
|
uint32_t depth_format_size = 4;
|
||||||
|
|
||||||
if (backbuffer3d.color == 0 && p_need_color) {
|
if (backbuffer3d.color == 0 && p_need_color) {
|
||||||
glGenTextures(1, &backbuffer3d.color);
|
glGenTextures(1, &backbuffer3d.color);
|
||||||
|
|
@ -509,9 +511,9 @@ void RenderSceneBuffersGLES3::check_backbuffer(bool p_need_color, bool p_need_de
|
||||||
glBindTexture(texture_target, backbuffer3d.depth);
|
glBindTexture(texture_target, backbuffer3d.depth);
|
||||||
|
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, internal_size.x, internal_size.y, view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
glTexImage3D(texture_target, 0, depth_format, internal_size.x, internal_size.y, view_count, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT, nullptr);
|
||||||
} else {
|
} else {
|
||||||
glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, internal_size.x, internal_size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
glTexImage2D(texture_target, 0, depth_format, internal_size.x, internal_size.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
@ -523,12 +525,12 @@ void RenderSceneBuffersGLES3::check_backbuffer(bool p_need_color, bool p_need_de
|
||||||
|
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, backbuffer3d.depth, 0, 0, view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, backbuffer3d.depth, 0, 0, view_count);
|
||||||
} else {
|
} else {
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texture_target, backbuffer3d.depth, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texture_target, backbuffer3d.depth, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2183,14 +2183,15 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
|
||||||
ERR_FAIL_NULL(texture);
|
ERR_FAIL_NULL(texture);
|
||||||
|
|
||||||
rt->depth = texture->tex_id;
|
rt->depth = texture->tex_id;
|
||||||
|
rt->depth_has_stencil = rt->overridden.depth_has_stencil;
|
||||||
} else {
|
} else {
|
||||||
glGenTextures(1, &rt->depth);
|
glGenTextures(1, &rt->depth);
|
||||||
glBindTexture(texture_target, rt->depth);
|
glBindTexture(texture_target, rt->depth);
|
||||||
|
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, rt->view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
glTexImage3D(texture_target, 0, GL_DEPTH24_STENCIL8, rt->size.x, rt->size.y, rt->view_count, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
||||||
} else {
|
} else {
|
||||||
glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
glTexImage2D(texture_target, 0, GL_DEPTH24_STENCIL8, rt->size.x, rt->size.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
@ -2198,16 +2199,19 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
GLES3::Utilities::get_singleton()->texture_allocated_data(rt->depth, rt->size.x * rt->size.y * rt->view_count * 3, "Render target depth texture");
|
rt->depth_has_stencil = true;
|
||||||
|
|
||||||
|
GLES3::Utilities::get_singleton()->texture_allocated_data(rt->depth, rt->size.x * rt->size.y * rt->view_count * 4, "Render target depth texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->depth, 0, 0, rt->view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, rt->depth_has_stencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, rt->depth, 0, 0, rt->view_count);
|
||||||
} else {
|
} else {
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texture_target, rt->depth, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, rt->depth_has_stencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, texture_target, rt->depth, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
|
@ -2354,12 +2358,33 @@ void GLES3::TextureStorage::check_backbuffer(RenderTarget *rt, const bool uses_s
|
||||||
if (rt->backbuffer_depth == 0 && uses_depth_texture) {
|
if (rt->backbuffer_depth == 0 && uses_depth_texture) {
|
||||||
glGenTextures(1, &rt->backbuffer_depth);
|
glGenTextures(1, &rt->backbuffer_depth);
|
||||||
glBindTexture(texture_target, rt->backbuffer_depth);
|
glBindTexture(texture_target, rt->backbuffer_depth);
|
||||||
if (use_multiview) {
|
|
||||||
glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, rt->view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
GLint internal_format;
|
||||||
|
GLenum format;
|
||||||
|
GLenum type;
|
||||||
|
GLenum attachment;
|
||||||
|
int element_size;
|
||||||
|
|
||||||
|
if (rt->depth_has_stencil) {
|
||||||
|
internal_format = GL_DEPTH24_STENCIL8;
|
||||||
|
format = GL_DEPTH_STENCIL;
|
||||||
|
type = GL_UNSIGNED_INT_24_8;
|
||||||
|
attachment = GL_DEPTH_STENCIL_ATTACHMENT;
|
||||||
|
element_size = 4;
|
||||||
} else {
|
} else {
|
||||||
glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
internal_format = GL_DEPTH_COMPONENT24;
|
||||||
|
format = GL_DEPTH_COMPONENT;
|
||||||
|
type = GL_UNSIGNED_INT;
|
||||||
|
attachment = GL_DEPTH_ATTACHMENT;
|
||||||
|
element_size = 3;
|
||||||
}
|
}
|
||||||
GLES3::Utilities::get_singleton()->texture_allocated_data(rt->backbuffer_depth, rt->size.x * rt->size.y * rt->view_count * 3, "Render target backbuffer depth texture");
|
|
||||||
|
if (use_multiview) {
|
||||||
|
glTexImage3D(texture_target, 0, internal_format, rt->size.x, rt->size.y, rt->view_count, 0, format, type, nullptr);
|
||||||
|
} else {
|
||||||
|
glTexImage2D(texture_target, 0, internal_format, rt->size.x, rt->size.y, 0, format, type, nullptr);
|
||||||
|
}
|
||||||
|
GLES3::Utilities::get_singleton()->texture_allocated_data(rt->backbuffer_depth, rt->size.x * rt->size.y * rt->view_count * element_size, "Render target backbuffer depth texture");
|
||||||
|
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
@ -2367,12 +2392,12 @@ void GLES3::TextureStorage::check_backbuffer(RenderTarget *rt, const bool uses_s
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->backbuffer_depth, 0, 0, rt->view_count);
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, attachment, rt->backbuffer_depth, 0, 0, rt->view_count);
|
||||||
} else {
|
} else {
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->backbuffer_depth, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, rt->backbuffer_depth, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2546,6 +2571,7 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color
|
||||||
|
|
||||||
rt->overridden.color = p_color_texture;
|
rt->overridden.color = p_color_texture;
|
||||||
rt->overridden.depth = p_depth_texture;
|
rt->overridden.depth = p_depth_texture;
|
||||||
|
rt->overridden.depth_has_stencil = p_depth_texture.is_null();
|
||||||
rt->overridden.is_overridden = true;
|
rt->overridden.is_overridden = true;
|
||||||
|
|
||||||
uint32_t hash_key = hash_murmur3_one_64(p_color_texture.get_id());
|
uint32_t hash_key = hash_murmur3_one_64(p_color_texture.get_id());
|
||||||
|
|
@ -2557,6 +2583,7 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color
|
||||||
rt->fbo = cache->get().fbo;
|
rt->fbo = cache->get().fbo;
|
||||||
rt->color = cache->get().color;
|
rt->color = cache->get().color;
|
||||||
rt->depth = cache->get().depth;
|
rt->depth = cache->get().depth;
|
||||||
|
rt->depth_has_stencil = cache->get().depth_has_stencil;
|
||||||
rt->size = cache->get().size;
|
rt->size = cache->get().size;
|
||||||
rt->texture = p_color_texture;
|
rt->texture = p_color_texture;
|
||||||
return;
|
return;
|
||||||
|
|
@ -2568,6 +2595,7 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color
|
||||||
new_entry.fbo = rt->fbo;
|
new_entry.fbo = rt->fbo;
|
||||||
new_entry.color = rt->color;
|
new_entry.color = rt->color;
|
||||||
new_entry.depth = rt->depth;
|
new_entry.depth = rt->depth;
|
||||||
|
new_entry.depth_has_stencil = rt->depth_has_stencil;
|
||||||
new_entry.size = rt->size;
|
new_entry.size = rt->size;
|
||||||
// Keep track of any textures we had to allocate because they weren't overridden.
|
// Keep track of any textures we had to allocate because they weren't overridden.
|
||||||
if (p_color_texture.is_null()) {
|
if (p_color_texture.is_null()) {
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,7 @@ struct RenderTarget {
|
||||||
GLuint backbuffer_fbo = 0;
|
GLuint backbuffer_fbo = 0;
|
||||||
GLuint backbuffer = 0;
|
GLuint backbuffer = 0;
|
||||||
GLuint backbuffer_depth = 0;
|
GLuint backbuffer_depth = 0;
|
||||||
|
bool depth_has_stencil = true;
|
||||||
|
|
||||||
bool hdr = false; // For Compatibility this effects both 2D and 3D rendering!
|
bool hdr = false; // For Compatibility this effects both 2D and 3D rendering!
|
||||||
GLuint color_internal_format = GL_RGBA8;
|
GLuint color_internal_format = GL_RGBA8;
|
||||||
|
|
@ -375,6 +376,7 @@ struct RenderTarget {
|
||||||
|
|
||||||
struct RTOverridden {
|
struct RTOverridden {
|
||||||
bool is_overridden = false;
|
bool is_overridden = false;
|
||||||
|
bool depth_has_stencil = false;
|
||||||
RID color;
|
RID color;
|
||||||
RID depth;
|
RID depth;
|
||||||
RID velocity;
|
RID velocity;
|
||||||
|
|
@ -385,6 +387,7 @@ struct RenderTarget {
|
||||||
GLuint depth;
|
GLuint depth;
|
||||||
Size2i size;
|
Size2i size;
|
||||||
Vector<GLuint> allocated_textures;
|
Vector<GLuint> allocated_textures;
|
||||||
|
bool depth_has_stencil;
|
||||||
};
|
};
|
||||||
RBMap<uint32_t, FBOCacheEntry> fbo_cache;
|
RBMap<uint32_t, FBOCacheEntry> fbo_cache;
|
||||||
} overridden;
|
} overridden;
|
||||||
|
|
|
||||||
|
|
@ -269,17 +269,31 @@ void ShaderTextEditor::_load_theme_settings() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector<ShaderLanguage::ModeInfo> &modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
|
{
|
||||||
|
const Vector<ShaderLanguage::ModeInfo> &render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
|
||||||
|
|
||||||
for (int j = 0; j < modes.size(); j++) {
|
for (const ShaderLanguage::ModeInfo &mode_info : render_modes) {
|
||||||
const ShaderLanguage::ModeInfo &mode_info = modes[j];
|
if (!mode_info.options.is_empty()) {
|
||||||
|
for (const StringName &option : mode_info.options) {
|
||||||
if (!mode_info.options.is_empty()) {
|
built_ins.push_back(String(mode_info.name) + "_" + String(option));
|
||||||
for (int k = 0; k < mode_info.options.size(); k++) {
|
}
|
||||||
built_ins.push_back(String(mode_info.name) + "_" + String(mode_info.options[k]));
|
} else {
|
||||||
|
built_ins.push_back(String(mode_info.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const Vector<ShaderLanguage::ModeInfo> &stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(i));
|
||||||
|
|
||||||
|
for (const ShaderLanguage::ModeInfo &mode_info : stencil_modes) {
|
||||||
|
if (!mode_info.options.is_empty()) {
|
||||||
|
for (const StringName &option : mode_info.options) {
|
||||||
|
built_ins.push_back(String(mode_info.name) + "_" + String(option));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
built_ins.push_back(String(mode_info.name));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
built_ins.push_back(String(mode_info.name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -290,17 +304,31 @@ void ShaderTextEditor::_load_theme_settings() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector<ShaderLanguage::ModeInfo> &modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode()));
|
{
|
||||||
|
const Vector<ShaderLanguage::ModeInfo> &shader_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode()));
|
||||||
|
|
||||||
for (int i = 0; i < modes.size(); i++) {
|
for (const ShaderLanguage::ModeInfo &mode_info : shader_modes) {
|
||||||
const ShaderLanguage::ModeInfo &mode_info = modes[i];
|
if (!mode_info.options.is_empty()) {
|
||||||
|
for (const StringName &option : mode_info.options) {
|
||||||
if (!mode_info.options.is_empty()) {
|
built_ins.push_back(String(mode_info.name) + "_" + String(option));
|
||||||
for (int j = 0; j < mode_info.options.size(); j++) {
|
}
|
||||||
built_ins.push_back(String(mode_info.name) + "_" + String(mode_info.options[j]));
|
} else {
|
||||||
|
built_ins.push_back(String(mode_info.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const Vector<ShaderLanguage::ModeInfo> &stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(shader->get_mode()));
|
||||||
|
|
||||||
|
for (const ShaderLanguage::ModeInfo &mode_info : stencil_modes) {
|
||||||
|
if (!mode_info.options.is_empty()) {
|
||||||
|
for (const StringName &option : mode_info.options) {
|
||||||
|
built_ins.push_back(String(mode_info.name) + "_" + String(option));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
built_ins.push_back(String(mode_info.name));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
built_ins.push_back(String(mode_info.name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -437,6 +465,7 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptLa
|
||||||
_check_shader_mode();
|
_check_shader_mode();
|
||||||
comp_info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode()));
|
comp_info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode()));
|
||||||
comp_info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode()));
|
comp_info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode()));
|
||||||
|
comp_info.stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(shader->get_mode()));
|
||||||
comp_info.shader_types = ShaderTypes::get_singleton()->get_types();
|
comp_info.shader_types = ShaderTypes::get_singleton()->get_types();
|
||||||
|
|
||||||
sl.complete(code, comp_info, r_options, calltip);
|
sl.complete(code, comp_info, r_options, calltip);
|
||||||
|
|
@ -541,6 +570,7 @@ void ShaderTextEditor::_validate_script() {
|
||||||
Shader::Mode mode = shader->get_mode();
|
Shader::Mode mode = shader->get_mode();
|
||||||
comp_info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(mode));
|
comp_info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(mode));
|
||||||
comp_info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(mode));
|
comp_info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(mode));
|
||||||
|
comp_info.stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(mode));
|
||||||
comp_info.shader_types = ShaderTypes::get_singleton()->get_types();
|
comp_info.shader_types = ShaderTypes::get_singleton()->get_types();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6297,6 +6297,7 @@ void VisualShaderEditor::_update_preview() {
|
||||||
ShaderLanguage::ShaderCompileInfo info;
|
ShaderLanguage::ShaderCompileInfo info;
|
||||||
info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode()));
|
info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode()));
|
||||||
info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
|
info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
|
||||||
|
info.stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
|
||||||
info.shader_types = ShaderTypes::get_singleton()->get_types();
|
info.shader_types = ShaderTypes::get_singleton()->get_types();
|
||||||
info.global_shader_uniform_type_func = _visual_shader_editor_get_global_shader_uniform_type;
|
info.global_shader_uniform_type_func = _visual_shader_editor_get_global_shader_uniform_type;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -861,6 +861,17 @@ void BaseMaterial3D::_update_shader() {
|
||||||
}
|
}
|
||||||
if (flags[FLAG_DISABLE_DEPTH_TEST]) {
|
if (flags[FLAG_DISABLE_DEPTH_TEST]) {
|
||||||
code += ", depth_test_disabled";
|
code += ", depth_test_disabled";
|
||||||
|
} else {
|
||||||
|
switch (depth_test) {
|
||||||
|
case DEPTH_TEST_DEFAULT:
|
||||||
|
// depth_test_default is the default behavior, no need to emit it here.
|
||||||
|
break;
|
||||||
|
case DEPTH_TEST_INVERTED:
|
||||||
|
code += ", depth_test_inverted";
|
||||||
|
break;
|
||||||
|
case DEPTH_TEST_MAX:
|
||||||
|
break; // Internal value, skip.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (flags[FLAG_PARTICLE_TRAILS_MODE]) {
|
if (flags[FLAG_PARTICLE_TRAILS_MODE]) {
|
||||||
code += ", particle_trails";
|
code += ", particle_trails";
|
||||||
|
|
@ -901,6 +912,56 @@ void BaseMaterial3D::_update_shader() {
|
||||||
|
|
||||||
code += ";\n";
|
code += ";\n";
|
||||||
|
|
||||||
|
if (stencil_mode != STENCIL_MODE_DISABLED && stencil_flags != 0) {
|
||||||
|
code += "stencil_mode ";
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_READ) {
|
||||||
|
code += "read";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_WRITE) {
|
||||||
|
if (stencil_flags & STENCIL_FLAG_READ) {
|
||||||
|
code += ", ";
|
||||||
|
}
|
||||||
|
code += "write";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_WRITE_DEPTH_FAIL) {
|
||||||
|
if (stencil_flags & (STENCIL_FLAG_READ | STENCIL_FLAG_WRITE)) {
|
||||||
|
code += ", ";
|
||||||
|
}
|
||||||
|
code += "write_depth_fail";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (stencil_compare) {
|
||||||
|
case STENCIL_COMPARE_ALWAYS:
|
||||||
|
code += ", compare_always";
|
||||||
|
break;
|
||||||
|
case STENCIL_COMPARE_LESS:
|
||||||
|
code += ", compare_less";
|
||||||
|
break;
|
||||||
|
case STENCIL_COMPARE_EQUAL:
|
||||||
|
code += ", compare_equal";
|
||||||
|
break;
|
||||||
|
case STENCIL_COMPARE_LESS_OR_EQUAL:
|
||||||
|
code += ", compare_less_or_equal";
|
||||||
|
break;
|
||||||
|
case STENCIL_COMPARE_GREATER:
|
||||||
|
code += ", compare_greater";
|
||||||
|
break;
|
||||||
|
case STENCIL_COMPARE_NOT_EQUAL:
|
||||||
|
code += ", compare_not_equal";
|
||||||
|
break;
|
||||||
|
case STENCIL_COMPARE_GREATER_OR_EQUAL:
|
||||||
|
code += ", compare_greater_or_equal";
|
||||||
|
break;
|
||||||
|
case STENCIL_COMPARE_MAX:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
code += vformat(", %s;\n", stencil_reference);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate list of uniforms.
|
// Generate list of uniforms.
|
||||||
code += vformat(R"(
|
code += vformat(R"(
|
||||||
uniform vec4 albedo : source_color;
|
uniform vec4 albedo : source_color;
|
||||||
|
|
@ -2354,6 +2415,19 @@ BaseMaterial3D::DepthDrawMode BaseMaterial3D::get_depth_draw_mode() const {
|
||||||
return depth_draw_mode;
|
return depth_draw_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseMaterial3D::set_depth_test(DepthTest p_func) {
|
||||||
|
if (depth_test == p_func) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
depth_test = p_func;
|
||||||
|
_queue_shader_change();
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseMaterial3D::DepthTest BaseMaterial3D::get_depth_test() const {
|
||||||
|
return depth_test;
|
||||||
|
}
|
||||||
|
|
||||||
void BaseMaterial3D::set_cull_mode(CullMode p_mode) {
|
void BaseMaterial3D::set_cull_mode(CullMode p_mode) {
|
||||||
if (cull_mode == p_mode) {
|
if (cull_mode == p_mode) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -2410,7 +2484,8 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) {
|
||||||
p_flag == FLAG_UV1_USE_TRIPLANAR ||
|
p_flag == FLAG_UV1_USE_TRIPLANAR ||
|
||||||
p_flag == FLAG_UV2_USE_TRIPLANAR ||
|
p_flag == FLAG_UV2_USE_TRIPLANAR ||
|
||||||
p_flag == FLAG_USE_Z_CLIP_SCALE ||
|
p_flag == FLAG_USE_Z_CLIP_SCALE ||
|
||||||
p_flag == FLAG_USE_FOV_OVERRIDE) {
|
p_flag == FLAG_USE_FOV_OVERRIDE ||
|
||||||
|
p_flag == FLAG_DISABLE_DEPTH_TEST) {
|
||||||
notify_property_list_changed();
|
notify_property_list_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2565,6 +2640,26 @@ void BaseMaterial3D::_validate_property(PropertyInfo &p_property) const {
|
||||||
p_property.usage = PROPERTY_USAGE_NONE;
|
p_property.usage = PROPERTY_USAGE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_property.name == "depth_test" && flags[FLAG_DISABLE_DEPTH_TEST]) {
|
||||||
|
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_property.name == "stencil_reference" && stencil_mode == STENCIL_MODE_DISABLED) {
|
||||||
|
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p_property.name == "stencil_flags" || p_property.name == "stencil_compare") && stencil_mode != STENCIL_MODE_CUSTOM) {
|
||||||
|
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_property.name == "stencil_color" && stencil_mode != STENCIL_MODE_OUTLINE && stencil_mode != STENCIL_MODE_XRAY) {
|
||||||
|
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_property.name == "stencil_outline_thickness" && stencil_mode != STENCIL_MODE_OUTLINE) {
|
||||||
|
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (p_property.name == "subsurf_scatter_transmittance_color" || p_property.name == "subsurf_scatter_transmittance_texture")) {
|
if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (p_property.name == "subsurf_scatter_transmittance_color" || p_property.name == "subsurf_scatter_transmittance_texture")) {
|
||||||
p_property.usage = PROPERTY_USAGE_NONE;
|
p_property.usage = PROPERTY_USAGE_NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -3037,6 +3132,179 @@ RID BaseMaterial3D::get_rid() const {
|
||||||
return _get_material();
|
return _get_material();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseMaterial3D::_prepare_stencil_effect() {
|
||||||
|
const Ref<Material> current_next_pass = get_next_pass();
|
||||||
|
|
||||||
|
if (stencil_mode == STENCIL_MODE_DISABLED || stencil_mode == STENCIL_MODE_CUSTOM) {
|
||||||
|
if (current_next_pass.is_valid() && current_next_pass->has_meta("_stencil_owned")) {
|
||||||
|
set_next_pass(current_next_pass->get_next_pass());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<BaseMaterial3D> stencil_next_pass;
|
||||||
|
|
||||||
|
if (current_next_pass.is_null() || !current_next_pass->has_meta("_stencil_owned")) {
|
||||||
|
stencil_next_pass = Ref<BaseMaterial3D>(memnew(StandardMaterial3D));
|
||||||
|
stencil_next_pass->set_meta("_stencil_owned", true);
|
||||||
|
stencil_next_pass->set_next_pass(current_next_pass);
|
||||||
|
set_next_pass(stencil_next_pass);
|
||||||
|
} else {
|
||||||
|
stencil_next_pass = current_next_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (stencil_mode) {
|
||||||
|
case STENCIL_MODE_DISABLED:
|
||||||
|
break;
|
||||||
|
case STENCIL_MODE_OUTLINE:
|
||||||
|
set_stencil_flags(STENCIL_FLAG_WRITE);
|
||||||
|
set_stencil_compare(STENCIL_COMPARE_ALWAYS);
|
||||||
|
stencil_next_pass->set_render_priority(-1);
|
||||||
|
stencil_next_pass->set_shading_mode(SHADING_MODE_UNSHADED);
|
||||||
|
stencil_next_pass->set_transparency(TRANSPARENCY_ALPHA);
|
||||||
|
stencil_next_pass->set_flag(FLAG_DISABLE_DEPTH_TEST, false);
|
||||||
|
stencil_next_pass->set_grow_enabled(true);
|
||||||
|
stencil_next_pass->set_grow(stencil_effect_outline_thickness);
|
||||||
|
stencil_next_pass->set_albedo(stencil_effect_color);
|
||||||
|
stencil_next_pass->set_stencil_mode(STENCIL_MODE_CUSTOM);
|
||||||
|
stencil_next_pass->set_stencil_flags(STENCIL_FLAG_READ | STENCIL_FLAG_WRITE);
|
||||||
|
stencil_next_pass->set_stencil_compare(STENCIL_COMPARE_NOT_EQUAL);
|
||||||
|
stencil_next_pass->set_stencil_reference(stencil_reference);
|
||||||
|
break;
|
||||||
|
case STENCIL_MODE_XRAY:
|
||||||
|
set_stencil_flags(STENCIL_FLAG_WRITE);
|
||||||
|
set_stencil_compare(STENCIL_COMPARE_ALWAYS);
|
||||||
|
stencil_next_pass->set_render_priority(-1);
|
||||||
|
stencil_next_pass->set_shading_mode(SHADING_MODE_UNSHADED);
|
||||||
|
stencil_next_pass->set_transparency(TRANSPARENCY_ALPHA);
|
||||||
|
stencil_next_pass->set_flag(FLAG_DISABLE_DEPTH_TEST, true);
|
||||||
|
stencil_next_pass->set_grow_enabled(false);
|
||||||
|
stencil_next_pass->set_grow(0);
|
||||||
|
stencil_next_pass->set_albedo(stencil_effect_color);
|
||||||
|
stencil_next_pass->set_stencil_mode(STENCIL_MODE_CUSTOM);
|
||||||
|
stencil_next_pass->set_stencil_flags(STENCIL_FLAG_READ | STENCIL_FLAG_WRITE);
|
||||||
|
stencil_next_pass->set_stencil_compare(STENCIL_COMPARE_NOT_EQUAL);
|
||||||
|
stencil_next_pass->set_stencil_reference(stencil_reference);
|
||||||
|
break;
|
||||||
|
case STENCIL_MODE_CUSTOM:
|
||||||
|
break;
|
||||||
|
case STENCIL_MODE_MAX:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<BaseMaterial3D> BaseMaterial3D::_get_stencil_next_pass() const {
|
||||||
|
const Ref<Material> current_next_pass = get_next_pass();
|
||||||
|
Ref<BaseMaterial3D> stencil_next_pass;
|
||||||
|
|
||||||
|
if (current_next_pass.is_valid() && current_next_pass->has_meta("_stencil_owned")) {
|
||||||
|
stencil_next_pass = current_next_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stencil_next_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMaterial3D::set_stencil_mode(StencilMode p_stencil_mode) {
|
||||||
|
if (stencil_mode == p_stencil_mode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stencil_mode = p_stencil_mode;
|
||||||
|
_prepare_stencil_effect();
|
||||||
|
_queue_shader_change();
|
||||||
|
notify_property_list_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseMaterial3D::StencilMode BaseMaterial3D::get_stencil_mode() const {
|
||||||
|
return stencil_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMaterial3D::set_stencil_flags(int p_stencil_flags) {
|
||||||
|
if (stencil_flags == p_stencil_flags) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p_stencil_flags & STENCIL_FLAG_READ) && (stencil_flags & (STENCIL_FLAG_WRITE | STENCIL_FLAG_WRITE_DEPTH_FAIL))) {
|
||||||
|
p_stencil_flags = p_stencil_flags & STENCIL_FLAG_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p_stencil_flags & (STENCIL_FLAG_WRITE | STENCIL_FLAG_WRITE_DEPTH_FAIL)) && (stencil_flags & STENCIL_FLAG_READ)) {
|
||||||
|
p_stencil_flags = p_stencil_flags & (STENCIL_FLAG_WRITE | STENCIL_FLAG_WRITE_DEPTH_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
stencil_flags = p_stencil_flags;
|
||||||
|
_queue_shader_change();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseMaterial3D::get_stencil_flags() const {
|
||||||
|
return stencil_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMaterial3D::set_stencil_compare(BaseMaterial3D::StencilCompare p_op) {
|
||||||
|
if (stencil_compare == p_op) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stencil_compare = p_op;
|
||||||
|
_queue_shader_change();
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseMaterial3D::StencilCompare BaseMaterial3D::get_stencil_compare() const {
|
||||||
|
return stencil_compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMaterial3D::set_stencil_reference(int p_reference) {
|
||||||
|
if (stencil_reference == p_reference) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stencil_reference = p_reference;
|
||||||
|
_queue_shader_change();
|
||||||
|
|
||||||
|
Ref<BaseMaterial3D> stencil_next_pass = _get_stencil_next_pass();
|
||||||
|
if (stencil_next_pass.is_valid()) {
|
||||||
|
stencil_next_pass->set_stencil_reference(p_reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseMaterial3D::get_stencil_reference() const {
|
||||||
|
return stencil_reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMaterial3D::set_stencil_effect_color(const Color &p_color) {
|
||||||
|
if (stencil_effect_color == p_color) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stencil_effect_color = p_color;
|
||||||
|
|
||||||
|
Ref<BaseMaterial3D> stencil_next_pass = _get_stencil_next_pass();
|
||||||
|
if (stencil_next_pass.is_valid()) {
|
||||||
|
stencil_next_pass->set_albedo(p_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color BaseMaterial3D::get_stencil_effect_color() const {
|
||||||
|
return stencil_effect_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMaterial3D::set_stencil_effect_outline_thickness(float p_outline_thickness) {
|
||||||
|
if (stencil_effect_outline_thickness == p_outline_thickness) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stencil_effect_outline_thickness = p_outline_thickness;
|
||||||
|
|
||||||
|
Ref<BaseMaterial3D> stencil_next_pass = _get_stencil_next_pass();
|
||||||
|
if (stencil_next_pass.is_valid()) {
|
||||||
|
stencil_next_pass->set_grow(p_outline_thickness);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float BaseMaterial3D::get_stencil_effect_outline_thickness() const {
|
||||||
|
return stencil_effect_outline_thickness;
|
||||||
|
}
|
||||||
|
|
||||||
RID BaseMaterial3D::get_shader_rid() const {
|
RID BaseMaterial3D::get_shader_rid() const {
|
||||||
const_cast<BaseMaterial3D *>(this)->_update_shader();
|
const_cast<BaseMaterial3D *>(this)->_update_shader();
|
||||||
return shader_rid;
|
return shader_rid;
|
||||||
|
|
@ -3133,6 +3401,9 @@ void BaseMaterial3D::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &BaseMaterial3D::set_depth_draw_mode);
|
ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &BaseMaterial3D::set_depth_draw_mode);
|
||||||
ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &BaseMaterial3D::get_depth_draw_mode);
|
ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &BaseMaterial3D::get_depth_draw_mode);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_depth_test", "depth_test"), &BaseMaterial3D::set_depth_test);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_depth_test"), &BaseMaterial3D::get_depth_test);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &BaseMaterial3D::set_cull_mode);
|
ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &BaseMaterial3D::set_cull_mode);
|
||||||
ClassDB::bind_method(D_METHOD("get_cull_mode"), &BaseMaterial3D::get_cull_mode);
|
ClassDB::bind_method(D_METHOD("get_cull_mode"), &BaseMaterial3D::get_cull_mode);
|
||||||
|
|
||||||
|
|
@ -3259,6 +3530,24 @@ void BaseMaterial3D::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_fov_override", "scale"), &BaseMaterial3D::set_fov_override);
|
ClassDB::bind_method(D_METHOD("set_fov_override", "scale"), &BaseMaterial3D::set_fov_override);
|
||||||
ClassDB::bind_method(D_METHOD("get_fov_override"), &BaseMaterial3D::get_fov_override);
|
ClassDB::bind_method(D_METHOD("get_fov_override"), &BaseMaterial3D::get_fov_override);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_stencil_mode", "stencil_mode"), &BaseMaterial3D::set_stencil_mode);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_stencil_mode"), &BaseMaterial3D::get_stencil_mode);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_stencil_flags", "stencil_flags"), &BaseMaterial3D::set_stencil_flags);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_stencil_flags"), &BaseMaterial3D::get_stencil_flags);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_stencil_compare", "stencil_compare"), &BaseMaterial3D::set_stencil_compare);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_stencil_compare"), &BaseMaterial3D::get_stencil_compare);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_stencil_reference", "stencil_reference"), &BaseMaterial3D::set_stencil_reference);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_stencil_reference"), &BaseMaterial3D::get_stencil_reference);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_stencil_effect_color", "stencil_color"), &BaseMaterial3D::set_stencil_effect_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_stencil_effect_color"), &BaseMaterial3D::get_stencil_effect_color);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_stencil_effect_outline_thickness", "stencil_outline_thickness"), &BaseMaterial3D::set_stencil_effect_outline_thickness);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_stencil_effect_outline_thickness"), &BaseMaterial3D::get_stencil_effect_outline_thickness);
|
||||||
|
|
||||||
ADD_GROUP("Transparency", "");
|
ADD_GROUP("Transparency", "");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth Pre-Pass"), "set_transparency", "get_transparency");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth Pre-Pass"), "set_transparency", "get_transparency");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
|
||||||
|
|
@ -3269,6 +3558,7 @@ void BaseMaterial3D::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_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");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never"), "set_depth_draw_mode", "get_depth_draw_mode");
|
||||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST);
|
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST);
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_test", PROPERTY_HINT_ENUM, "Default,Inverted"), "set_depth_test", "get_depth_test");
|
||||||
|
|
||||||
ADD_GROUP("Shading", "");
|
ADD_GROUP("Shading", "");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,Per-Pixel,Per-Vertex"), "set_shading_mode", "get_shading_mode");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,Per-Pixel,Per-Vertex"), "set_shading_mode", "get_shading_mode");
|
||||||
|
|
@ -3445,6 +3735,15 @@ void BaseMaterial3D::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:m"), "set_distance_fade_min_distance", "get_distance_fade_min_distance");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:m"), "set_distance_fade_min_distance", "get_distance_fade_min_distance");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:m"), "set_distance_fade_max_distance", "get_distance_fade_max_distance");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:m"), "set_distance_fade_max_distance", "get_distance_fade_max_distance");
|
||||||
|
|
||||||
|
ADD_GROUP("Stencil", "stencil_");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "stencil_mode", PROPERTY_HINT_ENUM, "Disabled,Outline,X-Ray,Custom"), "set_stencil_mode", "get_stencil_mode");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "stencil_flags", PROPERTY_HINT_FLAGS, "Read,Write,Write Depth Fail"), "set_stencil_flags", "get_stencil_flags");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "stencil_compare", PROPERTY_HINT_ENUM, "Always,Less,Equal,Less Or Equal,Greater,Not Equal,Greater Or Equal"), "set_stencil_compare", "get_stencil_compare");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "stencil_reference", PROPERTY_HINT_RANGE, "0,255,1"), "set_stencil_reference", "get_stencil_reference");
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "stencil_color", PROPERTY_HINT_NONE), "set_stencil_effect_color", "get_stencil_effect_color");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stencil_outline_thickness", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_stencil_effect_outline_thickness", "get_stencil_effect_outline_thickness");
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(TEXTURE_ALBEDO);
|
BIND_ENUM_CONSTANT(TEXTURE_ALBEDO);
|
||||||
BIND_ENUM_CONSTANT(TEXTURE_METALLIC);
|
BIND_ENUM_CONSTANT(TEXTURE_METALLIC);
|
||||||
BIND_ENUM_CONSTANT(TEXTURE_ROUGHNESS);
|
BIND_ENUM_CONSTANT(TEXTURE_ROUGHNESS);
|
||||||
|
|
@ -3518,6 +3817,9 @@ void BaseMaterial3D::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(DEPTH_DRAW_ALWAYS);
|
BIND_ENUM_CONSTANT(DEPTH_DRAW_ALWAYS);
|
||||||
BIND_ENUM_CONSTANT(DEPTH_DRAW_DISABLED);
|
BIND_ENUM_CONSTANT(DEPTH_DRAW_DISABLED);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(DEPTH_TEST_DEFAULT);
|
||||||
|
BIND_ENUM_CONSTANT(DEPTH_TEST_INVERTED);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(CULL_BACK);
|
BIND_ENUM_CONSTANT(CULL_BACK);
|
||||||
BIND_ENUM_CONSTANT(CULL_FRONT);
|
BIND_ENUM_CONSTANT(CULL_FRONT);
|
||||||
BIND_ENUM_CONSTANT(CULL_DISABLED);
|
BIND_ENUM_CONSTANT(CULL_DISABLED);
|
||||||
|
|
@ -3576,6 +3878,23 @@ void BaseMaterial3D::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(DISTANCE_FADE_PIXEL_ALPHA);
|
BIND_ENUM_CONSTANT(DISTANCE_FADE_PIXEL_ALPHA);
|
||||||
BIND_ENUM_CONSTANT(DISTANCE_FADE_PIXEL_DITHER);
|
BIND_ENUM_CONSTANT(DISTANCE_FADE_PIXEL_DITHER);
|
||||||
BIND_ENUM_CONSTANT(DISTANCE_FADE_OBJECT_DITHER);
|
BIND_ENUM_CONSTANT(DISTANCE_FADE_OBJECT_DITHER);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_MODE_DISABLED);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_MODE_OUTLINE);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_MODE_XRAY);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_MODE_CUSTOM);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_FLAG_READ);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_FLAG_WRITE);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_FLAG_WRITE_DEPTH_FAIL);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_COMPARE_ALWAYS);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_COMPARE_LESS);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_COMPARE_EQUAL);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_COMPARE_LESS_OR_EQUAL);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_COMPARE_GREATER);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_COMPARE_NOT_EQUAL);
|
||||||
|
BIND_ENUM_CONSTANT(STENCIL_COMPARE_GREATER_OR_EQUAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseMaterial3D::BaseMaterial3D(bool p_orm) :
|
BaseMaterial3D::BaseMaterial3D(bool p_orm) :
|
||||||
|
|
@ -3644,6 +3963,8 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
|
||||||
set_z_clip_scale(1.0);
|
set_z_clip_scale(1.0);
|
||||||
set_fov_override(75.0);
|
set_fov_override(75.0);
|
||||||
|
|
||||||
|
set_stencil_mode(STENCIL_MODE_DISABLED);
|
||||||
|
|
||||||
flags[FLAG_ALBEDO_TEXTURE_MSDF] = false;
|
flags[FLAG_ALBEDO_TEXTURE_MSDF] = false;
|
||||||
flags[FLAG_USE_TEXTURE_REPEAT] = true;
|
flags[FLAG_USE_TEXTURE_REPEAT] = true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,12 @@ public:
|
||||||
DEPTH_DRAW_MAX
|
DEPTH_DRAW_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DepthTest {
|
||||||
|
DEPTH_TEST_DEFAULT,
|
||||||
|
DEPTH_TEST_INVERTED,
|
||||||
|
DEPTH_TEST_MAX
|
||||||
|
};
|
||||||
|
|
||||||
enum CullMode {
|
enum CullMode {
|
||||||
CULL_BACK,
|
CULL_BACK,
|
||||||
CULL_FRONT,
|
CULL_FRONT,
|
||||||
|
|
@ -320,6 +326,33 @@ public:
|
||||||
DISTANCE_FADE_MAX
|
DISTANCE_FADE_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StencilMode {
|
||||||
|
STENCIL_MODE_DISABLED,
|
||||||
|
STENCIL_MODE_OUTLINE,
|
||||||
|
STENCIL_MODE_XRAY,
|
||||||
|
STENCIL_MODE_CUSTOM,
|
||||||
|
STENCIL_MODE_MAX // Not an actual mode, just the amount of modes.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StencilFlags {
|
||||||
|
STENCIL_FLAG_READ = 1,
|
||||||
|
STENCIL_FLAG_WRITE = 2,
|
||||||
|
STENCIL_FLAG_WRITE_DEPTH_FAIL = 4,
|
||||||
|
|
||||||
|
STENCIL_FLAG_NUM_BITS = 3 // Not an actual mode, just the amount of bits.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StencilCompare {
|
||||||
|
STENCIL_COMPARE_ALWAYS,
|
||||||
|
STENCIL_COMPARE_LESS,
|
||||||
|
STENCIL_COMPARE_EQUAL,
|
||||||
|
STENCIL_COMPARE_LESS_OR_EQUAL,
|
||||||
|
STENCIL_COMPARE_GREATER,
|
||||||
|
STENCIL_COMPARE_NOT_EQUAL,
|
||||||
|
STENCIL_COMPARE_GREATER_OR_EQUAL,
|
||||||
|
STENCIL_COMPARE_MAX // Not an actual operator, just the amount of operators.
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct MaterialKey {
|
struct MaterialKey {
|
||||||
// enum values
|
// enum values
|
||||||
|
|
@ -330,6 +363,7 @@ private:
|
||||||
uint64_t shading_mode : get_num_bits(SHADING_MODE_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 blend_mode : get_num_bits(BLEND_MODE_MAX - 1);
|
||||||
uint64_t depth_draw_mode : get_num_bits(DEPTH_DRAW_MAX - 1);
|
uint64_t depth_draw_mode : get_num_bits(DEPTH_DRAW_MAX - 1);
|
||||||
|
uint64_t depth_test : get_num_bits(DEPTH_TEST_MAX - 1);
|
||||||
uint64_t cull_mode : get_num_bits(CULL_MAX - 1);
|
uint64_t cull_mode : get_num_bits(CULL_MAX - 1);
|
||||||
uint64_t diffuse_mode : get_num_bits(DIFFUSE_MAX - 1);
|
uint64_t diffuse_mode : get_num_bits(DIFFUSE_MAX - 1);
|
||||||
uint64_t specular_mode : get_num_bits(SPECULAR_MAX - 1);
|
uint64_t specular_mode : get_num_bits(SPECULAR_MAX - 1);
|
||||||
|
|
@ -338,6 +372,13 @@ private:
|
||||||
uint64_t roughness_channel : get_num_bits(TEXTURE_CHANNEL_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 emission_op : get_num_bits(EMISSION_OP_MAX - 1);
|
||||||
uint64_t distance_fade : get_num_bits(DISTANCE_FADE_MAX - 1);
|
uint64_t distance_fade : get_num_bits(DISTANCE_FADE_MAX - 1);
|
||||||
|
|
||||||
|
// stencil
|
||||||
|
uint64_t stencil_mode : get_num_bits(STENCIL_MODE_MAX - 1);
|
||||||
|
uint64_t stencil_flags : STENCIL_FLAG_NUM_BITS;
|
||||||
|
uint64_t stencil_compare : get_num_bits(STENCIL_COMPARE_MAX - 1);
|
||||||
|
uint64_t stencil_reference : 8;
|
||||||
|
|
||||||
// booleans
|
// booleans
|
||||||
uint64_t invalid_key : 1;
|
uint64_t invalid_key : 1;
|
||||||
uint64_t deep_parallax : 1;
|
uint64_t deep_parallax : 1;
|
||||||
|
|
@ -381,6 +422,7 @@ private:
|
||||||
mk.detail_uv = detail_uv;
|
mk.detail_uv = detail_uv;
|
||||||
mk.blend_mode = blend_mode;
|
mk.blend_mode = blend_mode;
|
||||||
mk.depth_draw_mode = depth_draw_mode;
|
mk.depth_draw_mode = depth_draw_mode;
|
||||||
|
mk.depth_test = depth_test;
|
||||||
mk.cull_mode = cull_mode;
|
mk.cull_mode = cull_mode;
|
||||||
mk.texture_filter = texture_filter;
|
mk.texture_filter = texture_filter;
|
||||||
mk.transparency = transparency;
|
mk.transparency = transparency;
|
||||||
|
|
@ -398,6 +440,11 @@ private:
|
||||||
mk.alpha_antialiasing_mode = alpha_antialiasing_mode;
|
mk.alpha_antialiasing_mode = alpha_antialiasing_mode;
|
||||||
mk.orm = orm;
|
mk.orm = orm;
|
||||||
|
|
||||||
|
mk.stencil_mode = stencil_mode;
|
||||||
|
mk.stencil_flags = stencil_flags;
|
||||||
|
mk.stencil_compare = stencil_compare;
|
||||||
|
mk.stencil_reference = stencil_reference;
|
||||||
|
|
||||||
for (int i = 0; i < FEATURE_MAX; i++) {
|
for (int i = 0; i < FEATURE_MAX; i++) {
|
||||||
if (features[i]) {
|
if (features[i]) {
|
||||||
mk.feature_mask |= ((uint64_t)1 << i);
|
mk.feature_mask |= ((uint64_t)1 << i);
|
||||||
|
|
@ -553,6 +600,7 @@ private:
|
||||||
BlendMode blend_mode = BLEND_MODE_MIX;
|
BlendMode blend_mode = BLEND_MODE_MIX;
|
||||||
BlendMode detail_blend_mode = BLEND_MODE_MIX;
|
BlendMode detail_blend_mode = BLEND_MODE_MIX;
|
||||||
DepthDrawMode depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY;
|
DepthDrawMode depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY;
|
||||||
|
DepthTest depth_test = DEPTH_TEST_DEFAULT;
|
||||||
CullMode cull_mode = CULL_BACK;
|
CullMode cull_mode = CULL_BACK;
|
||||||
bool flags[FLAG_MAX] = {};
|
bool flags[FLAG_MAX] = {};
|
||||||
SpecularMode specular_mode = SPECULAR_SCHLICK_GGX;
|
SpecularMode specular_mode = SPECULAR_SCHLICK_GGX;
|
||||||
|
|
@ -570,10 +618,21 @@ private:
|
||||||
float z_clip_scale = 1.0;
|
float z_clip_scale = 1.0;
|
||||||
float fov_override = 75.0;
|
float fov_override = 75.0;
|
||||||
|
|
||||||
|
StencilMode stencil_mode = STENCIL_MODE_DISABLED;
|
||||||
|
int stencil_flags = 0;
|
||||||
|
StencilCompare stencil_compare = STENCIL_COMPARE_ALWAYS;
|
||||||
|
int stencil_reference = 1;
|
||||||
|
|
||||||
|
Color stencil_effect_color;
|
||||||
|
float stencil_effect_outline_thickness = 0.01f;
|
||||||
|
|
||||||
bool features[FEATURE_MAX] = {};
|
bool features[FEATURE_MAX] = {};
|
||||||
|
|
||||||
Ref<Texture2D> textures[TEXTURE_MAX];
|
Ref<Texture2D> textures[TEXTURE_MAX];
|
||||||
|
|
||||||
|
void _prepare_stencil_effect();
|
||||||
|
Ref<BaseMaterial3D> _get_stencil_next_pass() const;
|
||||||
|
|
||||||
static HashMap<uint64_t, Ref<StandardMaterial3D>> materials_for_2d; //used by Sprite3D, Label3D and other stuff
|
static HashMap<uint64_t, Ref<StandardMaterial3D>> materials_for_2d; //used by Sprite3D, Label3D and other stuff
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -688,6 +747,9 @@ public:
|
||||||
void set_depth_draw_mode(DepthDrawMode p_mode);
|
void set_depth_draw_mode(DepthDrawMode p_mode);
|
||||||
DepthDrawMode get_depth_draw_mode() const;
|
DepthDrawMode get_depth_draw_mode() const;
|
||||||
|
|
||||||
|
void set_depth_test(DepthTest p_func);
|
||||||
|
DepthTest get_depth_test() const;
|
||||||
|
|
||||||
void set_cull_mode(CullMode p_mode);
|
void set_cull_mode(CullMode p_mode);
|
||||||
CullMode get_cull_mode() const;
|
CullMode get_cull_mode() const;
|
||||||
|
|
||||||
|
|
@ -778,6 +840,24 @@ public:
|
||||||
void set_emission_operator(EmissionOperator p_op);
|
void set_emission_operator(EmissionOperator p_op);
|
||||||
EmissionOperator get_emission_operator() const;
|
EmissionOperator get_emission_operator() const;
|
||||||
|
|
||||||
|
void set_stencil_mode(StencilMode p_stencil_mode);
|
||||||
|
StencilMode get_stencil_mode() const;
|
||||||
|
|
||||||
|
void set_stencil_flags(int p_stencil_flags);
|
||||||
|
int get_stencil_flags() const;
|
||||||
|
|
||||||
|
void set_stencil_compare(StencilCompare p_op);
|
||||||
|
StencilCompare get_stencil_compare() const;
|
||||||
|
|
||||||
|
void set_stencil_reference(int p_reference);
|
||||||
|
int get_stencil_reference() const;
|
||||||
|
|
||||||
|
void set_stencil_effect_color(const Color &p_color);
|
||||||
|
Color get_stencil_effect_color() const;
|
||||||
|
|
||||||
|
void set_stencil_effect_outline_thickness(float p_outline_thickness);
|
||||||
|
float get_stencil_effect_outline_thickness() const;
|
||||||
|
|
||||||
void set_metallic_texture_channel(TextureChannel p_channel);
|
void set_metallic_texture_channel(TextureChannel p_channel);
|
||||||
TextureChannel get_metallic_texture_channel() const;
|
TextureChannel get_metallic_texture_channel() const;
|
||||||
void set_roughness_texture_channel(TextureChannel p_channel);
|
void set_roughness_texture_channel(TextureChannel p_channel);
|
||||||
|
|
@ -816,6 +896,7 @@ VARIANT_ENUM_CAST(BaseMaterial3D::DetailUV)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::Feature)
|
VARIANT_ENUM_CAST(BaseMaterial3D::Feature)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::BlendMode)
|
VARIANT_ENUM_CAST(BaseMaterial3D::BlendMode)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::DepthDrawMode)
|
VARIANT_ENUM_CAST(BaseMaterial3D::DepthDrawMode)
|
||||||
|
VARIANT_ENUM_CAST(BaseMaterial3D::DepthTest)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::CullMode)
|
VARIANT_ENUM_CAST(BaseMaterial3D::CullMode)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::Flags)
|
VARIANT_ENUM_CAST(BaseMaterial3D::Flags)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::DiffuseMode)
|
VARIANT_ENUM_CAST(BaseMaterial3D::DiffuseMode)
|
||||||
|
|
@ -824,6 +905,9 @@ VARIANT_ENUM_CAST(BaseMaterial3D::BillboardMode)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::TextureChannel)
|
VARIANT_ENUM_CAST(BaseMaterial3D::TextureChannel)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::EmissionOperator)
|
VARIANT_ENUM_CAST(BaseMaterial3D::EmissionOperator)
|
||||||
VARIANT_ENUM_CAST(BaseMaterial3D::DistanceFadeMode)
|
VARIANT_ENUM_CAST(BaseMaterial3D::DistanceFadeMode)
|
||||||
|
VARIANT_ENUM_CAST(BaseMaterial3D::StencilMode)
|
||||||
|
VARIANT_ENUM_CAST(BaseMaterial3D::StencilFlags)
|
||||||
|
VARIANT_ENUM_CAST(BaseMaterial3D::StencilCompare)
|
||||||
|
|
||||||
class StandardMaterial3D : public BaseMaterial3D {
|
class StandardMaterial3D : public BaseMaterial3D {
|
||||||
GDCLASS(StandardMaterial3D, BaseMaterial3D)
|
GDCLASS(StandardMaterial3D, BaseMaterial3D)
|
||||||
|
|
|
||||||
|
|
@ -1715,6 +1715,41 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
}
|
}
|
||||||
_queue_update();
|
_queue_update();
|
||||||
return true;
|
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);
|
||||||
|
if (flag == "read") {
|
||||||
|
stencil_flags.erase("write");
|
||||||
|
stencil_flags.erase("write_depth_fail");
|
||||||
|
} else if (flag == "write" || flag == "write_depth_fail") {
|
||||||
|
stencil_flags.erase("read");
|
||||||
|
}
|
||||||
|
} 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/")) {
|
} else if (prop_name.begins_with("varyings/")) {
|
||||||
String var_name = prop_name.get_slicec('/', 1);
|
String var_name = prop_name.get_slicec('/', 1);
|
||||||
Varying value = Varying();
|
Varying value = Varying();
|
||||||
|
|
@ -1798,6 +1833,24 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
r_ret = 0;
|
r_ret = 0;
|
||||||
}
|
}
|
||||||
return true;
|
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/")) {
|
} else if (prop_name.begins_with("varyings/")) {
|
||||||
String var_name = prop_name.get_slicec('/', 1);
|
String var_name = prop_name.get_slicec('/', 1);
|
||||||
if (varyings.has(var_name)) {
|
if (varyings.has(var_name)) {
|
||||||
|
|
@ -1886,6 +1939,29 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
for (int i = 0; i < rmodes.size(); i++) {
|
for (int i = 0; i < rmodes.size(); i++) {
|
||||||
const ShaderLanguage::ModeInfo &info = rmodes[i];
|
const ShaderLanguage::ModeInfo &info = rmodes[i];
|
||||||
|
|
||||||
|
// Special handling for depth_test.
|
||||||
|
if (info.name == "depth_test") {
|
||||||
|
toggles.insert("depth_test_disabled");
|
||||||
|
|
||||||
|
const String begin = String(info.name);
|
||||||
|
|
||||||
|
for (int j = 0; j < info.options.size(); j++) {
|
||||||
|
if (info.options[j] == "disabled") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const String option = String(info.options[j]).capitalize();
|
||||||
|
|
||||||
|
if (!blend_mode_enums.has(begin)) {
|
||||||
|
blend_mode_enums[begin] = vformat("%s:%s", option, j);
|
||||||
|
} else {
|
||||||
|
blend_mode_enums[begin] += "," + vformat("%s:%s", option, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!info.options.is_empty()) {
|
if (!info.options.is_empty()) {
|
||||||
const String begin = String(info.name);
|
const String begin = String(info.name);
|
||||||
|
|
||||||
|
|
@ -1911,6 +1987,45 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("flags"), E)));
|
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 (const ShaderLanguage::ModeInfo &info : smodes) {
|
||||||
|
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) {
|
for (const KeyValue<String, Varying> &E : varyings) {
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", "varyings", E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", "varyings", E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||||
}
|
}
|
||||||
|
|
@ -2550,6 +2665,23 @@ void VisualShader::_update_shader() const {
|
||||||
const ShaderLanguage::ModeInfo &info = rmodes[i];
|
const ShaderLanguage::ModeInfo &info = rmodes[i];
|
||||||
const String temp = String(info.name);
|
const String temp = String(info.name);
|
||||||
|
|
||||||
|
// Special handling for depth_test.
|
||||||
|
if (temp == "depth_test") {
|
||||||
|
if (flags.has("depth_test_disabled")) {
|
||||||
|
flag_names.push_back("depth_test_disabled");
|
||||||
|
} else {
|
||||||
|
if (!render_mode.is_empty()) {
|
||||||
|
render_mode += ", ";
|
||||||
|
}
|
||||||
|
if (modes.has(temp) && modes[temp] < info.options.size()) {
|
||||||
|
render_mode += temp + "_" + info.options[modes[temp]];
|
||||||
|
} else {
|
||||||
|
render_mode += temp + "_" + info.options[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!info.options.is_empty()) {
|
if (!info.options.is_empty()) {
|
||||||
if (!render_mode.is_empty()) {
|
if (!render_mode.is_empty()) {
|
||||||
render_mode += ", ";
|
render_mode += ", ";
|
||||||
|
|
@ -2581,6 +2713,46 @@ void VisualShader::_update_shader() const {
|
||||||
global_code += "render_mode " + render_mode + ";\n\n";
|
global_code += "render_mode " + render_mode + ";\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Vector<ShaderLanguage::ModeInfo> &smodes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(shader_mode));
|
||||||
|
|
||||||
|
if (stencil_enabled && smodes.size() > 0 && (stencil_flags.has("read") || stencil_flags.has("write") || stencil_flags.has("write_depth_fail"))) {
|
||||||
|
String stencil_mode;
|
||||||
|
|
||||||
|
Vector<String> flag_names;
|
||||||
|
|
||||||
|
// Add enum modes first.
|
||||||
|
for (const ShaderLanguage::ModeInfo &info : smodes) {
|
||||||
|
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 (const String &flag_name : flag_names) {
|
||||||
|
if (!stencil_mode.is_empty()) {
|
||||||
|
stencil_mode += ", ";
|
||||||
|
}
|
||||||
|
stencil_mode += flag_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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" };
|
static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };
|
||||||
|
|
||||||
String global_expressions;
|
String global_expressions;
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,11 @@ private:
|
||||||
HashMap<String, int> modes;
|
HashMap<String, int> modes;
|
||||||
HashSet<StringName> flags;
|
HashSet<StringName> flags;
|
||||||
|
|
||||||
|
bool stencil_enabled = false;
|
||||||
|
HashMap<String, int> stencil_modes;
|
||||||
|
HashSet<StringName> stencil_flags;
|
||||||
|
int stencil_reference = 1;
|
||||||
|
|
||||||
HashMap<String, Varying> varyings;
|
HashMap<String, Varying> varyings;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
HashMap<String, Variant> preview_params;
|
HashMap<String, Variant> preview_params;
|
||||||
|
|
|
||||||
|
|
@ -881,6 +881,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
|
||||||
scene_state.used_normal_texture = false;
|
scene_state.used_normal_texture = false;
|
||||||
scene_state.used_depth_texture = false;
|
scene_state.used_depth_texture = false;
|
||||||
scene_state.used_lightmap = false;
|
scene_state.used_lightmap = false;
|
||||||
|
scene_state.used_opaque_stencil = false;
|
||||||
}
|
}
|
||||||
uint32_t lightmap_captures_used = 0;
|
uint32_t lightmap_captures_used = 0;
|
||||||
|
|
||||||
|
|
@ -1126,6 +1127,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
|
||||||
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
|
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
|
||||||
scene_state.used_depth_texture = true;
|
scene_state.used_depth_texture = true;
|
||||||
}
|
}
|
||||||
|
if ((surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_STENCIL) && !force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) {
|
||||||
|
scene_state.used_opaque_stencil = true;
|
||||||
|
}
|
||||||
} else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) {
|
} else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) {
|
||||||
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) {
|
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) {
|
||||||
rl->add_element(surf);
|
rl->add_element(surf);
|
||||||
|
|
@ -2041,7 +2045,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||||
|
|
||||||
bool debug_voxelgis = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION;
|
bool debug_voxelgis = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION;
|
||||||
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
|
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
|
||||||
bool depth_pre_pass = bool(GLOBAL_GET_CACHED(bool, "rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid();
|
bool force_depth_pre_pass = scene_state.used_opaque_stencil;
|
||||||
|
bool depth_pre_pass = (force_depth_pre_pass || bool(GLOBAL_GET_CACHED(bool, "rendering/driver/depth_prepass/enable"))) && depth_framebuffer.is_valid();
|
||||||
|
|
||||||
SceneShaderForwardClustered::ShaderSpecialization base_specialization = scene_shader.default_specialization;
|
SceneShaderForwardClustered::ShaderSpecialization base_specialization = scene_shader.default_specialization;
|
||||||
base_specialization.use_depth_fog = p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH;
|
base_specialization.use_depth_fog = p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH;
|
||||||
|
|
@ -3984,6 +3989,10 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
|
||||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS;
|
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_material->shader_data->stencil_enabled) {
|
||||||
|
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_STENCIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (p_material->shader_data->uses_alpha_pass()) {
|
if (p_material->shader_data->uses_alpha_pass()) {
|
||||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA;
|
flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA;
|
||||||
if (p_material->shader_data->uses_depth_in_alpha_pass()) {
|
if (p_material->shader_data->uses_depth_in_alpha_pass()) {
|
||||||
|
|
@ -4004,6 +4013,17 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
|
||||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_MOTION_VECTOR;
|
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_MOTION_VECTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_material->shader_data->stencil_enabled) {
|
||||||
|
if (p_material->shader_data->stencil_flags & SceneShaderForwardClustered::ShaderData::STENCIL_FLAG_READ) {
|
||||||
|
// Stencil materials which read from the stencil buffer must be in the alpha pass.
|
||||||
|
// This is critical to preserve compatibility once we'll have the compositor.
|
||||||
|
if (!(flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) {
|
||||||
|
String shader_path = p_material->shader_data->path.is_empty() ? "" : "(" + p_material->shader_data->path + ")";
|
||||||
|
ERR_PRINT_ED(vformat("Attempting to use a shader %s that reads stencil but is not in the alpha queue. Ensure the material uses alpha blending or has depth_draw disabled or depth_test disabled.", shader_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SceneShaderForwardClustered::MaterialData *material_shadow = nullptr;
|
SceneShaderForwardClustered::MaterialData *material_shadow = nullptr;
|
||||||
void *surface_shadow = nullptr;
|
void *surface_shadow = nullptr;
|
||||||
if (p_material->shader_data->uses_shared_shadow_material()) {
|
if (p_material->shader_data->uses_shared_shadow_material()) {
|
||||||
|
|
|
||||||
|
|
@ -408,6 +408,7 @@ private:
|
||||||
bool used_depth_texture = false;
|
bool used_depth_texture = false;
|
||||||
bool used_sss = false;
|
bool used_sss = false;
|
||||||
bool used_lightmap = false;
|
bool used_lightmap = false;
|
||||||
|
bool used_opaque_stencil = false;
|
||||||
|
|
||||||
struct ShadowPass {
|
struct ShadowPass {
|
||||||
uint32_t element_from;
|
uint32_t element_from;
|
||||||
|
|
@ -485,6 +486,7 @@ private:
|
||||||
FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768,
|
FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768,
|
||||||
FLAG_USES_PARTICLE_TRAILS = 65536,
|
FLAG_USES_PARTICLE_TRAILS = 65536,
|
||||||
FLAG_USES_MOTION_VECTOR = 131072,
|
FLAG_USES_MOTION_VECTOR = 131072,
|
||||||
|
FLAG_USES_STENCIL = 262144,
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||||
ShaderCompiler::GeneratedCode gen_code;
|
ShaderCompiler::GeneratedCode gen_code;
|
||||||
|
|
||||||
blend_mode = BLEND_MODE_MIX;
|
blend_mode = BLEND_MODE_MIX;
|
||||||
depth_testi = DEPTH_TEST_ENABLED;
|
depth_test_disabledi = 0;
|
||||||
|
depth_test_invertedi = 0;
|
||||||
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||||
int cull_modei = RS::CULL_MODE_BACK;
|
int cull_modei = RS::CULL_MODE_BACK;
|
||||||
|
|
||||||
|
|
@ -83,6 +84,12 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||||
|
|
||||||
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
||||||
|
|
||||||
|
int stencil_readi = 0;
|
||||||
|
int stencil_writei = 0;
|
||||||
|
int stencil_write_depth_faili = 0;
|
||||||
|
int stencil_comparei = STENCIL_COMPARE_ALWAYS;
|
||||||
|
int stencil_referencei = -1;
|
||||||
|
|
||||||
ShaderCompiler::IdentifierActions actions;
|
ShaderCompiler::IdentifierActions actions;
|
||||||
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
|
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
|
||||||
actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
|
actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
|
||||||
|
|
@ -101,7 +108,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||||
actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
|
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);
|
actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
|
||||||
|
|
||||||
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
|
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_test_disabledi, 1);
|
||||||
|
actions.render_mode_values["depth_test_inverted"] = Pair<int *, int>(&depth_test_invertedi, 1);
|
||||||
|
|
||||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_DISABLED);
|
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_DISABLED);
|
||||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_FRONT);
|
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_FRONT);
|
||||||
|
|
@ -143,6 +151,20 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||||
actions.write_flag_pointers["POSITION"] = &uses_position;
|
actions.write_flag_pointers["POSITION"] = &uses_position;
|
||||||
actions.write_flag_pointers["Z_CLIP_SCALE"] = &uses_z_clip_scale;
|
actions.write_flag_pointers["Z_CLIP_SCALE"] = &uses_z_clip_scale;
|
||||||
|
|
||||||
|
actions.stencil_mode_values["read"] = Pair<int *, int>(&stencil_readi, STENCIL_FLAG_READ);
|
||||||
|
actions.stencil_mode_values["write"] = Pair<int *, int>(&stencil_writei, STENCIL_FLAG_WRITE);
|
||||||
|
actions.stencil_mode_values["write_depth_fail"] = Pair<int *, int>(&stencil_write_depth_faili, STENCIL_FLAG_WRITE_DEPTH_FAIL);
|
||||||
|
|
||||||
|
actions.stencil_mode_values["compare_less"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_LESS);
|
||||||
|
actions.stencil_mode_values["compare_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_less_or_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_LESS_OR_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_greater"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_GREATER);
|
||||||
|
actions.stencil_mode_values["compare_not_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_NOT_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_greater_or_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_GREATER_OR_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_always"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_ALWAYS);
|
||||||
|
|
||||||
|
actions.stencil_reference = &stencil_referencei;
|
||||||
|
|
||||||
actions.uniforms = &uniforms;
|
actions.uniforms = &uniforms;
|
||||||
|
|
||||||
Error err = OK;
|
Error err = OK;
|
||||||
|
|
@ -164,7 +186,13 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||||
}
|
}
|
||||||
|
|
||||||
depth_draw = DepthDraw(depth_drawi);
|
depth_draw = DepthDraw(depth_drawi);
|
||||||
depth_test = DepthTest(depth_testi);
|
if (depth_test_disabledi) {
|
||||||
|
depth_test = DEPTH_TEST_DISABLED;
|
||||||
|
} else if (depth_test_invertedi) {
|
||||||
|
depth_test = DEPTH_TEST_ENABLED_INVERTED;
|
||||||
|
} else {
|
||||||
|
depth_test = DEPTH_TEST_ENABLED;
|
||||||
|
}
|
||||||
cull_mode = RS::CullMode(cull_modei);
|
cull_mode = RS::CullMode(cull_modei);
|
||||||
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
|
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
|
||||||
uses_screen_texture = gen_code.uses_screen_texture;
|
uses_screen_texture = gen_code.uses_screen_texture;
|
||||||
|
|
@ -177,6 +205,11 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||||
uses_tangent |= uses_normal_map;
|
uses_tangent |= uses_normal_map;
|
||||||
uses_tangent |= uses_bent_normal_map;
|
uses_tangent |= uses_bent_normal_map;
|
||||||
|
|
||||||
|
stencil_enabled = stencil_referencei != -1;
|
||||||
|
stencil_flags = stencil_readi | stencil_writei | stencil_write_depth_faili;
|
||||||
|
stencil_compare = StencilCompare(stencil_comparei);
|
||||||
|
stencil_reference = stencil_referencei;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
print_line("**compiling shader:");
|
print_line("**compiling shader:");
|
||||||
print_line("**defines:\n");
|
print_line("**defines:\n");
|
||||||
|
|
@ -219,7 +252,7 @@ bool SceneShaderForwardClustered::ShaderData::casts_shadows() const {
|
||||||
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
|
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
|
||||||
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
||||||
|
|
||||||
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
|
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test != DEPTH_TEST_ENABLED));
|
||||||
}
|
}
|
||||||
|
|
||||||
RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_source_code() const {
|
RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_source_code() const {
|
||||||
|
|
@ -318,9 +351,55 @@ void SceneShaderForwardClustered::ShaderData::_create_pipeline(PipelineKey p_pip
|
||||||
|
|
||||||
if (depth_test != DEPTH_TEST_DISABLED) {
|
if (depth_test != DEPTH_TEST_DISABLED) {
|
||||||
depth_stencil_state.enable_depth_test = true;
|
depth_stencil_state.enable_depth_test = true;
|
||||||
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
|
|
||||||
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
|
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
|
||||||
|
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
|
||||||
|
|
||||||
|
if (depth_test == DEPTH_TEST_ENABLED_INVERTED) {
|
||||||
|
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
depth_stencil_state.enable_stencil = stencil_enabled;
|
||||||
|
if (stencil_enabled) {
|
||||||
|
static const RD::CompareOperator stencil_compare_rd_table[STENCIL_COMPARE_MAX] = {
|
||||||
|
RD::COMPARE_OP_LESS,
|
||||||
|
RD::COMPARE_OP_EQUAL,
|
||||||
|
RD::COMPARE_OP_LESS_OR_EQUAL,
|
||||||
|
RD::COMPARE_OP_GREATER,
|
||||||
|
RD::COMPARE_OP_NOT_EQUAL,
|
||||||
|
RD::COMPARE_OP_GREATER_OR_EQUAL,
|
||||||
|
RD::COMPARE_OP_ALWAYS,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t stencil_mask = 255;
|
||||||
|
|
||||||
|
RD::PipelineDepthStencilState::StencilOperationState op;
|
||||||
|
op.fail = RD::STENCIL_OP_KEEP;
|
||||||
|
op.pass = RD::STENCIL_OP_KEEP;
|
||||||
|
op.depth_fail = RD::STENCIL_OP_KEEP;
|
||||||
|
op.compare = stencil_compare_rd_table[stencil_compare];
|
||||||
|
op.compare_mask = 0;
|
||||||
|
op.write_mask = 0;
|
||||||
|
op.reference = stencil_reference;
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_READ) {
|
||||||
|
op.compare_mask = stencil_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_WRITE) {
|
||||||
|
op.pass = RD::STENCIL_OP_REPLACE;
|
||||||
|
op.write_mask = stencil_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_WRITE_DEPTH_FAIL) {
|
||||||
|
op.depth_fail = RD::STENCIL_OP_REPLACE;
|
||||||
|
op.write_mask = stencil_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
depth_stencil_state.front_op = op;
|
||||||
|
depth_stencil_state.back_op = op;
|
||||||
|
}
|
||||||
|
|
||||||
bool depth_pre_pass_enabled = bool(GLOBAL_GET_CACHED(bool, "rendering/driver/depth_prepass/enable"));
|
bool depth_pre_pass_enabled = bool(GLOBAL_GET_CACHED(bool, "rendering/driver/depth_prepass/enable"));
|
||||||
|
|
||||||
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
|
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,8 @@ public:
|
||||||
|
|
||||||
enum DepthTest {
|
enum DepthTest {
|
||||||
DEPTH_TEST_DISABLED,
|
DEPTH_TEST_DISABLED,
|
||||||
DEPTH_TEST_ENABLED
|
DEPTH_TEST_ENABLED,
|
||||||
|
DEPTH_TEST_ENABLED_INVERTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CullVariant {
|
enum CullVariant {
|
||||||
|
|
@ -167,6 +168,23 @@ public:
|
||||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StencilFlags {
|
||||||
|
STENCIL_FLAG_READ = 1,
|
||||||
|
STENCIL_FLAG_WRITE = 2,
|
||||||
|
STENCIL_FLAG_WRITE_DEPTH_FAIL = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StencilCompare {
|
||||||
|
STENCIL_COMPARE_LESS,
|
||||||
|
STENCIL_COMPARE_EQUAL,
|
||||||
|
STENCIL_COMPARE_LESS_OR_EQUAL,
|
||||||
|
STENCIL_COMPARE_GREATER,
|
||||||
|
STENCIL_COMPARE_NOT_EQUAL,
|
||||||
|
STENCIL_COMPARE_GREATER_OR_EQUAL,
|
||||||
|
STENCIL_COMPARE_ALWAYS,
|
||||||
|
STENCIL_COMPARE_MAX // Not an actual operator, just the amount of operators.
|
||||||
|
};
|
||||||
|
|
||||||
struct PipelineKey {
|
struct PipelineKey {
|
||||||
RD::VertexFormatID vertex_format_id;
|
RD::VertexFormatID vertex_format_id;
|
||||||
RD::FramebufferFormatID framebuffer_format_id;
|
RD::FramebufferFormatID framebuffer_format_id;
|
||||||
|
|
@ -213,7 +231,8 @@ public:
|
||||||
DepthTest depth_test = DEPTH_TEST_ENABLED;
|
DepthTest depth_test = DEPTH_TEST_ENABLED;
|
||||||
|
|
||||||
int blend_mode = BLEND_MODE_MIX;
|
int blend_mode = BLEND_MODE_MIX;
|
||||||
int depth_testi = DEPTH_TEST_ENABLED;
|
int depth_test_disabledi = 0;
|
||||||
|
int depth_test_invertedi = 0;
|
||||||
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||||
|
|
||||||
bool uses_point_size = false;
|
bool uses_point_size = false;
|
||||||
|
|
@ -248,6 +267,11 @@ public:
|
||||||
bool uses_z_clip_scale = false;
|
bool uses_z_clip_scale = false;
|
||||||
RS::CullMode cull_mode = RS::CULL_MODE_DISABLED;
|
RS::CullMode cull_mode = RS::CULL_MODE_DISABLED;
|
||||||
|
|
||||||
|
bool stencil_enabled = false;
|
||||||
|
uint32_t stencil_flags = 0;
|
||||||
|
StencilCompare stencil_compare = STENCIL_COMPARE_LESS;
|
||||||
|
uint32_t stencil_reference = 0;
|
||||||
|
|
||||||
uint64_t last_pass = 0;
|
uint64_t last_pass = 0;
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
|
|
||||||
|
|
@ -257,13 +281,13 @@ public:
|
||||||
bool has_blend_alpha = uses_blend_alpha;
|
bool has_blend_alpha = uses_blend_alpha;
|
||||||
bool has_alpha = has_base_alpha || has_blend_alpha;
|
bool has_alpha = has_base_alpha || has_blend_alpha;
|
||||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||||
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
|
bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
|
||||||
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
|
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
|
||||||
}
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
|
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
|
||||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||||
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
|
bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
|
||||||
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
|
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2683,6 +2683,17 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
|
||||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_PARTICLE_TRAILS;
|
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_PARTICLE_TRAILS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_material->shader_data->stencil_enabled) {
|
||||||
|
if (p_material->shader_data->stencil_flags & SceneShaderForwardMobile::ShaderData::STENCIL_FLAG_READ) {
|
||||||
|
// Stencil materials which read from the stencil buffer must be in the alpha pass.
|
||||||
|
// This is critical to preserve compatibility once we'll have the compositor.
|
||||||
|
if (!(flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) {
|
||||||
|
String shader_path = p_material->shader_data->path.is_empty() ? "" : "(" + p_material->shader_data->path + ")";
|
||||||
|
ERR_PRINT_ED(vformat("Attempting to use a shader %s that reads stencil but is not in the alpha queue. Ensure the material uses alpha blending or has depth_draw disabled or depth_test disabled.", shader_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SceneShaderForwardMobile::MaterialData *material_shadow = nullptr;
|
SceneShaderForwardMobile::MaterialData *material_shadow = nullptr;
|
||||||
void *surface_shadow = nullptr;
|
void *surface_shadow = nullptr;
|
||||||
if (p_material->shader_data->uses_shared_shadow_material()) {
|
if (p_material->shader_data->uses_shared_shadow_material()) {
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
||||||
ShaderCompiler::GeneratedCode gen_code;
|
ShaderCompiler::GeneratedCode gen_code;
|
||||||
|
|
||||||
blend_mode = BLEND_MODE_MIX;
|
blend_mode = BLEND_MODE_MIX;
|
||||||
depth_testi = DEPTH_TEST_ENABLED;
|
depth_test_disabledi = 0;
|
||||||
|
depth_test_invertedi = 0;
|
||||||
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||||
cull_mode = RS::CULL_MODE_BACK;
|
cull_mode = RS::CULL_MODE_BACK;
|
||||||
|
|
||||||
|
|
@ -83,6 +84,12 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
||||||
|
|
||||||
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
||||||
|
|
||||||
|
int stencil_readi = 0;
|
||||||
|
int stencil_writei = 0;
|
||||||
|
int stencil_write_depth_faili = 0;
|
||||||
|
int stencil_comparei = STENCIL_COMPARE_ALWAYS;
|
||||||
|
int stencil_referencei = -1;
|
||||||
|
|
||||||
ShaderCompiler::IdentifierActions actions;
|
ShaderCompiler::IdentifierActions actions;
|
||||||
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
|
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
|
||||||
actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
|
actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
|
||||||
|
|
@ -101,7 +108,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
||||||
actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
|
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);
|
actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
|
||||||
|
|
||||||
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
|
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_test_disabledi, 1);
|
||||||
|
actions.render_mode_values["depth_test_inverted"] = Pair<int *, int>(&depth_test_invertedi, 1);
|
||||||
|
|
||||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_DISABLED);
|
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_DISABLED);
|
||||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_FRONT);
|
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_FRONT);
|
||||||
|
|
@ -141,6 +149,20 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
||||||
actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
|
actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
|
||||||
actions.write_flag_pointers["VERTEX"] = &uses_vertex;
|
actions.write_flag_pointers["VERTEX"] = &uses_vertex;
|
||||||
|
|
||||||
|
actions.stencil_mode_values["read"] = Pair<int *, int>(&stencil_readi, STENCIL_FLAG_READ);
|
||||||
|
actions.stencil_mode_values["write"] = Pair<int *, int>(&stencil_writei, STENCIL_FLAG_WRITE);
|
||||||
|
actions.stencil_mode_values["write_depth_fail"] = Pair<int *, int>(&stencil_write_depth_faili, STENCIL_FLAG_WRITE_DEPTH_FAIL);
|
||||||
|
|
||||||
|
actions.stencil_mode_values["compare_less"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_LESS);
|
||||||
|
actions.stencil_mode_values["compare_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_less_or_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_LESS_OR_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_greater"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_GREATER);
|
||||||
|
actions.stencil_mode_values["compare_not_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_NOT_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_greater_or_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_GREATER_OR_EQUAL);
|
||||||
|
actions.stencil_mode_values["compare_always"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_ALWAYS);
|
||||||
|
|
||||||
|
actions.stencil_reference = &stencil_referencei;
|
||||||
|
|
||||||
actions.uniforms = &uniforms;
|
actions.uniforms = &uniforms;
|
||||||
|
|
||||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||||
|
|
@ -159,7 +181,13 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
||||||
}
|
}
|
||||||
|
|
||||||
depth_draw = DepthDraw(depth_drawi);
|
depth_draw = DepthDraw(depth_drawi);
|
||||||
depth_test = DepthTest(depth_testi);
|
if (depth_test_disabledi) {
|
||||||
|
depth_test = DEPTH_TEST_DISABLED;
|
||||||
|
} else if (depth_test_invertedi) {
|
||||||
|
depth_test = DEPTH_TEST_ENABLED_INVERTED;
|
||||||
|
} else {
|
||||||
|
depth_test = DEPTH_TEST_ENABLED;
|
||||||
|
}
|
||||||
uses_vertex_time = gen_code.uses_vertex_time;
|
uses_vertex_time = gen_code.uses_vertex_time;
|
||||||
uses_fragment_time = gen_code.uses_fragment_time;
|
uses_fragment_time = gen_code.uses_fragment_time;
|
||||||
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
|
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
|
||||||
|
|
@ -171,6 +199,11 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
||||||
uses_tangent |= uses_normal_map;
|
uses_tangent |= uses_normal_map;
|
||||||
uses_tangent |= uses_bent_normal_map;
|
uses_tangent |= uses_bent_normal_map;
|
||||||
|
|
||||||
|
stencil_enabled = stencil_referencei != -1;
|
||||||
|
stencil_flags = stencil_readi | stencil_writei | stencil_write_depth_faili;
|
||||||
|
stencil_compare = StencilCompare(stencil_comparei);
|
||||||
|
stencil_reference = stencil_referencei;
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (uses_sss) {
|
if (uses_sss) {
|
||||||
WARN_PRINT_ONCE_ED("Subsurface scattering is only available when using the Forward+ renderer.");
|
WARN_PRINT_ONCE_ED("Subsurface scattering is only available when using the Forward+ renderer.");
|
||||||
|
|
@ -224,7 +257,7 @@ bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
|
||||||
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
|
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
|
||||||
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
||||||
|
|
||||||
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
|
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test != DEPTH_TEST_ENABLED));
|
||||||
}
|
}
|
||||||
|
|
||||||
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
|
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
|
||||||
|
|
@ -276,8 +309,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
|
||||||
|
|
||||||
if (depth_test != DEPTH_TEST_DISABLED) {
|
if (depth_test != DEPTH_TEST_DISABLED) {
|
||||||
depth_stencil_state.enable_depth_test = true;
|
depth_stencil_state.enable_depth_test = true;
|
||||||
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
|
|
||||||
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
|
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
|
||||||
|
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
|
||||||
|
|
||||||
|
if (depth_test == DEPTH_TEST_ENABLED_INVERTED) {
|
||||||
|
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
|
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
|
||||||
|
|
@ -288,6 +325,47 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
|
||||||
RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
|
RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
depth_stencil_state.enable_stencil = stencil_enabled;
|
||||||
|
if (stencil_enabled) {
|
||||||
|
static const RD::CompareOperator stencil_compare_rd_table[STENCIL_COMPARE_MAX] = {
|
||||||
|
RD::COMPARE_OP_LESS,
|
||||||
|
RD::COMPARE_OP_EQUAL,
|
||||||
|
RD::COMPARE_OP_LESS_OR_EQUAL,
|
||||||
|
RD::COMPARE_OP_GREATER,
|
||||||
|
RD::COMPARE_OP_NOT_EQUAL,
|
||||||
|
RD::COMPARE_OP_GREATER_OR_EQUAL,
|
||||||
|
RD::COMPARE_OP_ALWAYS,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t stencil_mask = 255;
|
||||||
|
|
||||||
|
RD::PipelineDepthStencilState::StencilOperationState op;
|
||||||
|
op.fail = RD::STENCIL_OP_KEEP;
|
||||||
|
op.pass = RD::STENCIL_OP_KEEP;
|
||||||
|
op.depth_fail = RD::STENCIL_OP_KEEP;
|
||||||
|
op.compare = stencil_compare_rd_table[stencil_compare];
|
||||||
|
op.compare_mask = 0;
|
||||||
|
op.write_mask = 0;
|
||||||
|
op.reference = stencil_reference;
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_READ) {
|
||||||
|
op.compare_mask = stencil_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_WRITE) {
|
||||||
|
op.pass = RD::STENCIL_OP_REPLACE;
|
||||||
|
op.write_mask = stencil_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stencil_flags & STENCIL_FLAG_WRITE_DEPTH_FAIL) {
|
||||||
|
op.depth_fail = RD::STENCIL_OP_REPLACE;
|
||||||
|
op.write_mask = stencil_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
depth_stencil_state.front_op = op;
|
||||||
|
depth_stencil_state.back_op = op;
|
||||||
|
}
|
||||||
|
|
||||||
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[p_pipeline_key.primitive_type];
|
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[p_pipeline_key.primitive_type];
|
||||||
|
|
||||||
RD::PipelineRasterizationState raster_state;
|
RD::PipelineRasterizationState raster_state;
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,8 @@ public:
|
||||||
|
|
||||||
enum DepthTest {
|
enum DepthTest {
|
||||||
DEPTH_TEST_DISABLED,
|
DEPTH_TEST_DISABLED,
|
||||||
DEPTH_TEST_ENABLED
|
DEPTH_TEST_ENABLED,
|
||||||
|
DEPTH_TEST_ENABLED_INVERTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CullVariant {
|
enum CullVariant {
|
||||||
|
|
@ -167,6 +168,23 @@ public:
|
||||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StencilFlags {
|
||||||
|
STENCIL_FLAG_READ = 1,
|
||||||
|
STENCIL_FLAG_WRITE = 2,
|
||||||
|
STENCIL_FLAG_WRITE_DEPTH_FAIL = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StencilCompare {
|
||||||
|
STENCIL_COMPARE_LESS,
|
||||||
|
STENCIL_COMPARE_EQUAL,
|
||||||
|
STENCIL_COMPARE_LESS_OR_EQUAL,
|
||||||
|
STENCIL_COMPARE_GREATER,
|
||||||
|
STENCIL_COMPARE_NOT_EQUAL,
|
||||||
|
STENCIL_COMPARE_GREATER_OR_EQUAL,
|
||||||
|
STENCIL_COMPARE_ALWAYS,
|
||||||
|
STENCIL_COMPARE_MAX // Not an actual operator, just the amount of operators.
|
||||||
|
};
|
||||||
|
|
||||||
struct PipelineKey {
|
struct PipelineKey {
|
||||||
RD::VertexFormatID vertex_format_id;
|
RD::VertexFormatID vertex_format_id;
|
||||||
RD::FramebufferFormatID framebuffer_format_id;
|
RD::FramebufferFormatID framebuffer_format_id;
|
||||||
|
|
@ -213,7 +231,8 @@ public:
|
||||||
DepthTest depth_test;
|
DepthTest depth_test;
|
||||||
|
|
||||||
int blend_mode = BLEND_MODE_MIX;
|
int blend_mode = BLEND_MODE_MIX;
|
||||||
int depth_testi = DEPTH_TEST_ENABLED;
|
int depth_test_disabledi = 0;
|
||||||
|
int depth_test_invertedi = 0;
|
||||||
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||||
int cull_mode = RS::CULL_MODE_BACK;
|
int cull_mode = RS::CULL_MODE_BACK;
|
||||||
|
|
||||||
|
|
@ -246,6 +265,11 @@ public:
|
||||||
bool writes_modelview_or_projection = false;
|
bool writes_modelview_or_projection = false;
|
||||||
bool uses_world_coordinates = false;
|
bool uses_world_coordinates = false;
|
||||||
|
|
||||||
|
bool stencil_enabled = false;
|
||||||
|
uint32_t stencil_flags = 0;
|
||||||
|
StencilCompare stencil_compare = STENCIL_COMPARE_LESS;
|
||||||
|
uint32_t stencil_reference = 0;
|
||||||
|
|
||||||
uint64_t last_pass = 0;
|
uint64_t last_pass = 0;
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
|
|
||||||
|
|
@ -255,13 +279,13 @@ public:
|
||||||
bool has_blend_alpha = uses_blend_alpha;
|
bool has_blend_alpha = uses_blend_alpha;
|
||||||
bool has_alpha = has_base_alpha || has_blend_alpha;
|
bool has_alpha = has_base_alpha || has_blend_alpha;
|
||||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||||
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
|
bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
|
||||||
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
|
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
|
||||||
}
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
|
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
|
||||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||||
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
|
bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
|
||||||
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
|
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -453,6 +453,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
||||||
case SL::Node::NODE_TYPE_SHADER: {
|
case SL::Node::NODE_TYPE_SHADER: {
|
||||||
SL::ShaderNode *pnode = (SL::ShaderNode *)p_node;
|
SL::ShaderNode *pnode = (SL::ShaderNode *)p_node;
|
||||||
|
|
||||||
|
// Render modes.
|
||||||
|
|
||||||
for (int i = 0; i < pnode->render_modes.size(); i++) {
|
for (int i = 0; i < pnode->render_modes.size(); i++) {
|
||||||
if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) {
|
if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) {
|
||||||
r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]]);
|
r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]]);
|
||||||
|
|
@ -469,6 +471,21 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stencil modes.
|
||||||
|
|
||||||
|
for (int i = 0; i < pnode->stencil_modes.size(); i++) {
|
||||||
|
if (p_actions.stencil_mode_values.has(pnode->stencil_modes[i])) {
|
||||||
|
Pair<int *, int> &p = p_actions.stencil_mode_values[pnode->stencil_modes[i]];
|
||||||
|
*p.first = p.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stencil reference value.
|
||||||
|
|
||||||
|
if (p_actions.stencil_reference && pnode->stencil_reference != -1) {
|
||||||
|
*p_actions.stencil_reference = pnode->stencil_reference;
|
||||||
|
}
|
||||||
|
|
||||||
// structs
|
// structs
|
||||||
|
|
||||||
for (int i = 0; i < pnode->vstructs.size(); i++) {
|
for (int i = 0; i < pnode->vstructs.size(); i++) {
|
||||||
|
|
@ -1463,6 +1480,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
|
||||||
SL::ShaderCompileInfo info;
|
SL::ShaderCompileInfo info;
|
||||||
info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
|
info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
|
||||||
info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
|
info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
|
||||||
|
info.stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(p_mode);
|
||||||
info.shader_types = ShaderTypes::get_singleton()->get_types();
|
info.shader_types = ShaderTypes::get_singleton()->get_types();
|
||||||
info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
|
info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
|
||||||
info.base_varying_index = actions.base_varying_index;
|
info.base_varying_index = actions.base_varying_index;
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ public:
|
||||||
HashMap<StringName, bool *> render_mode_flags;
|
HashMap<StringName, bool *> render_mode_flags;
|
||||||
HashMap<StringName, bool *> usage_flag_pointers;
|
HashMap<StringName, bool *> usage_flag_pointers;
|
||||||
HashMap<StringName, bool *> write_flag_pointers;
|
HashMap<StringName, bool *> write_flag_pointers;
|
||||||
|
HashMap<StringName, Pair<int *, int>> stencil_mode_values;
|
||||||
|
int *stencil_reference = nullptr;
|
||||||
|
|
||||||
HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms = nullptr;
|
HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -339,6 +339,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
|
||||||
{ TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} },
|
{ TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} },
|
||||||
{ TK_SHADER_TYPE, "shader_type", CF_SHADER_TYPE, {}, {} },
|
{ TK_SHADER_TYPE, "shader_type", CF_SHADER_TYPE, {}, {} },
|
||||||
{ TK_RENDER_MODE, "render_mode", CF_GLOBAL_SPACE, {}, {} },
|
{ TK_RENDER_MODE, "render_mode", CF_GLOBAL_SPACE, {}, {} },
|
||||||
|
{ TK_STENCIL_MODE, "stencil_mode", CF_GLOBAL_SPACE, {}, {} },
|
||||||
|
|
||||||
// uniform qualifiers
|
// uniform qualifiers
|
||||||
|
|
||||||
|
|
@ -4128,7 +4129,7 @@ bool ShaderLanguage::is_token_operator_assign(TokenType p_type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderLanguage::is_token_hint(TokenType p_type) {
|
bool ShaderLanguage::is_token_hint(TokenType p_type) {
|
||||||
return int(p_type) > int(TK_RENDER_MODE) && int(p_type) < int(TK_SHADER_TYPE);
|
return int(p_type) > int(TK_STENCIL_MODE) && int(p_type) < int(TK_SHADER_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, Scalar *p_value) {
|
bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, Scalar *p_value) {
|
||||||
|
|
@ -9110,7 +9111,7 @@ bool ShaderLanguage::_parse_numeric_constant_expression(const FunctionInfo &p_fu
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) {
|
Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Vector<ModeInfo> &p_stencil_modes, const HashSet<String> &p_shader_types) {
|
||||||
Token tk;
|
Token tk;
|
||||||
TkPos prev_pos;
|
TkPos prev_pos;
|
||||||
Token next;
|
Token next;
|
||||||
|
|
@ -9173,7 +9174,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
|
||||||
|
|
||||||
const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
|
const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
|
||||||
|
|
||||||
HashMap<String, String> defined_modes;
|
HashMap<String, String> defined_render_modes;
|
||||||
|
HashMap<String, String> defined_stencil_modes;
|
||||||
|
|
||||||
while (tk.type != TK_EOF) {
|
while (tk.type != TK_EOF) {
|
||||||
switch (tk.type) {
|
switch (tk.type) {
|
||||||
|
|
@ -9182,83 +9184,64 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
|
||||||
keyword_completion_context = CF_UNSPECIFIED;
|
keyword_completion_context = CF_UNSPECIFIED;
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
while (true) {
|
while (true) {
|
||||||
StringName mode;
|
Error error = _parse_shader_mode(false, p_render_modes, defined_render_modes);
|
||||||
_get_completable_identifier(nullptr, COMPLETION_RENDER_MODE, mode);
|
if (error != OK) {
|
||||||
|
return error;
|
||||||
if (mode == StringName()) {
|
|
||||||
_set_error(RTR("Expected an identifier for render mode."));
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const String smode = String(mode);
|
|
||||||
|
|
||||||
if (shader->render_modes.has(mode)) {
|
|
||||||
_set_error(vformat(RTR("Duplicated render mode: '%s'."), smode));
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
if (is_shader_inc) {
|
|
||||||
for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
|
|
||||||
const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
|
|
||||||
|
|
||||||
for (int j = 0; j < modes.size(); j++) {
|
|
||||||
const ModeInfo &info = modes[j];
|
|
||||||
const String name = String(info.name);
|
|
||||||
|
|
||||||
if (smode.begins_with(name)) {
|
|
||||||
if (!info.options.is_empty()) {
|
|
||||||
if (info.options.has(smode.substr(name.length() + 1))) {
|
|
||||||
found = true;
|
|
||||||
|
|
||||||
if (defined_modes.has(name)) {
|
|
||||||
_set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
defined_modes.insert(name, smode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < p_render_modes.size(); i++) {
|
|
||||||
const ModeInfo &info = p_render_modes[i];
|
|
||||||
const String name = String(info.name);
|
|
||||||
|
|
||||||
if (smode.begins_with(name)) {
|
|
||||||
if (!info.options.is_empty()) {
|
|
||||||
if (info.options.has(smode.substr(name.length() + 1))) {
|
|
||||||
found = true;
|
|
||||||
|
|
||||||
if (defined_modes.has(name)) {
|
|
||||||
_set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
defined_modes.insert(name, smode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
_set_error(vformat(RTR("Invalid render mode: '%s'."), smode));
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
shader->render_modes.push_back(mode);
|
|
||||||
|
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
|
|
||||||
|
if (tk.type == TK_COMMA) {
|
||||||
|
// All good, do nothing.
|
||||||
|
} else if (tk.type == TK_SEMICOLON) {
|
||||||
|
break; // Done.
|
||||||
|
} else {
|
||||||
|
_set_error(vformat(RTR("Unexpected token: '%s'."), get_token_text(tk)));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
keyword_completion_context = CF_GLOBAL_SPACE;
|
||||||
|
#endif // DEBUG_ENABLED
|
||||||
|
} break;
|
||||||
|
case TK_STENCIL_MODE: {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
keyword_completion_context = CF_UNSPECIFIED;
|
||||||
|
#endif // DEBUG_ENABLED
|
||||||
|
while (true) {
|
||||||
|
TkPos pos = _get_tkpos();
|
||||||
|
tk = _get_token();
|
||||||
|
|
||||||
|
if (tk.is_integer_constant()) {
|
||||||
|
const int reference_value = tk.constant;
|
||||||
|
|
||||||
|
if (shader->stencil_reference != -1) {
|
||||||
|
_set_error(vformat(RTR("Duplicated stencil mode reference value: '%s'."), reference_value));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reference_value < 0) {
|
||||||
|
_set_error(vformat(RTR("Stencil mode reference value cannot be negative: '%s'."), reference_value));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reference_value > 255) {
|
||||||
|
_set_error(vformat(RTR("Stencil mode reference value cannot be greater than 255: '%s'."), reference_value));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->stencil_reference = reference_value;
|
||||||
|
} else {
|
||||||
|
_set_tkpos(pos);
|
||||||
|
|
||||||
|
Error error = _parse_shader_mode(true, p_stencil_modes, defined_stencil_modes);
|
||||||
|
if (error != OK) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
|
||||||
if (tk.type == TK_COMMA) {
|
if (tk.type == TK_COMMA) {
|
||||||
//all good, do nothing
|
//all good, do nothing
|
||||||
} else if (tk.type == TK_SEMICOLON) {
|
} else if (tk.type == TK_SEMICOLON) {
|
||||||
|
|
@ -11076,6 +11059,110 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error ShaderLanguage::_parse_shader_mode(bool p_is_stencil, const Vector<ModeInfo> &p_modes, HashMap<String, String> &r_defined_modes) {
|
||||||
|
StringName mode;
|
||||||
|
_get_completable_identifier(nullptr, p_is_stencil ? COMPLETION_STENCIL_MODE : COMPLETION_RENDER_MODE, mode);
|
||||||
|
|
||||||
|
if (mode == StringName()) {
|
||||||
|
if (p_is_stencil) {
|
||||||
|
_set_error(RTR("Expected an identifier for stencil mode."));
|
||||||
|
} else {
|
||||||
|
_set_error(RTR("Expected an identifier for render mode."));
|
||||||
|
}
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const String smode = String(mode);
|
||||||
|
|
||||||
|
Vector<StringName> ¤t_modes = p_is_stencil ? shader->stencil_modes : shader->render_modes;
|
||||||
|
|
||||||
|
if (current_modes.has(mode)) {
|
||||||
|
if (p_is_stencil) {
|
||||||
|
_set_error(vformat(RTR("Duplicated stencil mode: '%s'."), smode));
|
||||||
|
} else {
|
||||||
|
_set_error(vformat(RTR("Duplicated render mode: '%s'."), smode));
|
||||||
|
}
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
if (is_shader_inc) {
|
||||||
|
for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
|
||||||
|
const Vector<ModeInfo> modes = p_is_stencil ? ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(i)) : ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
|
||||||
|
|
||||||
|
for (const ModeInfo &info : modes) {
|
||||||
|
const String name = String(info.name);
|
||||||
|
|
||||||
|
if (smode.begins_with(name)) {
|
||||||
|
if (!info.options.is_empty()) {
|
||||||
|
if (info.options.has(smode.substr(name.length() + 1))) {
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (r_defined_modes.has(name)) {
|
||||||
|
if (p_is_stencil) {
|
||||||
|
_set_error(vformat(RTR("Redefinition of stencil mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, r_defined_modes[name]));
|
||||||
|
} else {
|
||||||
|
_set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, r_defined_modes[name]));
|
||||||
|
}
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
r_defined_modes.insert(name, smode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const ModeInfo &info : p_modes) {
|
||||||
|
const String name = String(info.name);
|
||||||
|
|
||||||
|
if (smode.begins_with(name)) {
|
||||||
|
if (!info.options.is_empty()) {
|
||||||
|
if (info.options.has(smode.substr(name.length() + 1))) {
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (r_defined_modes.has(name)) {
|
||||||
|
if (p_is_stencil) {
|
||||||
|
_set_error(vformat(RTR("Redefinition of stencil mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, r_defined_modes[name]));
|
||||||
|
} else {
|
||||||
|
_set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, r_defined_modes[name]));
|
||||||
|
}
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
r_defined_modes.insert(name, smode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
if (p_is_stencil) {
|
||||||
|
_set_error(vformat(RTR("Invalid stencil mode: '%s'."), smode));
|
||||||
|
} else {
|
||||||
|
_set_error(vformat(RTR("Invalid render mode: '%s'."), smode));
|
||||||
|
}
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_is_stencil) {
|
||||||
|
shader->stencil_modes.push_back(mode);
|
||||||
|
} else {
|
||||||
|
shader->render_modes.push_back(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
// skips over whitespace and /* */ and // comments
|
// skips over whitespace and /* */ and // comments
|
||||||
static int _get_first_ident_pos(const String &p_code) {
|
static int _get_first_ident_pos(const String &p_code) {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
@ -11226,7 +11313,7 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i
|
||||||
nodes = nullptr;
|
nodes = nullptr;
|
||||||
|
|
||||||
shader = alloc_node<ShaderNode>();
|
shader = alloc_node<ShaderNode>();
|
||||||
Error err = _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
|
Error err = _parse_shader(p_info.functions, p_info.render_modes, p_info.stencil_modes, p_info.shader_types);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (check_warnings) {
|
if (check_warnings) {
|
||||||
|
|
@ -11251,7 +11338,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
|
||||||
global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func;
|
global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func;
|
||||||
|
|
||||||
shader = alloc_node<ShaderNode>();
|
shader = alloc_node<ShaderNode>();
|
||||||
_parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
|
_parse_shader(p_info.functions, p_info.render_modes, p_info.stencil_modes, p_info.shader_types);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
// Adds context keywords.
|
// Adds context keywords.
|
||||||
|
|
@ -11349,6 +11436,67 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
} break;
|
} break;
|
||||||
|
case COMPLETION_STENCIL_MODE: {
|
||||||
|
if (is_shader_inc) {
|
||||||
|
for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
|
||||||
|
const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(i));
|
||||||
|
|
||||||
|
for (const ModeInfo &info : modes) {
|
||||||
|
if (!info.options.is_empty()) {
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (const StringName &option : info.options) {
|
||||||
|
if (shader->stencil_modes.has(String(info.name) + "_" + String(option))) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
for (const StringName &option : info.options) {
|
||||||
|
ScriptLanguage::CodeCompletionOption completion_option(String(info.name) + "_" + String(option), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
|
||||||
|
r_options->push_back(completion_option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const String name = String(info.name);
|
||||||
|
|
||||||
|
if (!shader->stencil_modes.has(name)) {
|
||||||
|
ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
|
||||||
|
r_options->push_back(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const ModeInfo &info : p_info.stencil_modes) {
|
||||||
|
if (!info.options.is_empty()) {
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (const StringName &option : info.options) {
|
||||||
|
if (shader->stencil_modes.has(String(info.name) + "_" + String(option))) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
for (const StringName &option : info.options) {
|
||||||
|
ScriptLanguage::CodeCompletionOption completion_option(String(info.name) + "_" + String(option), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
|
||||||
|
r_options->push_back(completion_option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const String name = String(info.name);
|
||||||
|
|
||||||
|
if (!shader->stencil_modes.has(name)) {
|
||||||
|
ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
|
||||||
|
r_options->push_back(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
} break;
|
||||||
case COMPLETION_STRUCT: {
|
case COMPLETION_STRUCT: {
|
||||||
if (shader->structs.has(completion_struct)) {
|
if (shader->structs.has(completion_struct)) {
|
||||||
StructNode *node = shader->structs[completion_struct].shader_struct;
|
StructNode *node = shader->structs[completion_struct].shader_struct;
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,7 @@ public:
|
||||||
TK_ARG_OUT,
|
TK_ARG_OUT,
|
||||||
TK_ARG_INOUT,
|
TK_ARG_INOUT,
|
||||||
TK_RENDER_MODE,
|
TK_RENDER_MODE,
|
||||||
|
TK_STENCIL_MODE,
|
||||||
TK_HINT_DEFAULT_WHITE_TEXTURE,
|
TK_HINT_DEFAULT_WHITE_TEXTURE,
|
||||||
TK_HINT_DEFAULT_BLACK_TEXTURE,
|
TK_HINT_DEFAULT_BLACK_TEXTURE,
|
||||||
TK_HINT_DEFAULT_TRANSPARENT_TEXTURE,
|
TK_HINT_DEFAULT_TRANSPARENT_TEXTURE,
|
||||||
|
|
@ -723,6 +724,8 @@ public:
|
||||||
HashMap<StringName, Struct> structs;
|
HashMap<StringName, Struct> structs;
|
||||||
HashMap<StringName, Function> functions;
|
HashMap<StringName, Function> functions;
|
||||||
Vector<StringName> render_modes;
|
Vector<StringName> render_modes;
|
||||||
|
Vector<StringName> stencil_modes;
|
||||||
|
int stencil_reference = -1;
|
||||||
|
|
||||||
Vector<Function> vfunctions;
|
Vector<Function> vfunctions;
|
||||||
Vector<Constant> vconstants;
|
Vector<Constant> vconstants;
|
||||||
|
|
@ -799,6 +802,7 @@ public:
|
||||||
COMPLETION_NONE,
|
COMPLETION_NONE,
|
||||||
COMPLETION_SHADER_TYPE,
|
COMPLETION_SHADER_TYPE,
|
||||||
COMPLETION_RENDER_MODE,
|
COMPLETION_RENDER_MODE,
|
||||||
|
COMPLETION_STENCIL_MODE,
|
||||||
COMPLETION_MAIN_FUNCTION,
|
COMPLETION_MAIN_FUNCTION,
|
||||||
COMPLETION_IDENTIFIER,
|
COMPLETION_IDENTIFIER,
|
||||||
COMPLETION_FUNCTION_CALL,
|
COMPLETION_FUNCTION_CALL,
|
||||||
|
|
@ -937,6 +941,13 @@ public:
|
||||||
options.push_back(p_arg5);
|
options.push_back(p_arg5);
|
||||||
options.push_back(p_arg6);
|
options.push_back(p_arg6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModeInfo(const StringName &p_name, std::initializer_list<StringName> p_args) :
|
||||||
|
name(p_name) {
|
||||||
|
for (const StringName &arg : p_args) {
|
||||||
|
options.push_back(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionInfo {
|
struct FunctionInfo {
|
||||||
|
|
@ -1215,11 +1226,13 @@ private:
|
||||||
String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
|
String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
|
||||||
|
|
||||||
bool _parse_numeric_constant_expression(const FunctionInfo &p_function_info, float &r_constant);
|
bool _parse_numeric_constant_expression(const FunctionInfo &p_function_info, float &r_constant);
|
||||||
Error _parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types);
|
Error _parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Vector<ModeInfo> &p_stencil_modes, const HashSet<String> &p_shader_types);
|
||||||
|
|
||||||
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
|
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
|
||||||
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
|
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
|
||||||
|
|
||||||
|
Error _parse_shader_mode(bool p_is_stencil, const Vector<ModeInfo> &p_modes, HashMap<String, String> &r_defined_modes);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
List<ShaderWarning>::Element *get_warnings_ptr();
|
List<ShaderWarning>::Element *get_warnings_ptr();
|
||||||
|
|
@ -1241,6 +1254,7 @@ public:
|
||||||
struct ShaderCompileInfo {
|
struct ShaderCompileInfo {
|
||||||
HashMap<StringName, FunctionInfo> functions;
|
HashMap<StringName, FunctionInfo> functions;
|
||||||
Vector<ModeInfo> render_modes;
|
Vector<ModeInfo> render_modes;
|
||||||
|
Vector<ModeInfo> stencil_modes;
|
||||||
VaryingFunctionNames varying_function_names;
|
VaryingFunctionNames varying_function_names;
|
||||||
HashSet<String> shader_types;
|
HashSet<String> shader_types;
|
||||||
GlobalShaderUniformGetTypeFunc global_shader_uniform_type_func = nullptr;
|
GlobalShaderUniformGetTypeFunc global_shader_uniform_type_func = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,10 @@ const Vector<ShaderLanguage::ModeInfo> &ShaderTypes::get_modes(RS::ShaderMode p_
|
||||||
return shader_modes[p_mode].modes;
|
return shader_modes[p_mode].modes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Vector<ShaderLanguage::ModeInfo> &ShaderTypes::get_stencil_modes(RS::ShaderMode p_mode) const {
|
||||||
|
return shader_modes[p_mode].stencil_modes;
|
||||||
|
}
|
||||||
|
|
||||||
const HashSet<String> &ShaderTypes::get_types() const {
|
const HashSet<String> &ShaderTypes::get_types() const {
|
||||||
return shader_types;
|
return shader_types;
|
||||||
}
|
}
|
||||||
|
|
@ -226,7 +230,7 @@ ShaderTypes::ShaderTypes() {
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("blend"), "mix", "add", "sub", "mul", "premul_alpha" });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("blend"), "mix", "add", "sub", "mul", "premul_alpha" });
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_draw"), "opaque", "always", "never" });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_draw"), "opaque", "always", "never" });
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_prepass_alpha") });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_prepass_alpha") });
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test_disabled") });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test"), { "default", "disabled", "inverted" } });
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("sss_mode_skin") });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("sss_mode_skin") });
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("cull"), "back", "front", "disabled" });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("cull"), "back", "front", "disabled" });
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("unshaded") });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("unshaded") });
|
||||||
|
|
@ -246,6 +250,10 @@ ShaderTypes::ShaderTypes() {
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("debug_shadow_splits") });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("debug_shadow_splits") });
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("fog_disabled") });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("fog_disabled") });
|
||||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("specular_occlusion_disabled") });
|
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("specular_occlusion_disabled") });
|
||||||
|
shader_modes[RS::SHADER_SPATIAL].stencil_modes.push_back({ PNAME("read") });
|
||||||
|
shader_modes[RS::SHADER_SPATIAL].stencil_modes.push_back({ PNAME("write") });
|
||||||
|
shader_modes[RS::SHADER_SPATIAL].stencil_modes.push_back({ PNAME("write_depth_fail") });
|
||||||
|
shader_modes[RS::SHADER_SPATIAL].stencil_modes.push_back({ PNAME("compare"), { "always", "less", "equal", "less_or_equal", "greater", "not_equal", "greater_or_equal" } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/************ CANVAS ITEM **************************/
|
/************ CANVAS ITEM **************************/
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ class ShaderTypes {
|
||||||
struct Type {
|
struct Type {
|
||||||
HashMap<StringName, ShaderLanguage::FunctionInfo> functions;
|
HashMap<StringName, ShaderLanguage::FunctionInfo> functions;
|
||||||
Vector<ShaderLanguage::ModeInfo> modes;
|
Vector<ShaderLanguage::ModeInfo> modes;
|
||||||
|
Vector<ShaderLanguage::ModeInfo> stencil_modes;
|
||||||
};
|
};
|
||||||
|
|
||||||
HashMap<RS::ShaderMode, Type> shader_modes;
|
HashMap<RS::ShaderMode, Type> shader_modes;
|
||||||
|
|
@ -51,6 +52,7 @@ public:
|
||||||
|
|
||||||
const HashMap<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const;
|
const HashMap<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const;
|
||||||
const Vector<ShaderLanguage::ModeInfo> &get_modes(RS::ShaderMode p_mode) const;
|
const Vector<ShaderLanguage::ModeInfo> &get_modes(RS::ShaderMode p_mode) const;
|
||||||
|
const Vector<ShaderLanguage::ModeInfo> &get_stencil_modes(RS::ShaderMode p_mode) const;
|
||||||
const HashSet<String> &get_types() const;
|
const HashSet<String> &get_types() const;
|
||||||
const List<String> &get_types_list() const;
|
const List<String> &get_types_list() const;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue