Skip to content

Commit d674c9e

Browse files
committed
Add stencil support for spatial materials
1 parent 7574a5d commit d674c9e

29 files changed

+1319
-125
lines changed

doc/classes/BaseMaterial3D.xml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,24 @@
378378
The method for rendering the specular blob.
379379
[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.
380380
</member>
381+
<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.">
382+
The primary color of the stencil effect.
383+
</member>
384+
<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.">
385+
The comparison operator to use for stencil masking operations. See [enum StencilCompare].
386+
</member>
387+
<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.">
388+
The flags dictating how the stencil operation behaves. See [enum StencilFlags].
389+
</member>
390+
<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.">
391+
The stencil effect mode. See [enum StencilMode].
392+
</member>
393+
<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.">
394+
The outline thickness for [constant STENCIL_MODE_OUTLINE].
395+
</member>
396+
<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.">
397+
The stencil reference value (0-255). Typically a power of 2.
398+
</member>
381399
<member name="subsurf_scatter_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
382400
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].
383401
</member>
@@ -828,5 +846,49 @@
828846
<constant name="DISTANCE_FADE_OBJECT_DITHER" value="3" enum="DistanceFadeMode">
829847
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].
830848
</constant>
849+
<constant name="STENCIL_MODE_DISABLED" value="0" enum="StencilMode">
850+
Disables stencil operations.
851+
</constant>
852+
<constant name="STENCIL_MODE_OUTLINE" value="1" enum="StencilMode">
853+
Stencil preset which applies an outline to the object.
854+
[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.
855+
</constant>
856+
<constant name="STENCIL_MODE_XRAY" value="2" enum="StencilMode">
857+
Stencil preset which shows a silhouette of the object behind walls.
858+
[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.
859+
</constant>
860+
<constant name="STENCIL_MODE_CUSTOM" value="3" enum="StencilMode">
861+
Enables stencil operations without a preset.
862+
</constant>
863+
<constant name="STENCIL_FLAG_READ" value="1" enum="StencilFlags">
864+
The material will only be rendered where it passes a stencil comparison with existing stencil buffer values. See [enum StencilCompare].
865+
</constant>
866+
<constant name="STENCIL_FLAG_WRITE" value="2" enum="StencilFlags">
867+
The material will write the reference value to the stencil buffer where it passes the depth test.
868+
</constant>
869+
<constant name="STENCIL_FLAG_WRITE_DEPTH_FAIL" value="4" enum="StencilFlags">
870+
The material will write the reference value to the stencil buffer where it fails the depth test.
871+
</constant>
872+
<constant name="STENCIL_COMPARE_ALWAYS" value="0" enum="StencilCompare">
873+
Always passes the stencil test.
874+
</constant>
875+
<constant name="STENCIL_COMPARE_LESS" value="1" enum="StencilCompare">
876+
Passes the stencil test when the reference value is less than the existing stencil value.
877+
</constant>
878+
<constant name="STENCIL_COMPARE_EQUAL" value="2" enum="StencilCompare">
879+
Passes the stencil test when the reference value is equal to the existing stencil value.
880+
</constant>
881+
<constant name="STENCIL_COMPARE_LESS_OR_EQUAL" value="3" enum="StencilCompare">
882+
Passes the stencil test when the reference value is less than or equal to the existing stencil value.
883+
</constant>
884+
<constant name="STENCIL_COMPARE_GREATER" value="4" enum="StencilCompare">
885+
Passes the stencil test when the reference value is greater than the existing stencil value.
886+
</constant>
887+
<constant name="STENCIL_COMPARE_NOT_EQUAL" value="5" enum="StencilCompare">
888+
Passes the stencil test when the reference value is not equal to the existing stencil value.
889+
</constant>
890+
<constant name="STENCIL_COMPARE_GREATER_OR_EQUAL" value="6" enum="StencilCompare">
891+
Passes the stencil test when the reference value is greater than or equal to the existing stencil value.
892+
</constant>
831893
</constants>
832894
</class>

drivers/gles3/rasterizer_gles3.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ void RasterizerGLES3::clear_depth(float p_depth) {
138138
#endif // GLES_API_ENABLED
139139
}
140140

141+
void RasterizerGLES3::clear_stencil(int32_t p_stencil) {
142+
glClearStencil(p_stencil);
143+
}
144+
141145
#ifdef CAN_DEBUG
142146
static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
143147
// These are ultimately annoying, so removing for now.

drivers/gles3/rasterizer_gles3.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class RasterizerGLES3 : public RendererCompositor {
116116

117117
static bool is_gles_over_gl() { return gles_over_gl; }
118118
static void clear_depth(float p_depth);
119+
static void clear_stencil(int32_t p_stencil);
119120

120121
static void make_current(bool p_gles_over_gl) {
121122
gles_over_gl = p_gles_over_gl;

drivers/gles3/rasterizer_scene_gles3.cpp

Lines changed: 82 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
224224
flags |= GeometryInstanceSurface::FLAG_USES_DOUBLE_SIDED_SHADOWS;
225225
}
226226

227+
if (p_material->shader_data->stencil_enabled) {
228+
flags |= GeometryInstanceSurface::FLAG_USES_STENCIL;
229+
}
230+
227231
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) {
228232
//material is only meant for alpha pass
229233
flags |= GeometryInstanceSurface::FLAG_PASS_ALPHA;
@@ -237,6 +241,17 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
237241
flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW;
238242
}
239243

244+
if (p_material->shader_data->stencil_enabled) {
245+
if (p_material->shader_data->stencil_flags & GLES3::SceneShaderData::STENCIL_FLAG_READ) {
246+
// Stencil materials which read from the stencil buffer must be in the alpha pass.
247+
// This is critical to preserve compatibility once we'll have the compositor.
248+
if (!(flags & GeometryInstanceSurface::FLAG_PASS_ALPHA)) {
249+
String shader_path = p_material->shader_data->path.is_empty() ? "" : "(" + p_material->shader_data->path + ")";
250+
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));
251+
}
252+
}
253+
}
254+
240255
GLES3::SceneMaterialData *material_shadow = nullptr;
241256
void *surface_shadow = nullptr;
242257
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) {
@@ -1234,6 +1249,7 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
12341249
scene_state.used_screen_texture = false;
12351250
scene_state.used_normal_texture = false;
12361251
scene_state.used_depth_texture = false;
1252+
scene_state.used_opaque_stencil = false;
12371253
}
12381254

