Merge pull request #80710 from apples/7174-apples-stencil
Add stencil support to spatial materials
This commit is contained in:
@@ -138,6 +138,10 @@ void RasterizerGLES3::clear_depth(float p_depth) {
|
||||
#endif // GLES_API_ENABLED
|
||||
}
|
||||
|
||||
void RasterizerGLES3::clear_stencil(int32_t p_stencil) {
|
||||
glClearStencil(p_stencil);
|
||||
}
|
||||
|
||||
#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) {
|
||||
// These are ultimately annoying, so removing for now.
|
||||
|
||||
@@ -116,6 +116,7 @@ public:
|
||||
|
||||
static bool is_gles_over_gl() { return gles_over_gl; }
|
||||
static void clear_depth(float p_depth);
|
||||
static void clear_stencil(int32_t p_stencil);
|
||||
|
||||
static void make_current(bool 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/feed_effects.h"
|
||||
#include "drivers/gles3/storage/material_storage.h"
|
||||
#include "rasterizer_gles3.h"
|
||||
#include "storage/config.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;
|
||||
}
|
||||
|
||||
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
|
||||
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_SHADOW;
|
||||
}
|
||||
@@ -236,6 +241,17 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
|
||||
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;
|
||||
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) {
|
||||
@@ -1233,6 +1249,7 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
|
||||
scene_state.used_screen_texture = false;
|
||||
scene_state.used_normal_texture = false;
|
||||
scene_state.used_depth_texture = false;
|
||||
scene_state.used_opaque_stencil = false;
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
glDepthFunc(GL_GREATER);
|
||||
scene_state.set_gl_depth_func(GL_GREATER);
|
||||
|
||||
glColorMask(0, 0, 0, 0);
|
||||
glDrawBuffers(0, nullptr);
|
||||
@@ -2489,6 +2509,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
// Do depth prepass if it's explicitly enabled
|
||||
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
|
||||
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_draw(true);
|
||||
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_stencil_test(false);
|
||||
scene_state.set_gl_stencil_write_mask(255);
|
||||
|
||||
glColorMask(0, 0, 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.
|
||||
GLuint db = p_camera_data->view_count > 1 ? GL_COLOR_ATTACHMENT0 : GL_NONE;
|
||||
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_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
scene_state.set_gl_depth_func(GL_GEQUAL);
|
||||
|
||||
{
|
||||
GLuint db = GL_COLOR_ATTACHMENT0;
|
||||
glDrawBuffers(1, &db);
|
||||
}
|
||||
|
||||
scene_state.enable_gl_stencil_test(false);
|
||||
|
||||
if (!fb_cleared) {
|
||||
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:
|
||||
@@ -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());
|
||||
|
||||
scene_state.enable_gl_depth_draw(false);
|
||||
scene_state.enable_gl_stencil_test(false);
|
||||
|
||||
if (draw_sky || draw_sky_fog_only) {
|
||||
RENDER_TIMESTAMP("Render Sky");
|
||||
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.set_gl_depth_func(GL_GEQUAL);
|
||||
scene_state.enable_gl_blend(false);
|
||||
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) {
|
||||
glBlitFramebuffer(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);
|
||||
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);
|
||||
|
||||
scene_state.enable_gl_stencil_test(false);
|
||||
|
||||
if (!flip_y) {
|
||||
// Restore the default winding order.
|
||||
glFrontFace(GL_CCW);
|
||||
@@ -2834,7 +2867,7 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||
// Copy depth buffer
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_int);
|
||||
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);
|
||||
@@ -2863,10 +2896,10 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||
|
||||
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_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_DEPTH_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);
|
||||
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_STENCIL_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2908,10 +2941,10 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
|
||||
|
||||
for (uint32_t v = 0; v < view_count; v++) {
|
||||
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, read_depth, 0, v);
|
||||
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
|
||||
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, read_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) {
|
||||
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) {
|
||||
@@ -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 (!uses_additive_lighting && pass == 1) {
|
||||
// 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.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
glDepthFunc(GL_GREATER);
|
||||
scene_state.set_gl_depth_func(GL_GREATER);
|
||||
|
||||
glDrawBuffers(0, nullptr);
|
||||
|
||||
@@ -3759,7 +3839,7 @@ void RasterizerSceneGLES3::_render_uv2(const PagedArray<RenderGeometryInstance *
|
||||
scene_state.reset_gl_state();
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
glDepthFunc(GL_GREATER);
|
||||
scene_state.set_gl_depth_func(GL_GREATER);
|
||||
|
||||
TightLocalVector<GLenum> draw_buffers;
|
||||
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);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
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);
|
||||
|
||||
// Loop through quadrants and copy shadows over.
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "platform_gl.h"
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "core/math/projection.h"
|
||||
@@ -246,6 +247,7 @@ private:
|
||||
FLAG_USES_DEPTH_TEXTURE = 4096,
|
||||
FLAG_USES_NORMAL_TEXTURE = 8192,
|
||||
FLAG_USES_DOUBLE_SIDED_SHADOWS = 16384,
|
||||
FLAG_USES_STENCIL = 32768,
|
||||
};
|
||||
|
||||
union {
|
||||
@@ -462,6 +464,7 @@ private:
|
||||
|
||||
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
||||
RS::CullMode cull_mode = RS::CULL_MODE_BACK;
|
||||
GLenum current_depth_function = GL_GEQUAL;
|
||||
|
||||
bool current_blend_enabled = false;
|
||||
bool current_depth_draw_enabled = false;
|
||||
@@ -483,6 +486,18 @@ private:
|
||||
current_depth_draw_enabled = false;
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
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) {
|
||||
@@ -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 used_screen_texture = false;
|
||||
bool used_normal_texture = false;
|
||||
bool used_depth_texture = false;
|
||||
bool used_opaque_stencil = false;
|
||||
|
||||
LightData *omni_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.
|
||||
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 cull_modei = RS::CULL_MODE_BACK;
|
||||
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;
|
||||
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
|
||||
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_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_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_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;
|
||||
|
||||
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);
|
||||
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
|
||||
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);
|
||||
|
||||
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_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
|
||||
if (uses_particle_trails) {
|
||||
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_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 {
|
||||
|
||||
@@ -257,7 +257,25 @@ struct SceneShaderData : public ShaderData {
|
||||
|
||||
enum DepthTest {
|
||||
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 {
|
||||
@@ -285,6 +303,11 @@ struct SceneShaderData : public ShaderData {
|
||||
DepthTest depth_test;
|
||||
RS::CullMode cull_mode;
|
||||
|
||||
StencilCompare stencil_compare;
|
||||
uint32_t stencil_flags;
|
||||
int32_t stencil_reference;
|
||||
bool stencil_enabled;
|
||||
|
||||
bool uses_point_size;
|
||||
bool uses_alpha;
|
||||
bool uses_alpha_clip;
|
||||
|
||||
@@ -63,14 +63,14 @@ void RenderSceneBuffersGLES3::_rt_attach_textures(GLuint p_color, GLuint p_depth
|
||||
if (p_samples > 1) {
|
||||
#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_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
|
||||
ERR_PRINT_ONCE("Multiview MSAA isn't supported on this platform.");
|
||||
#endif
|
||||
} else {
|
||||
#ifndef IOS_ENABLED
|
||||
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
|
||||
ERR_PRINT_ONCE("Multiview isn't supported on this platform.");
|
||||
#endif
|
||||
@@ -79,13 +79,13 @@ void RenderSceneBuffersGLES3::_rt_attach_textures(GLuint p_color, GLuint p_depth
|
||||
if (p_samples > 1) {
|
||||
#ifdef ANDROID_ENABLED
|
||||
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
|
||||
ERR_PRINT_ONCE("MSAA via EXT_multisampled_render_to_texture isn't supported on this platform.");
|
||||
#endif
|
||||
} else {
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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 {
|
||||
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);
|
||||
@@ -250,13 +251,13 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||
#ifndef IOS_ENABLED
|
||||
if (use_multiview) {
|
||||
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
|
||||
{
|
||||
#endif
|
||||
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);
|
||||
@@ -299,15 +300,15 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||
glGenRenderbuffers(1, &msaa3d.depth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, msaa3d.depth);
|
||||
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa3d.samples, GL_DEPTH_COMPONENT24, 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");
|
||||
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 * depth_format_size * msaa3d.samples, "MSAA 3D depth render buffer");
|
||||
|
||||
// Create our MSAA 3D FBO.
|
||||
glGenFramebuffers(1, &msaa3d.fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
|
||||
|
||||
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);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
@@ -341,9 +342,9 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.depth);
|
||||
|
||||
#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
|
||||
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
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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;
|
||||
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) {
|
||||
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);
|
||||
|
||||
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 {
|
||||
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);
|
||||
@@ -523,12 +525,12 @@ void RenderSceneBuffersGLES3::check_backbuffer(bool p_need_color, bool p_need_de
|
||||
|
||||
#ifndef IOS_ENABLED
|
||||
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
|
||||
{
|
||||
#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);
|
||||
|
||||
rt->depth = texture->tex_id;
|
||||
rt->depth_has_stencil = rt->overridden.depth_has_stencil;
|
||||
} else {
|
||||
glGenTextures(1, &rt->depth);
|
||||
glBindTexture(texture_target, rt->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);
|
||||
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 {
|
||||
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);
|
||||
@@ -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_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
|
||||
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
|
||||
{
|
||||
#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);
|
||||
@@ -2354,12 +2358,33 @@ void GLES3::TextureStorage::check_backbuffer(RenderTarget *rt, const bool uses_s
|
||||
if (rt->backbuffer_depth == 0 && uses_depth_texture) {
|
||||
glGenTextures(1, &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 {
|
||||
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_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);
|
||||
#ifndef IOS_ENABLED
|
||||
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
|
||||
{
|
||||
#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.depth = p_depth_texture;
|
||||
rt->overridden.depth_has_stencil = p_depth_texture.is_null();
|
||||
rt->overridden.is_overridden = true;
|
||||
|
||||
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->color = cache->get().color;
|
||||
rt->depth = cache->get().depth;
|
||||
rt->depth_has_stencil = cache->get().depth_has_stencil;
|
||||
rt->size = cache->get().size;
|
||||
rt->texture = p_color_texture;
|
||||
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.color = rt->color;
|
||||
new_entry.depth = rt->depth;
|
||||
new_entry.depth_has_stencil = rt->depth_has_stencil;
|
||||
new_entry.size = rt->size;
|
||||
// Keep track of any textures we had to allocate because they weren't overridden.
|
||||
if (p_color_texture.is_null()) {
|
||||
|
||||
@@ -347,6 +347,7 @@ struct RenderTarget {
|
||||
GLuint backbuffer_fbo = 0;
|
||||
GLuint backbuffer = 0;
|
||||
GLuint backbuffer_depth = 0;
|
||||
bool depth_has_stencil = true;
|
||||
|
||||
bool hdr = false; // For Compatibility this effects both 2D and 3D rendering!
|
||||
GLuint color_internal_format = GL_RGBA8;
|
||||
@@ -375,6 +376,7 @@ struct RenderTarget {
|
||||
|
||||
struct RTOverridden {
|
||||
bool is_overridden = false;
|
||||
bool depth_has_stencil = false;
|
||||
RID color;
|
||||
RID depth;
|
||||
RID velocity;
|
||||
@@ -385,6 +387,7 @@ struct RenderTarget {
|
||||
GLuint depth;
|
||||
Size2i size;
|
||||
Vector<GLuint> allocated_textures;
|
||||
bool depth_has_stencil;
|
||||
};
|
||||
RBMap<uint32_t, FBOCacheEntry> fbo_cache;
|
||||
} overridden;
|
||||
|
||||
Reference in New Issue
Block a user