12391255
Plane near_plane;
@@ -1427,6 +1443,9 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
14271443
if (surf->flags & GeometryInstanceSurface::FLAG_USES_DEPTH_TEXTURE) {
14281444
scene_state.used_depth_texture = true;
14291445
}
1446+
if ((surf->flags & GeometryInstanceSurface::FLAG_USES_STENCIL) && !force_alpha && (surf->flags & (GeometryInstanceSurface::FLAG_PASS_DEPTH | GeometryInstanceSurface::FLAG_PASS_OPAQUE))) {
1447+
scene_state.used_opaque_stencil = true;
1448+
}
14301449

14311450
} else if (p_pass_mode == PASS_MODE_SHADOW) {
14321451
if (surf->flags & GeometryInstanceSurface::FLAG_PASS_SHADOW) {
@@ -2490,6 +2509,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
24902509
// Do depth prepass if it's explicitly enabled
24912510
bool use_depth_prepass = config->use_depth_prepass;
24922511

2512+
// Forcibly enable depth prepass if opaque stencil writes are used.
2513+
use_depth_prepass = use_depth_prepass || scene_state.used_opaque_stencil;
2514+
24932515
// Don't do depth prepass we are rendering overdraw
24942516
use_depth_prepass = use_depth_prepass && get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_OVERDRAW;
24952517

@@ -2506,10 +2528,13 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
25062528
scene_state.enable_gl_blend(false);
25072529
scene_state.set_gl_depth_func(GL_GEQUAL);
25082530
scene_state.enable_gl_scissor_test(false);
2531+
scene_state.enable_gl_stencil_test(false);
2532+
scene_state.set_gl_stencil_write_mask(255);
25092533

25102534
glColorMask(0, 0, 0, 0);
25112535
RasterizerGLES3::clear_depth(0.0);
2512-
glClear(GL_DEPTH_BUFFER_BIT);
2536+
RasterizerGLES3::clear_stencil(0);
2537+
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
25132538
// Some desktop GL implementations fall apart when using Multiview with GL_NONE.
25142539
GLuint db = p_camera_data->view_count > 1 ? GL_COLOR_ATTACHMENT0 : GL_NONE;
25152540
glDrawBuffers(1, &db);
@@ -2549,9 +2574,12 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
25492574
glDrawBuffers(1, &db);
25502575
}
25512576

2577+
scene_state.enable_gl_stencil_test(false);
2578+
25522579
if (!fb_cleared) {
25532580
RasterizerGLES3::clear_depth(0.0);
2554-
glClear(GL_DEPTH_BUFFER_BIT);
2581+
RasterizerGLES3::clear_stencil(0);
2582+
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
25552583
}
25562584

25572585
// Need to clear framebuffer unless:
@@ -2631,6 +2659,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
26312659
_render_list_template<PASS_MODE_COLOR>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_OPAQUE].elements.size());
26322660

26332661
scene_state.enable_gl_depth_draw(false);
2662+
scene_state.enable_gl_stencil_test(false);
26342663

26352664
if (draw_sky || draw_sky_fog_only) {
26362665
RENDER_TIMESTAMP("Render Sky");
@@ -2689,7 +2718,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
26892718
if (scene_state.used_depth_texture) {
26902719
glBlitFramebuffer(0, 0, size.x, size.y,
26912720
0, 0, size.x, size.y,
2692-
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
2721+
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
26932722
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 7);
26942723
glBindTexture(GL_TEXTURE_2D, backbuffer_depth);
26952724
}
@@ -2707,6 +2736,8 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
27072736

27082737
_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true);
27092738

2739+
scene_state.enable_gl_stencil_test(false);
2740+
27102741
if (!flip_y) {
27112742
// Restore the default winding order.
27122743
glFrontFace(GL_CCW);
@@ -2836,7 +2867,7 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
28362867
// Copy depth buffer
28372868
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_int);
28382869
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_rt);
2839-
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
2870+
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);
28402871
}
28412872

28422873
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
@@ -2865,10 +2896,10 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
28652896

28662897
for (uint32_t v = 0; v < view_count; v++) {
28672898
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, read_color, 0, v);
2868-
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, read_depth, 0, v);
2899+
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, read_depth, 0, v);
28692900
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
2870-
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
2871-
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);
2901+
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, write_depth, 0, v);
2902+
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);
28722903
}
28732904
}
28742905

@@ -2910,10 +2941,10 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
29102941
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
29112942

29122943
for (uint32_t v = 0; v < view_count; v++) {
2913-
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, read_depth, 0, v);
2914-
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
2944+
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, read_depth, 0, v);
2945+
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, write_depth, 0, v);
29152946

2916-
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
2947+
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);
29172948
}
29182949
}
29192950

@@ -3052,6 +3083,47 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
30523083
}
30533084
}
30543085

3086+
// Stencil.
3087+
if (shader->stencil_enabled) {
3088+
static const GLenum stencil_compare_table[GLES3::SceneShaderData::STENCIL_COMPARE_MAX] = {
3089+
GL_LESS,
3090+
GL_EQUAL,
3091+
GL_LEQUAL,
3092+
GL_GREATER,
3093+
GL_NOTEQUAL,
3094+
GL_GEQUAL,
3095+
GL_ALWAYS,
3096+
};
3097+
3098+
GLenum stencil_compare = stencil_compare_table[shader->stencil_compare];
3099+
GLuint stencil_compare_mask = 0;
3100+
GLuint stencil_write_mask = 0;
3101+
GLenum stencil_op_dpfail = GL_KEEP;
3102+
GLenum stencil_op_dppass = GL_KEEP;
3103+
3104+
if (shader->stencil_flags & GLES3::SceneShaderData::STENCIL_FLAG_READ) {
3105+
stencil_compare_mask = 255;
3106+
}
3107+
3108+
if (shader->stencil_flags & GLES3::SceneShaderData::STENCIL_FLAG_WRITE) {
3109+
stencil_op_dppass = GL_REPLACE;
3110+
stencil_write_mask = 255;
3111+
}
3112+
3113+
if (shader->stencil_flags & GLES3::SceneShaderData::STENCIL_FLAG_WRITE_DEPTH_FAIL) {
3114+
stencil_op_dpfail = GL_REPLACE;
3115+
stencil_write_mask = 255;
3116+
}
3117+
3118+
scene_state.enable_gl_stencil_test(true);
3119+
scene_state.set_gl_stencil_func(stencil_compare, shader->stencil_reference, stencil_compare_mask);
3120+
scene_state.set_gl_stencil_write_mask(stencil_write_mask);
3121+
scene_state.set_gl_stencil_op(GL_KEEP, stencil_op_dpfail, stencil_op_dppass);
3122+
} else {
3123+
scene_state.enable_gl_stencil_test(false);
3124+
scene_state.set_gl_stencil_write_mask(255);
3125+
}
3126+
30553127
if constexpr (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
30563128
if (!uses_additive_lighting && pass == 1) {
30573129
// Don't render additive passes if not using additive lighting.

drivers/gles3/rasterizer_scene_gles3.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
247247
FLAG_USES_DEPTH_TEXTURE = 4096,
248248
FLAG_USES_NORMAL_TEXTURE = 8192,
249249
FLAG_USES_DOUBLE_SIDED_SHADOWS = 16384,
250+
FLAG_USES_STENCIL = 32768,
250251
};
251252

252253
union {
@@ -488,6 +489,15 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
488489

489490
glDepthFunc(GL_GEQUAL);
490491
current_depth_function = GL_GEQUAL;
492+
493+
glDisable(GL_STENCIL_TEST);
494+
current_stencil_test_enabled = false;
495+
glStencilMask(255);
496+
current_stencil_write_mask = 255;
497+
glStencilFunc(GL_ALWAYS, 0, 255);
498+
current_stencil_compare = GL_ALWAYS;
499+
current_stencil_reference = 0;
500+
current_stencil_compare_mask = 255;
491501
}
492502

493503
void set_gl_cull_mode(RS::CullMode p_mode) {
@@ -552,10 +562,56 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
552562
}
553563
}
554564

565+
void enable_gl_stencil_test(bool p_enabled) {
566+
if (current_stencil_test_enabled != p_enabled) {
567+
if (p_enabled) {
568+
glEnable(GL_STENCIL_TEST);
569+
} else {
570+
glDisable(GL_STENCIL_TEST);
571+
}
572+
current_stencil_test_enabled = p_enabled;
573+
}
574+
}
575+
576+
void set_gl_stencil_func(GLenum p_compare, GLint p_reference, GLenum p_compare_mask) {
577+
if (current_stencil_compare != p_compare || current_stencil_reference != p_reference || current_stencil_compare_mask != p_compare_mask) {
578+
glStencilFunc(p_compare, p_reference, p_compare_mask);
579+
current_stencil_compare = p_compare;
580+
current_stencil_reference = p_reference;
581+
current_stencil_compare_mask = p_compare_mask;
582+
}
583+
}
584+
585+
void set_gl_stencil_write_mask(GLuint p_mask) {
586+
if (current_stencil_write_mask != p_mask) {
587+
glStencilMask(p_mask);
588+
current_stencil_write_mask = p_mask;
589+
}
590+
}
591+
592+
void set_gl_stencil_op(GLenum p_op_fail, GLenum p_op_dpfail, GLenum p_op_dppass) {
593+
if (current_stencil_op_fail != p_op_fail || current_stencil_op_dpfail != p_op_dpfail || current_stencil_op_dppass != p_op_dppass) {
594+
glStencilOp(p_op_fail, p_op_dpfail, p_op_dppass);
595+
current_stencil_op_fail = p_op_fail;
596+
current_stencil_op_dpfail = p_op_dpfail;
597+
current_stencil_op_dppass = p_op_dppass;
598+
}
599+
}
600+
601+
GLenum current_stencil_compare = GL_ALWAYS;
602+
GLuint current_stencil_compare_mask = 255;
603+
GLuint current_stencil_write_mask = 255;
604+
GLint current_stencil_reference = 0;
605+
GLenum current_stencil_op_fail = GL_KEEP;
606+
GLenum current_stencil_op_dpfail = GL_KEEP;
607+
GLenum current_stencil_op_dppass = GL_KEEP;
608+
bool current_stencil_test_enabled = false;
609+
555610
bool texscreen_copied = false;
556611
bool used_screen_texture = false;
557612
bool used_normal_texture = false;
558613
bool used_depth_texture = false;
614+
bool used_opaque_stencil = false;
559615

560616
LightData *omni_lights = nullptr;
561617
LightData *spot_lights = nullptr;

0 commit comments

Comments
 (0)