Implement glow/bloom on compatibility renderer
This commit is contained in:
parent
ab4c5a594a
commit
aa260e5f3d
|
@ -155,12 +155,14 @@ void CopyEffects::copy_to_and_from_rect(const Rect2 &p_rect) {
|
||||||
draw_screen_quad();
|
draw_screen_quad();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyEffects::copy_screen() {
|
void CopyEffects::copy_screen(float p_multiply) {
|
||||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT);
|
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SCREEN);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copy.shader.version_set_uniform(CopyShaderGLES3::MULTIPLY, p_multiply, copy.shader_version, CopyShaderGLES3::MODE_SCREEN);
|
||||||
|
|
||||||
draw_screen_triangle();
|
draw_screen_triangle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
#ifdef GLES3_ENABLED
|
#ifdef GLES3_ENABLED
|
||||||
|
|
||||||
#include "drivers/gles3/shaders/copy.glsl.gen.h"
|
#include "drivers/gles3/shaders/effects/copy.glsl.gen.h"
|
||||||
|
|
||||||
namespace GLES3 {
|
namespace GLES3 {
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ public:
|
||||||
void copy_to_rect(const Rect2 &p_rect);
|
void copy_to_rect(const Rect2 &p_rect);
|
||||||
void copy_to_rect_3d(const Rect2 &p_rect, float p_layer, int p_type, float p_lod = 0.0f);
|
void copy_to_rect_3d(const Rect2 &p_rect, float p_layer, int p_type, float p_lod = 0.0f);
|
||||||
void copy_to_and_from_rect(const Rect2 &p_rect);
|
void copy_to_and_from_rect(const Rect2 &p_rect);
|
||||||
void copy_screen();
|
void copy_screen(float p_multiply = 1.0);
|
||||||
void copy_cube_to_rect(const Rect2 &p_rect);
|
void copy_cube_to_rect(const Rect2 &p_rect);
|
||||||
void copy_cube_to_panorama(float p_mip_level);
|
void copy_cube_to_panorama(float p_mip_level);
|
||||||
void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region);
|
void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region);
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* glow.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifdef GLES3_ENABLED
|
||||||
|
|
||||||
|
#include "glow.h"
|
||||||
|
|
||||||
|
using namespace GLES3;
|
||||||
|
|
||||||
|
Glow *Glow::singleton = nullptr;
|
||||||
|
|
||||||
|
Glow *Glow::get_singleton() {
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
Glow::Glow() {
|
||||||
|
singleton = this;
|
||||||
|
|
||||||
|
glow.shader.initialize();
|
||||||
|
glow.shader_version = glow.shader.version_create();
|
||||||
|
|
||||||
|
{ // Screen Triangle.
|
||||||
|
glGenBuffers(1, &screen_triangle);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, screen_triangle);
|
||||||
|
|
||||||
|
const float qv[6] = {
|
||||||
|
-1.0f,
|
||||||
|
-1.0f,
|
||||||
|
3.0f,
|
||||||
|
-1.0f,
|
||||||
|
-1.0f,
|
||||||
|
3.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, qv, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &screen_triangle_array);
|
||||||
|
glBindVertexArray(screen_triangle_array);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, screen_triangle);
|
||||||
|
glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, nullptr);
|
||||||
|
glEnableVertexAttribArray(RS::ARRAY_VERTEX);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Glow::~Glow() {
|
||||||
|
glDeleteBuffers(1, &screen_triangle);
|
||||||
|
glDeleteVertexArrays(1, &screen_triangle_array);
|
||||||
|
|
||||||
|
glow.shader.version_free(glow.shader_version);
|
||||||
|
|
||||||
|
singleton = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Glow::_draw_screen_triangle() {
|
||||||
|
glBindVertexArray(screen_triangle_array);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Glow::process_glow(GLuint p_source_color, Size2i p_size, const Glow::GLOWLEVEL *p_glow_buffers, uint32_t p_view, bool p_use_multiview) {
|
||||||
|
ERR_FAIL_COND(p_source_color == 0);
|
||||||
|
ERR_FAIL_COND(p_glow_buffers[3].color == 0);
|
||||||
|
|
||||||
|
// Reset some OpenGL state...
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
|
||||||
|
// Start with our filter pass
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, p_glow_buffers[0].fbo);
|
||||||
|
glViewport(0, 0, p_glow_buffers[0].size.x, p_glow_buffers[0].size.y);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(p_use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D, p_source_color);
|
||||||
|
|
||||||
|
uint64_t specialization = p_use_multiview ? GlowShaderGLES3::USE_MULTIVIEW : 0;
|
||||||
|
bool success = glow.shader.version_bind_shader(glow.shader_version, GlowShaderGLES3::MODE_FILTER, specialization);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::PIXEL_SIZE, 1.0 / p_glow_buffers[0].size.x, 1.0 / p_glow_buffers[0].size.y, glow.shader_version, GlowShaderGLES3::MODE_FILTER, specialization);
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::VIEW, float(p_view), glow.shader_version, GlowShaderGLES3::MODE_FILTER, specialization);
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::LUMINANCE_MULTIPLIER, luminance_multiplier, glow.shader_version, GlowShaderGLES3::MODE_FILTER, specialization);
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::GLOW_BLOOM, glow_bloom, glow.shader_version, GlowShaderGLES3::MODE_FILTER, specialization);
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::GLOW_HDR_THRESHOLD, glow_hdr_bleed_threshold, glow.shader_version, GlowShaderGLES3::MODE_FILTER, specialization);
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::GLOW_HDR_SCALE, glow_hdr_bleed_scale, glow.shader_version, GlowShaderGLES3::MODE_FILTER, specialization);
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::GLOW_LUMINANCE_CAP, glow_hdr_luminance_cap, glow.shader_version, GlowShaderGLES3::MODE_FILTER, specialization);
|
||||||
|
|
||||||
|
_draw_screen_triangle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with downsampling
|
||||||
|
{
|
||||||
|
bool success = glow.shader.version_bind_shader(glow.shader_version, GlowShaderGLES3::MODE_DOWNSAMPLE, 0);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < 4; i++) {
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, p_glow_buffers[i].fbo);
|
||||||
|
glViewport(0, 0, p_glow_buffers[i].size.x, p_glow_buffers[i].size.y);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, p_glow_buffers[i - 1].color);
|
||||||
|
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::PIXEL_SIZE, 1.0 / p_glow_buffers[i].size.x, 1.0 / p_glow_buffers[i].size.y, glow.shader_version, GlowShaderGLES3::MODE_DOWNSAMPLE);
|
||||||
|
|
||||||
|
_draw_screen_triangle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now upsample
|
||||||
|
{
|
||||||
|
bool success = glow.shader.version_bind_shader(glow.shader_version, GlowShaderGLES3::MODE_UPSAMPLE, 0);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 2; i >= 0; i--) {
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, p_glow_buffers[i].fbo);
|
||||||
|
glViewport(0, 0, p_glow_buffers[i].size.x, p_glow_buffers[i].size.y);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, p_glow_buffers[i + 1].color);
|
||||||
|
|
||||||
|
glow.shader.version_set_uniform(GlowShaderGLES3::PIXEL_SIZE, 1.0 / p_glow_buffers[i].size.x, 1.0 / p_glow_buffers[i].size.y, glow.shader_version, GlowShaderGLES3::MODE_UPSAMPLE);
|
||||||
|
|
||||||
|
_draw_screen_triangle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glUseProgram(0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GLES3_ENABLED
|
|
@ -0,0 +1,89 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* glow.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef GLOW_GLES3_H
|
||||||
|
#define GLOW_GLES3_H
|
||||||
|
|
||||||
|
#ifdef GLES3_ENABLED
|
||||||
|
|
||||||
|
#include "drivers/gles3/shaders/effects/glow.glsl.gen.h"
|
||||||
|
|
||||||
|
namespace GLES3 {
|
||||||
|
|
||||||
|
class Glow {
|
||||||
|
private:
|
||||||
|
static Glow *singleton;
|
||||||
|
|
||||||
|
struct GLOW {
|
||||||
|
GlowShaderGLES3 shader;
|
||||||
|
RID shader_version;
|
||||||
|
} glow;
|
||||||
|
|
||||||
|
float luminance_multiplier = 1.0;
|
||||||
|
|
||||||
|
float glow_intensity = 1.0;
|
||||||
|
float glow_bloom = 0.0;
|
||||||
|
float glow_hdr_bleed_threshold = 1.0;
|
||||||
|
float glow_hdr_bleed_scale = 2.0;
|
||||||
|
float glow_hdr_luminance_cap = 12.0;
|
||||||
|
|
||||||
|
// Use for full-screen effects. Slightly more efficient than screen_quad as this eliminates pixel overdraw along the diagonal.
|
||||||
|
GLuint screen_triangle = 0;
|
||||||
|
GLuint screen_triangle_array = 0;
|
||||||
|
|
||||||
|
void _draw_screen_triangle();
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct GLOWLEVEL {
|
||||||
|
Size2i size;
|
||||||
|
GLuint color = 0;
|
||||||
|
GLuint fbo = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Glow *get_singleton();
|
||||||
|
|
||||||
|
Glow();
|
||||||
|
~Glow();
|
||||||
|
|
||||||
|
void set_intensity(float p_value) { glow_intensity = p_value; }
|
||||||
|
void set_luminance_multiplier(float p_luminance_multiplier) { luminance_multiplier = p_luminance_multiplier; }
|
||||||
|
void set_glow_bloom(float p_bloom) { glow_bloom = p_bloom; }
|
||||||
|
void set_glow_hdr_bleed_threshold(float p_threshold) { glow_hdr_bleed_threshold = p_threshold; }
|
||||||
|
void set_glow_hdr_bleed_scale(float p_scale) { glow_hdr_bleed_scale = p_scale; }
|
||||||
|
void set_glow_hdr_luminance_cap(float p_cap) { glow_hdr_luminance_cap = p_cap; }
|
||||||
|
|
||||||
|
void process_glow(GLuint p_source_color, Size2i p_size, const GLOWLEVEL *p_glow_buffers, uint32_t p_view = 0, bool p_use_multiview = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
} //namespace GLES3
|
||||||
|
|
||||||
|
#endif // GLES3_ENABLED
|
||||||
|
|
||||||
|
#endif // GLOW_GLES3_H
|
|
@ -0,0 +1,152 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* post_effects.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifdef GLES3_ENABLED
|
||||||
|
|
||||||
|
#include "post_effects.h"
|
||||||
|
|
||||||
|
using namespace GLES3;
|
||||||
|
|
||||||
|
PostEffects *PostEffects::singleton = nullptr;
|
||||||
|
|
||||||
|
PostEffects *PostEffects::get_singleton() {
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
PostEffects::PostEffects() {
|
||||||
|
singleton = this;
|
||||||
|
|
||||||
|
post.shader.initialize();
|
||||||
|
post.shader_version = post.shader.version_create();
|
||||||
|
post.shader.version_bind_shader(post.shader_version, PostShaderGLES3::MODE_DEFAULT);
|
||||||
|
|
||||||
|
{ // Screen Triangle.
|
||||||
|
glGenBuffers(1, &screen_triangle);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, screen_triangle);
|
||||||
|
|
||||||
|
const float qv[6] = {
|
||||||
|
-1.0f,
|
||||||
|
-1.0f,
|
||||||
|
3.0f,
|
||||||
|
-1.0f,
|
||||||
|
-1.0f,
|
||||||
|
3.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, qv, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &screen_triangle_array);
|
||||||
|
glBindVertexArray(screen_triangle_array);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, screen_triangle);
|
||||||
|
glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, nullptr);
|
||||||
|
glEnableVertexAttribArray(RS::ARRAY_VERTEX);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PostEffects::~PostEffects() {
|
||||||
|
singleton = nullptr;
|
||||||
|
glDeleteBuffers(1, &screen_triangle);
|
||||||
|
glDeleteVertexArrays(1, &screen_triangle_array);
|
||||||
|
post.shader.version_free(post.shader_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostEffects::_draw_screen_triangle() {
|
||||||
|
glBindVertexArray(screen_triangle_array);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostEffects::post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, uint32_t p_view, bool p_use_multiview) {
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, p_dest_framebuffer);
|
||||||
|
glViewport(0, 0, p_dest_size.x, p_dest_size.y);
|
||||||
|
|
||||||
|
PostShaderGLES3::ShaderVariant mode = PostShaderGLES3::MODE_DEFAULT;
|
||||||
|
uint64_t flags = 0;
|
||||||
|
if (p_use_multiview) {
|
||||||
|
flags |= PostShaderGLES3::USE_MULTIVIEW;
|
||||||
|
}
|
||||||
|
if (p_glow_buffers != nullptr) {
|
||||||
|
flags |= PostShaderGLES3::USE_GLOW;
|
||||||
|
}
|
||||||
|
if (p_luminance_multiplier != 1.0) {
|
||||||
|
flags |= PostShaderGLES3::USE_LUMINANCE_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = post.shader.version_bind_shader(post.shader_version, mode, flags);
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum texture_target = p_use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(texture_target, p_source_color);
|
||||||
|
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
if (p_glow_buffers != nullptr) {
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, p_glow_buffers[0].color);
|
||||||
|
|
||||||
|
post.shader.version_set_uniform(PostShaderGLES3::PIXEL_SIZE, 1.0 / p_source_size.x, 1.0 / p_source_size.y, post.shader_version, mode, flags);
|
||||||
|
post.shader.version_set_uniform(PostShaderGLES3::GLOW_INTENSITY, p_glow_intensity, post.shader_version, mode, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
post.shader.version_set_uniform(PostShaderGLES3::VIEW, float(p_view), post.shader_version, mode, flags);
|
||||||
|
post.shader.version_set_uniform(PostShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, post.shader_version, mode, flags);
|
||||||
|
|
||||||
|
_draw_screen_triangle();
|
||||||
|
|
||||||
|
// Reset state
|
||||||
|
if (p_glow_buffers != nullptr) {
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return back to nearest
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glBindTexture(texture_target, 0);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glUseProgram(0);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GLES3_ENABLED
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* post_effects.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef POST_EFFECTS_GLES3_H
|
||||||
|
#define POST_EFFECTS_GLES3_H
|
||||||
|
|
||||||
|
#ifdef GLES3_ENABLED
|
||||||
|
|
||||||
|
#include "drivers/gles3/shaders/effects/post.glsl.gen.h"
|
||||||
|
#include "glow.h"
|
||||||
|
|
||||||
|
namespace GLES3 {
|
||||||
|
|
||||||
|
class PostEffects {
|
||||||
|
private:
|
||||||
|
struct Post {
|
||||||
|
PostShaderGLES3 shader;
|
||||||
|
RID shader_version;
|
||||||
|
} post;
|
||||||
|
|
||||||
|
static PostEffects *singleton;
|
||||||
|
|
||||||
|
// Use for full-screen effects. Slightly more efficient than screen_quad as this eliminates pixel overdraw along the diagonal.
|
||||||
|
GLuint screen_triangle = 0;
|
||||||
|
GLuint screen_triangle_array = 0;
|
||||||
|
|
||||||
|
void _draw_screen_triangle();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static PostEffects *get_singleton();
|
||||||
|
|
||||||
|
PostEffects();
|
||||||
|
~PostEffects();
|
||||||
|
|
||||||
|
void post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, uint32_t p_view = 0, bool p_use_multiview = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
} //namespace GLES3
|
||||||
|
|
||||||
|
#endif // GLES3_ENABLED
|
||||||
|
|
||||||
|
#endif // POST_EFFECTS_GLES3_H
|
|
@ -201,6 +201,8 @@ void RasterizerGLES3::finalize() {
|
||||||
memdelete(canvas);
|
memdelete(canvas);
|
||||||
memdelete(gi);
|
memdelete(gi);
|
||||||
memdelete(fog);
|
memdelete(fog);
|
||||||
|
memdelete(post_effects);
|
||||||
|
memdelete(glow);
|
||||||
memdelete(copy_effects);
|
memdelete(copy_effects);
|
||||||
memdelete(light_storage);
|
memdelete(light_storage);
|
||||||
memdelete(particles_storage);
|
memdelete(particles_storage);
|
||||||
|
@ -347,6 +349,8 @@ RasterizerGLES3::RasterizerGLES3() {
|
||||||
particles_storage = memnew(GLES3::ParticlesStorage);
|
particles_storage = memnew(GLES3::ParticlesStorage);
|
||||||
light_storage = memnew(GLES3::LightStorage);
|
light_storage = memnew(GLES3::LightStorage);
|
||||||
copy_effects = memnew(GLES3::CopyEffects);
|
copy_effects = memnew(GLES3::CopyEffects);
|
||||||
|
glow = memnew(GLES3::Glow);
|
||||||
|
post_effects = memnew(GLES3::PostEffects);
|
||||||
gi = memnew(GLES3::GI);
|
gi = memnew(GLES3::GI);
|
||||||
fog = memnew(GLES3::Fog);
|
fog = memnew(GLES3::Fog);
|
||||||
canvas = memnew(RasterizerCanvasGLES3());
|
canvas = memnew(RasterizerCanvasGLES3());
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#ifdef GLES3_ENABLED
|
#ifdef GLES3_ENABLED
|
||||||
|
|
||||||
#include "effects/copy_effects.h"
|
#include "effects/copy_effects.h"
|
||||||
|
#include "effects/glow.h"
|
||||||
|
#include "effects/post_effects.h"
|
||||||
#include "environment/fog.h"
|
#include "environment/fog.h"
|
||||||
#include "environment/gi.h"
|
#include "environment/gi.h"
|
||||||
#include "rasterizer_canvas_gles3.h"
|
#include "rasterizer_canvas_gles3.h"
|
||||||
|
@ -67,6 +69,8 @@ protected:
|
||||||
GLES3::GI *gi = nullptr;
|
GLES3::GI *gi = nullptr;
|
||||||
GLES3::Fog *fog = nullptr;
|
GLES3::Fog *fog = nullptr;
|
||||||
GLES3::CopyEffects *copy_effects = nullptr;
|
GLES3::CopyEffects *copy_effects = nullptr;
|
||||||
|
GLES3::Glow *glow = nullptr;
|
||||||
|
GLES3::PostEffects *post_effects = nullptr;
|
||||||
RasterizerCanvasGLES3 *canvas = nullptr;
|
RasterizerCanvasGLES3 *canvas = nullptr;
|
||||||
RasterizerSceneGLES3 *scene = nullptr;
|
RasterizerSceneGLES3 *scene = nullptr;
|
||||||
static RasterizerGLES3 *singleton;
|
static RasterizerGLES3 *singleton;
|
||||||
|
|
|
@ -764,7 +764,7 @@ void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, cons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y) {
|
void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_sky_energy_multiplier, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y, bool p_apply_color_adjustments_in_post) {
|
||||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||||
ERR_FAIL_COND(p_env.is_null());
|
ERR_FAIL_COND(p_env.is_null());
|
||||||
|
|
||||||
|
@ -778,6 +778,10 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
|
||||||
if (p_flip_y) {
|
if (p_flip_y) {
|
||||||
spec_constants |= SkyShaderGLES3::USE_INVERTED_Y;
|
spec_constants |= SkyShaderGLES3::USE_INVERTED_Y;
|
||||||
}
|
}
|
||||||
|
if (!p_apply_color_adjustments_in_post) {
|
||||||
|
spec_constants |= SkyShaderGLES3::APPLY_TONEMAPPING;
|
||||||
|
// TODO add BCS and color corrections once supported.
|
||||||
|
}
|
||||||
|
|
||||||
RS::EnvironmentBG background = environment_get_background(p_env);
|
RS::EnvironmentBG background = environment_get_background(p_env);
|
||||||
|
|
||||||
|
@ -832,6 +836,7 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
|
||||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||||
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::SKY_ENERGY_MULTIPLIER, p_sky_energy_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||||
|
|
||||||
if (p_use_multiview) {
|
if (p_use_multiview) {
|
||||||
|
@ -843,7 +848,7 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier) {
|
void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_sky_energy_multiplier) {
|
||||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||||
ERR_FAIL_COND(p_env.is_null());
|
ERR_FAIL_COND(p_env.is_null());
|
||||||
|
|
||||||
|
@ -939,20 +944,17 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
|
||||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
||||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
||||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.columns[2][0], cm.columns[0][0], cm.columns[2][1], cm.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.columns[2][0], cm.columns[0][0], cm.columns[2][1], cm.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
||||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::SKY_ENERGY_MULTIPLIER, p_sky_energy_multiplier, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
||||||
|
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, 1.0, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
|
||||||
|
|
||||||
glBindVertexArray(sky_globals.screen_triangle_array);
|
glBindVertexArray(sky_globals.screen_triangle_array);
|
||||||
|
|
||||||
glViewport(0, 0, sky->radiance_size, sky->radiance_size);
|
glViewport(0, 0, sky->radiance_size, sky->radiance_size);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, sky->radiance_framebuffer);
|
glBindFramebuffer(GL_FRAMEBUFFER, sky->radiance_framebuffer);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
scene_state.reset_gl_state();
|
||||||
glDepthMask(GL_FALSE);
|
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||||
glDisable(GL_DEPTH_TEST);
|
scene_state.enable_gl_blend(false);
|
||||||
scene_state.current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_DISABLED;
|
|
||||||
glDisable(GL_SCISSOR_TEST);
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
|
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
|
||||||
|
@ -969,17 +971,13 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
|
||||||
_filter_sky_radiance(sky, 0); //Just copy over the first mipmap
|
_filter_sky_radiance(sky, 0); //Just copy over the first mipmap
|
||||||
}
|
}
|
||||||
sky->processing_layer = 1;
|
sky->processing_layer = 1;
|
||||||
sky->baked_exposure = p_luminance_multiplier;
|
sky->baked_exposure = p_sky_energy_multiplier;
|
||||||
sky->reflection_dirty = false;
|
sky->reflection_dirty = false;
|
||||||
} else {
|
} else {
|
||||||
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
|
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
|
||||||
glDisable(GL_BLEND);
|
scene_state.reset_gl_state();
|
||||||
glDepthMask(GL_FALSE);
|
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||||
glDisable(GL_DEPTH_TEST);
|
scene_state.enable_gl_blend(false);
|
||||||
scene_state.current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_DISABLED;
|
|
||||||
glDisable(GL_SCISSOR_TEST);
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
|
||||||
|
|
||||||
_filter_sky_radiance(sky, sky->processing_layer);
|
_filter_sky_radiance(sky, sky->processing_layer);
|
||||||
sky->processing_layer++;
|
sky->processing_layer++;
|
||||||
|
@ -1584,6 +1582,8 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
|
||||||
scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
|
scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
|
||||||
scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y;
|
scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y;
|
||||||
|
|
||||||
|
scene_state.ubo.luminance_multiplier = p_render_data->luminance_multiplier;
|
||||||
|
|
||||||
scene_state.ubo.shadow_bias = p_shadow_bias;
|
scene_state.ubo.shadow_bias = p_shadow_bias;
|
||||||
scene_state.ubo.pancake_shadows = p_pancake_shadows;
|
scene_state.ubo.pancake_shadows = p_pancake_shadows;
|
||||||
|
|
||||||
|
@ -2271,14 +2271,10 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
|
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
scene_state.reset_gl_state();
|
||||||
glDepthMask(GL_TRUE);
|
scene_state.enable_gl_depth_test(true);
|
||||||
glEnable(GL_DEPTH_TEST);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
|
||||||
glCullFace(GL_BACK);
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
|
||||||
|
|
||||||
glColorMask(0, 0, 0, 0);
|
glColorMask(0, 0, 0, 0);
|
||||||
glDrawBuffers(0, nullptr);
|
glDrawBuffers(0, nullptr);
|
||||||
|
@ -2303,8 +2299,8 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
|
||||||
_render_list_template<PASS_MODE_SHADOW>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_SECONDARY].elements.size());
|
_render_list_template<PASS_MODE_SHADOW>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_SECONDARY].elements.size());
|
||||||
|
|
||||||
glColorMask(1, 1, 1, 1);
|
glColorMask(1, 1, 1, 1);
|
||||||
glDisable(GL_DEPTH_TEST);
|
scene_state.enable_gl_depth_test(false);
|
||||||
glDepthMask(GL_FALSE);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
@ -2315,15 +2311,32 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
GLES3::Config *config = GLES3::Config::get_singleton();
|
GLES3::Config *config = GLES3::Config::get_singleton();
|
||||||
RENDER_TIMESTAMP("Setup 3D Scene");
|
RENDER_TIMESTAMP("Setup 3D Scene");
|
||||||
|
|
||||||
|
bool apply_color_adjustments_in_post = false;
|
||||||
|
|
||||||
Ref<RenderSceneBuffersGLES3> rb;
|
Ref<RenderSceneBuffersGLES3> rb;
|
||||||
if (p_render_buffers.is_valid()) {
|
if (p_render_buffers.is_valid()) {
|
||||||
rb = p_render_buffers;
|
rb = p_render_buffers;
|
||||||
ERR_FAIL_COND(rb.is_null());
|
ERR_FAIL_COND(rb.is_null());
|
||||||
|
|
||||||
|
if (rb->get_scaling_3d_mode() != RS::VIEWPORT_SCALING_3D_MODE_OFF) {
|
||||||
|
// If we're scaling, we apply tonemapping etc. in post, so disable it during rendering
|
||||||
|
apply_color_adjustments_in_post = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES3::RenderTarget *rt = texture_storage->get_render_target(rb->render_target);
|
GLES3::RenderTarget *rt = texture_storage->get_render_target(rb->render_target);
|
||||||
ERR_FAIL_NULL(rt);
|
ERR_FAIL_NULL(rt);
|
||||||
|
|
||||||
|
bool glow_enabled = false;
|
||||||
|
if (p_environment.is_valid() && rb.is_valid()) {
|
||||||
|
glow_enabled = environment_get_glow_enabled(p_environment);
|
||||||
|
rb->set_glow_enabled(glow_enabled); // ensure our intermediate buffer is available if glow is enabled
|
||||||
|
if (glow_enabled) {
|
||||||
|
// If glow is enabled, we apply tonemapping etc. in post, so disable it during rendering
|
||||||
|
apply_color_adjustments_in_post = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Assign render data
|
// Assign render data
|
||||||
// Use the format from rendererRD
|
// Use the format from rendererRD
|
||||||
RenderDataGLES3 render_data;
|
RenderDataGLES3 render_data;
|
||||||
|
@ -2359,6 +2372,13 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
// this should be the same for all cameras..
|
// this should be the same for all cameras..
|
||||||
render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
|
render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
|
||||||
|
|
||||||
|
if (rt->color_type == GL_UNSIGNED_INT_2_10_10_10_REV && glow_enabled) {
|
||||||
|
// As our output is in sRGB and we're using 10bit color space, we can fake a little HDR to do glow...
|
||||||
|
render_data.luminance_multiplier = 0.25;
|
||||||
|
} else {
|
||||||
|
render_data.luminance_multiplier = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
|
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
|
||||||
render_data.screen_mesh_lod_threshold = 0.0;
|
render_data.screen_mesh_lod_threshold = 0.0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2519,9 +2539,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
glViewport(0, 0, rb->internal_size.x, rb->internal_size.y);
|
glViewport(0, 0, rb->internal_size.x, rb->internal_size.y);
|
||||||
|
|
||||||
glCullFace(GL_BACK);
|
scene_state.reset_gl_state();
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
|
||||||
|
|
||||||
// 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;
|
||||||
|
@ -2533,11 +2551,11 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
RENDER_TIMESTAMP("Depth Prepass");
|
RENDER_TIMESTAMP("Depth Prepass");
|
||||||
//pre z pass
|
//pre z pass
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
scene_state.enable_gl_depth_test(true);
|
||||||
glDepthMask(GL_TRUE);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glEnable(GL_DEPTH_TEST);
|
scene_state.enable_gl_blend(false);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
scene_state.enable_gl_scissor_test(false);
|
||||||
|
|
||||||
glColorMask(0, 0, 0, 0);
|
glColorMask(0, 0, 0, 0);
|
||||||
RasterizerGLES3::clear_depth(1.0);
|
RasterizerGLES3::clear_depth(1.0);
|
||||||
|
@ -2560,21 +2578,19 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
}
|
}
|
||||||
|
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
|
|
||||||
if (render_data.transparent_bg) {
|
if (render_data.transparent_bg) {
|
||||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glEnable(GL_BLEND);
|
scene_state.enable_gl_blend(true);
|
||||||
} else {
|
} else {
|
||||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||||
glDisable(GL_BLEND);
|
scene_state.enable_gl_blend(false);
|
||||||
}
|
}
|
||||||
scene_state.current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
scene_state.current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
scene_state.enable_gl_scissor_test(false);
|
||||||
|
scene_state.enable_gl_depth_test(true);
|
||||||
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
glDepthMask(GL_TRUE);
|
|
||||||
scene_state.current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_ENABLED;
|
|
||||||
scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_ALWAYS;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
GLuint db = GL_COLOR_ATTACHMENT0;
|
GLuint db = GL_COLOR_ATTACHMENT0;
|
||||||
|
@ -2589,7 +2605,19 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
if (!keep_color) {
|
if (!keep_color) {
|
||||||
clear_color.a = render_data.transparent_bg ? 0.0f : 1.0f;
|
clear_color.a = render_data.transparent_bg ? 0.0f : 1.0f;
|
||||||
glClearBufferfv(GL_COLOR, 0, clear_color.components);
|
glClearBufferfv(GL_COLOR, 0, clear_color.components);
|
||||||
|
} else if (fbo != rt->fbo) {
|
||||||
|
// Need to copy our current contents to our intermediate/MSAA buffer
|
||||||
|
GLES3::CopyEffects *copy_effects = GLES3::CopyEffects::get_singleton();
|
||||||
|
|
||||||
|
scene_state.enable_gl_depth_test(false);
|
||||||
|
scene_state.enable_gl_depth_draw(false);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(rt->view_count > 1 ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D, rt->color);
|
||||||
|
|
||||||
|
copy_effects->copy_screen(render_data.luminance_multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDER_TIMESTAMP("Render Opaque Pass");
|
RENDER_TIMESTAMP("Render Opaque Pass");
|
||||||
uint64_t spec_constant_base_flags = 0;
|
uint64_t spec_constant_base_flags = 0;
|
||||||
|
|
||||||
|
@ -2606,26 +2634,28 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
if (render_data.environment.is_valid() && environment_get_fog_mode(render_data.environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) {
|
if (render_data.environment.is_valid() && environment_get_fog_mode(render_data.environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) {
|
||||||
spec_constant_base_flags |= SceneShaderGLES3::USE_DEPTH_FOG;
|
spec_constant_base_flags |= SceneShaderGLES3::USE_DEPTH_FOG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!apply_color_adjustments_in_post) {
|
||||||
|
spec_constant_base_flags |= SceneShaderGLES3::APPLY_TONEMAPPING;
|
||||||
|
|
||||||
|
// TODO add BCS and Color corrections here once supported.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Render Opaque Objects.
|
// Render Opaque Objects.
|
||||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe);
|
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe);
|
||||||
|
|
||||||
_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());
|
||||||
|
|
||||||
glDepthMask(GL_FALSE);
|
scene_state.enable_gl_depth_draw(false);
|
||||||
scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED;
|
|
||||||
|
|
||||||
if (draw_sky) {
|
if (draw_sky) {
|
||||||
RENDER_TIMESTAMP("Render Sky");
|
RENDER_TIMESTAMP("Render Sky");
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
scene_state.enable_gl_depth_test(true);
|
||||||
glDisable(GL_BLEND);
|
scene_state.enable_gl_blend(false);
|
||||||
glEnable(GL_CULL_FACE);
|
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_BACK);
|
||||||
glCullFace(GL_BACK);
|
|
||||||
scene_state.current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_ENABLED;
|
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
|
||||||
|
|
||||||
_draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier, p_camera_data->view_count > 1, flip_y);
|
_draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier, render_data.luminance_multiplier, p_camera_data->view_count > 1, flip_y, apply_color_adjustments_in_post);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
|
if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
|
||||||
|
@ -2674,7 +2704,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDER_TIMESTAMP("Render 3D Transparent Pass");
|
RENDER_TIMESTAMP("Render 3D Transparent Pass");
|
||||||
glEnable(GL_BLEND);
|
scene_state.enable_gl_blend(true);
|
||||||
|
|
||||||
//Render transparent pass
|
//Render transparent pass
|
||||||
RenderListParameters render_list_params_alpha(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe);
|
RenderListParameters render_list_params_alpha(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe);
|
||||||
|
@ -2689,7 +2719,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
if (rb.is_valid()) {
|
if (rb.is_valid()) {
|
||||||
_render_buffers_debug_draw(rb, p_shadow_atlas, fbo);
|
_render_buffers_debug_draw(rb, p_shadow_atlas, fbo);
|
||||||
}
|
}
|
||||||
glDisable(GL_BLEND);
|
|
||||||
|
// Reset stuff that may trip up the next process.
|
||||||
|
scene_state.reset_gl_state();
|
||||||
|
glUseProgram(0);
|
||||||
|
|
||||||
_render_post_processing(&render_data);
|
_render_post_processing(&render_data);
|
||||||
|
|
||||||
|
@ -2700,6 +2733,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||||
|
|
||||||
void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_render_data) {
|
void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_render_data) {
|
||||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
|
GLES3::Glow *glow = GLES3::Glow::get_singleton();
|
||||||
|
GLES3::PostEffects *post_effects = GLES3::PostEffects::get_singleton();
|
||||||
|
|
||||||
Ref<RenderSceneBuffersGLES3> rb = p_render_data->render_buffers;
|
Ref<RenderSceneBuffersGLES3> rb = p_render_data->render_buffers;
|
||||||
ERR_FAIL_COND(rb.is_null());
|
ERR_FAIL_COND(rb.is_null());
|
||||||
|
|
||||||
|
@ -2714,6 +2750,26 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||||
GLuint fbo_int = rb->get_internal_fbo();
|
GLuint fbo_int = rb->get_internal_fbo();
|
||||||
GLuint fbo_rt = texture_storage->render_target_get_fbo(render_target); // TODO if MSAA 2D is enabled and we're not using rt_msaa, get 2D render target here.
|
GLuint fbo_rt = texture_storage->render_target_get_fbo(render_target); // TODO if MSAA 2D is enabled and we're not using rt_msaa, get 2D render target here.
|
||||||
|
|
||||||
|
// Check if we have glow enabled and if so, check if our buffers were allocated
|
||||||
|
bool glow_enabled = false;
|
||||||
|
float glow_intensity = 1.0;
|
||||||
|
float glow_bloom = 0.0;
|
||||||
|
float glow_hdr_bleed_threshold = 1.0;
|
||||||
|
float glow_hdr_bleed_scale = 2.0;
|
||||||
|
float glow_hdr_luminance_cap = 12.0;
|
||||||
|
if (p_render_data->environment.is_valid()) {
|
||||||
|
glow_enabled = environment_get_glow_enabled(p_render_data->environment);
|
||||||
|
glow_intensity = environment_get_glow_intensity(p_render_data->environment);
|
||||||
|
glow_bloom = environment_get_glow_bloom(p_render_data->environment);
|
||||||
|
glow_hdr_bleed_threshold = environment_get_glow_hdr_bleed_threshold(p_render_data->environment);
|
||||||
|
glow_hdr_bleed_scale = environment_get_glow_hdr_bleed_scale(p_render_data->environment);
|
||||||
|
glow_hdr_luminance_cap = environment_get_glow_hdr_luminance_cap(p_render_data->environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glow_enabled) {
|
||||||
|
rb->check_glow_buffers();
|
||||||
|
}
|
||||||
|
|
||||||
if (view_count == 1) {
|
if (view_count == 1) {
|
||||||
// Resolve if needed.
|
// Resolve if needed.
|
||||||
if (fbo_msaa_3d != 0 && msaa3d_needs_resolve) {
|
if (fbo_msaa_3d != 0 && msaa3d_needs_resolve) {
|
||||||
|
@ -2729,23 +2785,41 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||||
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_NEAREST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rendered to intermediate buffer, must copy to our render target
|
||||||
if (fbo_int != 0) {
|
if (fbo_int != 0) {
|
||||||
// TODO If we have glow or other post processing, we upscale only depth here, post processing will also do scaling.
|
// Apply glow/bloom if requested? then populate our glow buffers
|
||||||
|
GLuint color = fbo_int != 0 ? rb->get_internal_color() : texture_storage->render_target_get_color(render_target);
|
||||||
|
const GLES3::Glow::GLOWLEVEL *glow_buffers = nullptr;
|
||||||
|
if (glow_enabled) {
|
||||||
|
glow_buffers = rb->get_glow_buffers();
|
||||||
|
|
||||||
|
glow->set_luminance_multiplier(p_render_data->luminance_multiplier);
|
||||||
|
|
||||||
|
glow->set_intensity(glow_intensity);
|
||||||
|
glow->set_glow_bloom(glow_bloom);
|
||||||
|
glow->set_glow_hdr_bleed_threshold(glow_hdr_bleed_threshold);
|
||||||
|
glow->set_glow_hdr_bleed_scale(glow_hdr_bleed_scale);
|
||||||
|
glow->set_glow_hdr_luminance_cap(glow_hdr_luminance_cap);
|
||||||
|
|
||||||
|
glow->process_glow(color, internal_size, glow_buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy color buffer
|
||||||
|
post_effects->post_copy(fbo_rt, target_size, color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity);
|
||||||
|
|
||||||
|
// 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_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
||||||
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_NEAREST);
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
|
||||||
} else if ((fbo_msaa_3d != 0 && msaa3d_needs_resolve) || (fbo_int != 0)) {
|
} else if ((fbo_msaa_3d != 0 && msaa3d_needs_resolve) || (fbo_int != 0)) {
|
||||||
// TODO investigate if it's smarter to cache these FBOs
|
// TODO investigate if it's smarter to cache these FBOs
|
||||||
GLuint fbos[2]; // read and write
|
GLuint fbos[3]; // read, write and post
|
||||||
glGenFramebuffers(2, fbos);
|
glGenFramebuffers(3, fbos);
|
||||||
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
|
|
||||||
|
|
||||||
|
// Resolve if needed.
|
||||||
if (fbo_msaa_3d != 0 && msaa3d_needs_resolve) {
|
if (fbo_msaa_3d != 0 && msaa3d_needs_resolve) {
|
||||||
GLuint read_color = rb->get_msaa3d_color();
|
GLuint read_color = rb->get_msaa3d_color();
|
||||||
GLuint read_depth = rb->get_msaa3d_depth();
|
GLuint read_depth = rb->get_msaa3d_depth();
|
||||||
|
@ -2760,6 +2834,9 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||||
write_depth = texture_storage->render_target_get_depth(render_target);
|
write_depth = texture_storage->render_target_get_depth(render_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
|
||||||
|
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_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_ATTACHMENT, read_depth, 0, v);
|
||||||
|
@ -2769,25 +2846,53 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rendered to intermediate buffer, must copy to our render target
|
||||||
if (fbo_int != 0) {
|
if (fbo_int != 0) {
|
||||||
GLuint read_color = rb->get_internal_color();
|
// Apply glow/bloom if requested? then populate our glow buffers
|
||||||
GLuint read_depth = rb->get_internal_depth();
|
const GLES3::Glow::GLOWLEVEL *glow_buffers = nullptr;
|
||||||
|
GLuint source_color = fbo_int != 0 ? rb->get_internal_color() : texture_storage->render_target_get_color(render_target);
|
||||||
|
|
||||||
|
if (glow_enabled) {
|
||||||
|
glow_buffers = rb->get_glow_buffers();
|
||||||
|
|
||||||
|
glow->set_luminance_multiplier(p_render_data->luminance_multiplier);
|
||||||
|
|
||||||
|
glow->set_intensity(glow_intensity);
|
||||||
|
glow->set_glow_bloom(glow_bloom);
|
||||||
|
glow->set_glow_hdr_bleed_threshold(glow_hdr_bleed_threshold);
|
||||||
|
glow->set_glow_hdr_bleed_scale(glow_hdr_bleed_scale);
|
||||||
|
glow->set_glow_hdr_luminance_cap(glow_hdr_luminance_cap);
|
||||||
|
}
|
||||||
|
|
||||||
GLuint write_color = texture_storage->render_target_get_color(render_target);
|
GLuint write_color = texture_storage->render_target_get_color(render_target);
|
||||||
GLuint write_depth = texture_storage->render_target_get_depth(render_target);
|
|
||||||
|
|
||||||
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);
|
if (glow_enabled) {
|
||||||
|
glow->process_glow(source_color, internal_size, glow_buffers, v, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbos[2]);
|
||||||
|
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
|
||||||
|
post_effects->post_copy(fbos[2], target_size, source_color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity, v, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy depth
|
||||||
|
GLuint read_depth = rb->get_internal_depth();
|
||||||
|
GLuint write_depth = texture_storage->render_target_get_depth(render_target);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
|
||||||
|
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_READ_FRAMEBUFFER, GL_DEPTH_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);
|
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
|
||||||
|
|
||||||
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
||||||
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_NEAREST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
|
||||||
glDeleteFramebuffers(2, fbos);
|
glDeleteFramebuffers(3, fbos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2884,33 +2989,15 @@ 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) {
|
||||||
if (scene_state.current_depth_test != shader->depth_test) {
|
scene_state.enable_gl_depth_test(shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_ENABLED);
|
||||||
if (shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED) {
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
} else {
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
}
|
|
||||||
scene_state.current_depth_test = shader->depth_test;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (p_pass_mode != PASS_MODE_SHADOW) {
|
if constexpr (p_pass_mode != PASS_MODE_SHADOW) {
|
||||||
if (scene_state.current_depth_draw != shader->depth_draw) {
|
if (shader->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE) {
|
||||||
switch (shader->depth_draw) {
|
scene_state.enable_gl_depth_draw((p_pass_mode == PASS_MODE_COLOR && !GLES3::Config::get_singleton()->use_depth_prepass) || p_pass_mode == PASS_MODE_DEPTH);
|
||||||
case GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE: {
|
} else {
|
||||||
glDepthMask((p_pass_mode == PASS_MODE_COLOR && !GLES3::Config::get_singleton()->use_depth_prepass) ||
|
scene_state.enable_gl_depth_draw(shader->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_ALWAYS);
|
||||||
p_pass_mode == PASS_MODE_DEPTH);
|
|
||||||
} break;
|
|
||||||
case GLES3::SceneShaderData::DEPTH_DRAW_ALWAYS: {
|
|
||||||
glDepthMask(GL_TRUE);
|
|
||||||
} break;
|
|
||||||
case GLES3::SceneShaderData::DEPTH_DRAW_DISABLED: {
|
|
||||||
glDepthMask(GL_FALSE);
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_state.current_depth_draw = shader->depth_draw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool uses_additive_lighting = (inst->light_passes.size() + p_render_data->directional_shadow_count) > 0;
|
bool uses_additive_lighting = (inst->light_passes.size() + p_render_data->directional_shadow_count) > 0;
|
||||||
|
@ -2937,7 +3024,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
||||||
}
|
}
|
||||||
if (uses_additive_lighting && pass == 1 && !p_render_data->transparent_bg) {
|
if (uses_additive_lighting && pass == 1 && !p_render_data->transparent_bg) {
|
||||||
// Enable blending if in opaque pass and not already enabled.
|
// Enable blending if in opaque pass and not already enabled.
|
||||||
glEnable(GL_BLEND);
|
scene_state.enable_gl_blend(true);
|
||||||
}
|
}
|
||||||
if (pass < int32_t(inst->light_passes.size())) {
|
if (pass < int32_t(inst->light_passes.size())) {
|
||||||
RID light_instance_rid = inst->light_passes[pass].light_instance_rid;
|
RID light_instance_rid = inst->light_passes[pass].light_instance_rid;
|
||||||
|
@ -3017,18 +3104,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene_state.cull_mode != cull_mode) {
|
scene_state.set_gl_cull_mode(cull_mode);
|
||||||
if (cull_mode == GLES3::SceneShaderData::CULL_DISABLED) {
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
} else {
|
|
||||||
if (scene_state.cull_mode == GLES3::SceneShaderData::CULL_DISABLED) {
|
|
||||||
// Last time was disabled, so enable and set proper face.
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
}
|
|
||||||
glCullFace(cull_mode == GLES3::SceneShaderData::CULL_FRONT ? GL_FRONT : GL_BACK);
|
|
||||||
}
|
|
||||||
scene_state.cull_mode = cull_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
RS::PrimitiveType primitive = surf->primitive;
|
RS::PrimitiveType primitive = surf->primitive;
|
||||||
if (shader->uses_point_size) {
|
if (shader->uses_point_size) {
|
||||||
|
@ -3417,7 +3493,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
||||||
if constexpr (p_pass_mode == PASS_MODE_COLOR) {
|
if constexpr (p_pass_mode == PASS_MODE_COLOR) {
|
||||||
if (uses_additive_lighting && !p_render_data->transparent_bg) {
|
if (uses_additive_lighting && !p_render_data->transparent_bg) {
|
||||||
// Disable additive blending if enabled for additive lights.
|
// Disable additive blending if enabled for additive lights.
|
||||||
glDisable(GL_BLEND);
|
scene_state.enable_gl_blend(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3480,14 +3556,10 @@ void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider,
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
|
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
scene_state.reset_gl_state();
|
||||||
glDepthMask(GL_TRUE);
|
scene_state.enable_gl_depth_test(true);
|
||||||
glEnable(GL_DEPTH_TEST);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
|
||||||
glCullFace(GL_BACK);
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
|
||||||
|
|
||||||
glDrawBuffers(0, nullptr);
|
glDrawBuffers(0, nullptr);
|
||||||
|
|
||||||
|
@ -3530,14 +3602,10 @@ void RasterizerSceneGLES3::_render_uv2(const PagedArray<RenderGeometryInstance *
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
|
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
scene_state.reset_gl_state();
|
||||||
glDepthMask(GL_TRUE);
|
scene_state.enable_gl_depth_test(true);
|
||||||
glEnable(GL_DEPTH_TEST);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
|
||||||
glCullFace(GL_BACK);
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
|
||||||
|
|
||||||
TightLocalVector<GLenum> draw_buffers;
|
TightLocalVector<GLenum> draw_buffers;
|
||||||
draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
|
draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
|
||||||
|
@ -3629,10 +3697,9 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas_fb);
|
glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas_fb);
|
||||||
glViewport(0, 0, shadow_atlas_size, shadow_atlas_size);
|
glViewport(0, 0, shadow_atlas_size, shadow_atlas_size);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glDepthMask(GL_TRUE);
|
scene_state.enable_gl_depth_draw(true);
|
||||||
glDepthFunc(GL_ALWAYS);
|
glDepthFunc(GL_ALWAYS);
|
||||||
glDisable(GL_CULL_FACE);
|
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
|
||||||
|
|
||||||
// Loop through quadrants and copy shadows over.
|
// Loop through quadrants and copy shadows over.
|
||||||
for (int quadrant = 0; quadrant < 4; quadrant++) {
|
for (int quadrant = 0; quadrant < 4; quadrant++) {
|
||||||
|
@ -3706,8 +3773,8 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
scene_state.enable_gl_depth_test(false);
|
||||||
glDepthMask(GL_FALSE);
|
scene_state.enable_gl_depth_draw(false);
|
||||||
|
|
||||||
copy_effects->copy_to_rect(Rect2(Vector2(), Vector2(0.5, 0.5)));
|
copy_effects->copy_to_rect(Rect2(Vector2(), Vector2(0.5, 0.5)));
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
|
||||||
|
|
|
@ -127,6 +127,8 @@ struct RenderDataGLES3 {
|
||||||
uint32_t spot_light_count = 0;
|
uint32_t spot_light_count = 0;
|
||||||
uint32_t omni_light_count = 0;
|
uint32_t omni_light_count = 0;
|
||||||
|
|
||||||
|
float luminance_multiplier = 1.0;
|
||||||
|
|
||||||
RenderingMethod::RenderInfo *render_info = nullptr;
|
RenderingMethod::RenderInfo *render_info = nullptr;
|
||||||
|
|
||||||
/* Shadow data */
|
/* Shadow data */
|
||||||
|
@ -404,15 +406,14 @@ private:
|
||||||
|
|
||||||
float fog_height_density;
|
float fog_height_density;
|
||||||
float fog_depth_curve;
|
float fog_depth_curve;
|
||||||
float pad;
|
float fog_sun_scatter;
|
||||||
float fog_depth_begin;
|
float fog_depth_begin;
|
||||||
|
|
||||||
float fog_light_color[3];
|
float fog_light_color[3];
|
||||||
float fog_depth_end;
|
float fog_depth_end;
|
||||||
|
|
||||||
float fog_sun_scatter;
|
|
||||||
|
|
||||||
float shadow_bias;
|
float shadow_bias;
|
||||||
|
float luminance_multiplier;
|
||||||
uint32_t camera_visible_layers;
|
uint32_t camera_visible_layers;
|
||||||
bool pancake_shadows;
|
bool pancake_shadows;
|
||||||
};
|
};
|
||||||
|
@ -442,10 +443,85 @@ private:
|
||||||
bool used_depth_prepass = false;
|
bool used_depth_prepass = false;
|
||||||
|
|
||||||
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
||||||
GLES3::SceneShaderData::DepthDraw current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE;
|
|
||||||
GLES3::SceneShaderData::DepthTest current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_DISABLED;
|
|
||||||
GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
||||||
|
|
||||||
|
bool current_blend_enabled = false;
|
||||||
|
bool current_depth_draw_enabled = false;
|
||||||
|
bool current_depth_test_enabled = false;
|
||||||
|
bool current_scissor_test_enabled = false;
|
||||||
|
|
||||||
|
void reset_gl_state() {
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
current_blend_enabled = false;
|
||||||
|
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
current_scissor_test_enabled = false;
|
||||||
|
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
||||||
|
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
current_depth_draw_enabled = false;
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
current_depth_test_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_gl_cull_mode(GLES3::SceneShaderData::Cull p_mode) {
|
||||||
|
if (cull_mode != p_mode) {
|
||||||
|
if (p_mode == GLES3::SceneShaderData::CULL_DISABLED) {
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
} else {
|
||||||
|
if (cull_mode == GLES3::SceneShaderData::CULL_DISABLED) {
|
||||||
|
// Last time was disabled, so enable and set proper face.
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
}
|
||||||
|
glCullFace(p_mode == GLES3::SceneShaderData::CULL_FRONT ? GL_FRONT : GL_BACK);
|
||||||
|
}
|
||||||
|
cull_mode = p_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_gl_blend(bool p_enabled) {
|
||||||
|
if (current_blend_enabled != p_enabled) {
|
||||||
|
if (p_enabled) {
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
current_blend_enabled = p_enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_gl_scissor_test(bool p_enabled) {
|
||||||
|
if (current_scissor_test_enabled != p_enabled) {
|
||||||
|
if (p_enabled) {
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
current_scissor_test_enabled = p_enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_gl_depth_draw(bool p_enabled) {
|
||||||
|
if (current_depth_draw_enabled != p_enabled) {
|
||||||
|
glDepthMask(p_enabled ? GL_TRUE : GL_FALSE);
|
||||||
|
current_depth_draw_enabled = p_enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_gl_depth_test(bool p_enabled) {
|
||||||
|
if (current_depth_test_enabled != p_enabled) {
|
||||||
|
if (p_enabled) {
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
} else {
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
}
|
||||||
|
current_depth_test_enabled = p_enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -656,9 +732,9 @@ protected:
|
||||||
void _setup_sky(const RenderDataGLES3 *p_render_data, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
|
void _setup_sky(const RenderDataGLES3 *p_render_data, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
|
||||||
void _invalidate_sky(Sky *p_sky);
|
void _invalidate_sky(Sky *p_sky);
|
||||||
void _update_dirty_skys();
|
void _update_dirty_skys();
|
||||||
void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier);
|
void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_sky_energy_multiplier);
|
||||||
void _filter_sky_radiance(Sky *p_sky, int p_base_layer);
|
void _filter_sky_radiance(Sky *p_sky, int p_base_layer);
|
||||||
void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y);
|
void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_sky_energy_multiplier, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y, bool p_apply_color_adjustments_in_post);
|
||||||
void _free_sky_data(Sky *p_sky);
|
void _free_sky_data(Sky *p_sky);
|
||||||
|
|
||||||
// Needed for a single argument calls (material and uv2).
|
// Needed for a single argument calls (material and uv2).
|
||||||
|
|
|
@ -12,8 +12,10 @@ if "GLES3_GLSL" in env["BUILDERS"]:
|
||||||
# make sure we recompile shaders if include files change
|
# make sure we recompile shaders if include files change
|
||||||
env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#gles3_builders.py"])
|
env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#gles3_builders.py"])
|
||||||
|
|
||||||
|
# compile shaders
|
||||||
|
|
||||||
|
# as we have a few, not yet, converted files we name the ones we want to include:
|
||||||
env.GLES3_GLSL("canvas.glsl")
|
env.GLES3_GLSL("canvas.glsl")
|
||||||
env.GLES3_GLSL("copy.glsl")
|
|
||||||
env.GLES3_GLSL("scene.glsl")
|
env.GLES3_GLSL("scene.glsl")
|
||||||
env.GLES3_GLSL("sky.glsl")
|
env.GLES3_GLSL("sky.glsl")
|
||||||
env.GLES3_GLSL("cubemap_filter.glsl")
|
env.GLES3_GLSL("cubemap_filter.glsl")
|
||||||
|
@ -22,3 +24,10 @@ if "GLES3_GLSL" in env["BUILDERS"]:
|
||||||
env.GLES3_GLSL("particles.glsl")
|
env.GLES3_GLSL("particles.glsl")
|
||||||
env.GLES3_GLSL("particles_copy.glsl")
|
env.GLES3_GLSL("particles_copy.glsl")
|
||||||
env.GLES3_GLSL("skeleton.glsl")
|
env.GLES3_GLSL("skeleton.glsl")
|
||||||
|
|
||||||
|
# once we finish conversion we can introduce this to cover all files:
|
||||||
|
# for glsl_file in glsl_files:
|
||||||
|
# env.GLES3_GLSL(glsl_file)
|
||||||
|
|
||||||
|
|
||||||
|
SConscript("effects/SCsub")
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
Import("env")
|
||||||
|
|
||||||
|
if "GLES3_GLSL" in env["BUILDERS"]:
|
||||||
|
# find all include files
|
||||||
|
gl_include_files = [str(f) for f in Glob("*_inc.glsl")]
|
||||||
|
|
||||||
|
# find all shader code(all glsl files excluding our include files)
|
||||||
|
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
|
||||||
|
|
||||||
|
# make sure we recompile shaders if include files change
|
||||||
|
env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#gles3_builders.py"])
|
||||||
|
|
||||||
|
# compile shaders
|
||||||
|
for glsl_file in glsl_files:
|
||||||
|
env.GLES3_GLSL(glsl_file)
|
|
@ -6,6 +6,7 @@ mode_copy_section = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY
|
||||||
mode_copy_section_source = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define MODE_COPY_FROM
|
mode_copy_section_source = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define MODE_COPY_FROM
|
||||||
mode_copy_section_3d = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define USE_TEXTURE_3D
|
mode_copy_section_3d = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define USE_TEXTURE_3D
|
||||||
mode_copy_section_2d_array = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define USE_TEXTURE_2D_ARRAY
|
mode_copy_section_2d_array = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY \n#define USE_TEXTURE_2D_ARRAY
|
||||||
|
mode_screen = #define MODE_SIMPLE_COPY \n#define MODE_MULTIPLY
|
||||||
mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR
|
mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR
|
||||||
mode_mipmap = #define MODE_MIPMAP
|
mode_mipmap = #define MODE_MIPMAP
|
||||||
mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION
|
mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION
|
||||||
|
@ -55,6 +56,10 @@ uniform float lod;
|
||||||
uniform vec4 color_in;
|
uniform vec4 color_in;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODE_MULTIPLY
|
||||||
|
uniform float multiply;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODE_GAUSSIAN_BLUR
|
#ifdef MODE_GAUSSIAN_BLUR
|
||||||
// Defined in 0-1 coords.
|
// Defined in 0-1 coords.
|
||||||
uniform highp vec2 pixel_size;
|
uniform highp vec2 pixel_size;
|
||||||
|
@ -105,10 +110,14 @@ void main() {
|
||||||
vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), lod);
|
vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), lod);
|
||||||
#else
|
#else
|
||||||
vec4 color = texture(source, uv_interp);
|
vec4 color = texture(source, uv_interp);
|
||||||
#endif
|
#endif // USE_TEXTURE_3D
|
||||||
|
|
||||||
|
#ifdef MODE_MULTIPLY
|
||||||
|
color *= multiply;
|
||||||
|
#endif // MODE_MULTIPLY
|
||||||
|
|
||||||
frag_color = color;
|
frag_color = color;
|
||||||
#endif
|
#endif // MODE_SIMPLE_COPY
|
||||||
|
|
||||||
#ifdef MODE_SIMPLE_COLOR
|
#ifdef MODE_SIMPLE_COLOR
|
||||||
frag_color = color_in;
|
frag_color = color_in;
|
|
@ -0,0 +1,113 @@
|
||||||
|
/* clang-format off */
|
||||||
|
#[modes]
|
||||||
|
|
||||||
|
// Based on Dual filtering glow as explained in Marius Bjørge presentation at Siggraph 2015 "Bandwidth-Efficient Rendering"
|
||||||
|
|
||||||
|
mode_filter = #define MODE_FILTER
|
||||||
|
mode_downsample = #define MODE_DOWNSAMPLE
|
||||||
|
mode_upsample = #define MODE_UPSAMPLE
|
||||||
|
|
||||||
|
#[specializations]
|
||||||
|
|
||||||
|
USE_MULTIVIEW = false
|
||||||
|
|
||||||
|
#[vertex]
|
||||||
|
layout(location = 0) in vec2 vertex_attrib;
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
out vec2 uv_interp;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
uv_interp = vertex_attrib * 0.5 + 0.5;
|
||||||
|
gl_Position = vec4(vertex_attrib, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
#[fragment]
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
#ifdef MODE_FILTER
|
||||||
|
#ifdef USE_MULTIVIEW
|
||||||
|
uniform sampler2DArray source_color; // texunit:0
|
||||||
|
#else
|
||||||
|
uniform sampler2D source_color; // texunit:0
|
||||||
|
#endif // USE_MULTIVIEW
|
||||||
|
uniform float view;
|
||||||
|
uniform vec2 pixel_size;
|
||||||
|
uniform float luminance_multiplier;
|
||||||
|
uniform float glow_bloom;
|
||||||
|
uniform float glow_hdr_threshold;
|
||||||
|
uniform float glow_hdr_scale;
|
||||||
|
uniform float glow_luminance_cap;
|
||||||
|
#endif // MODE_FILTER
|
||||||
|
|
||||||
|
#ifdef MODE_DOWNSAMPLE
|
||||||
|
uniform sampler2D source_color; // texunit:0
|
||||||
|
uniform vec2 pixel_size;
|
||||||
|
#endif // MODE_DOWNSAMPLE
|
||||||
|
|
||||||
|
#ifdef MODE_UPSAMPLE
|
||||||
|
uniform sampler2D source_color; // texunit:0
|
||||||
|
uniform vec2 pixel_size;
|
||||||
|
#endif // MODE_UPSAMPLE
|
||||||
|
|
||||||
|
in vec2 uv_interp;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 frag_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
#ifdef MODE_FILTER
|
||||||
|
// Note, we read from an image with double resolution, so we average those out
|
||||||
|
#ifdef USE_MULTIVIEW
|
||||||
|
vec2 half_pixel = pixel_size * 0.5;
|
||||||
|
vec3 uv = vec3(uv_interp, view);
|
||||||
|
vec3 color = textureLod(source_color, uv, 0.0).rgb * 4.0;
|
||||||
|
color += textureLod(source_color, uv - vec3(half_pixel, 0.0), 0.0).rgb;
|
||||||
|
color += textureLod(source_color, uv + vec3(half_pixel, 0.0), 0.0).rgb;
|
||||||
|
color += textureLod(source_color, uv - vec3(half_pixel.x, -half_pixel.y, 0.0), 0.0).rgb;
|
||||||
|
color += textureLod(source_color, uv + vec3(half_pixel.x, -half_pixel.y, 0.0), 0.0).rgb;
|
||||||
|
#else
|
||||||
|
vec2 half_pixel = pixel_size * 0.5;
|
||||||
|
vec2 uv = uv_interp;
|
||||||
|
vec3 color = textureLod(source_color, uv, 0.0).rgb * 4.0;
|
||||||
|
color += textureLod(source_color, uv - half_pixel, 0.0).rgb;
|
||||||
|
color += textureLod(source_color, uv + half_pixel, 0.0).rgb;
|
||||||
|
color += textureLod(source_color, uv - vec2(half_pixel.x, -half_pixel.y), 0.0).rgb;
|
||||||
|
color += textureLod(source_color, uv + vec2(half_pixel.x, -half_pixel.y), 0.0).rgb;
|
||||||
|
#endif // USE_MULTIVIEW
|
||||||
|
color /= luminance_multiplier * 8.0;
|
||||||
|
|
||||||
|
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||||
|
float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom);
|
||||||
|
|
||||||
|
color = min(color * feedback, vec3(glow_luminance_cap));
|
||||||
|
|
||||||
|
frag_color = vec4(luminance_multiplier * color, 1.0);
|
||||||
|
#endif // MODE_FILTER
|
||||||
|
|
||||||
|
#ifdef MODE_DOWNSAMPLE
|
||||||
|
vec2 half_pixel = pixel_size * 0.5;
|
||||||
|
vec4 color = textureLod(source_color, uv_interp, 0.0) * 4.0;
|
||||||
|
color += textureLod(source_color, uv_interp - half_pixel, 0.0);
|
||||||
|
color += textureLod(source_color, uv_interp + half_pixel, 0.0);
|
||||||
|
color += textureLod(source_color, uv_interp - vec2(half_pixel.x, -half_pixel.y), 0.0);
|
||||||
|
color += textureLod(source_color, uv_interp + vec2(half_pixel.x, -half_pixel.y), 0.0);
|
||||||
|
frag_color = color / 8.0;
|
||||||
|
#endif // MODE_DOWNSAMPLE
|
||||||
|
|
||||||
|
#ifdef MODE_UPSAMPLE
|
||||||
|
vec2 half_pixel = pixel_size * 0.5;
|
||||||
|
|
||||||
|
vec4 color = textureLod(source_color, uv_interp + vec2(-half_pixel.x * 2.0, 0.0), 0.0);
|
||||||
|
color += textureLod(source_color, uv_interp + vec2(-half_pixel.x, half_pixel.y), 0.0) * 2.0;
|
||||||
|
color += textureLod(source_color, uv_interp + vec2(0.0, half_pixel.y * 2.0), 0.0);
|
||||||
|
color += textureLod(source_color, uv_interp + vec2(half_pixel.x, half_pixel.y), 0.0) * 2.0;
|
||||||
|
color += textureLod(source_color, uv_interp + vec2(half_pixel.x * 2.0, 0.0), 0.0);
|
||||||
|
color += textureLod(source_color, uv_interp + vec2(half_pixel.x, -half_pixel.y), 0.0) * 2.0;
|
||||||
|
color += textureLod(source_color, uv_interp + vec2(0.0, -half_pixel.y * 2.0), 0.0);
|
||||||
|
color += textureLod(source_color, uv_interp + vec2(-half_pixel.x, -half_pixel.y), 0.0) * 2.0;
|
||||||
|
|
||||||
|
frag_color = color / 12.0;
|
||||||
|
#endif // MODE_UPSAMPLE
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/* clang-format off */
|
||||||
|
#[modes]
|
||||||
|
mode_default = #define MODE_DEFAULT
|
||||||
|
// mode_glow = #define MODE_GLOW
|
||||||
|
|
||||||
|
#[specializations]
|
||||||
|
|
||||||
|
USE_MULTIVIEW = false
|
||||||
|
USE_GLOW = false
|
||||||
|
USE_LUMINANCE_MULTIPLIER = false
|
||||||
|
|
||||||
|
#[vertex]
|
||||||
|
layout(location = 0) in vec2 vertex_attrib;
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
out vec2 uv_interp;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
uv_interp = vertex_attrib * 0.5 + 0.5;
|
||||||
|
gl_Position = vec4(vertex_attrib, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
#[fragment]
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
#include "../tonemap_inc.glsl"
|
||||||
|
|
||||||
|
#ifdef USE_MULTIVIEW
|
||||||
|
uniform sampler2DArray source_color; // texunit:0
|
||||||
|
#else
|
||||||
|
uniform sampler2D source_color; // texunit:0
|
||||||
|
#endif // USE_MULTIVIEW
|
||||||
|
|
||||||
|
uniform float view;
|
||||||
|
uniform float luminance_multiplier;
|
||||||
|
|
||||||
|
#ifdef USE_GLOW
|
||||||
|
uniform sampler2D glow_color; // texunit:1
|
||||||
|
uniform vec2 pixel_size;
|
||||||
|
uniform float glow_intensity;
|
||||||
|
|
||||||
|
vec4 get_glow_color(vec2 uv) {
|
||||||
|
vec2 half_pixel = pixel_size * 0.5;
|
||||||
|
|
||||||
|
vec4 color = textureLod(glow_color, uv + vec2(-half_pixel.x * 2.0, 0.0), 0.0);
|
||||||
|
color += textureLod(glow_color, uv + vec2(-half_pixel.x, half_pixel.y), 0.0) * 2.0;
|
||||||
|
color += textureLod(glow_color, uv + vec2(0.0, half_pixel.y * 2.0), 0.0);
|
||||||
|
color += textureLod(glow_color, uv + vec2(half_pixel.x, half_pixel.y), 0.0) * 2.0;
|
||||||
|
color += textureLod(glow_color, uv + vec2(half_pixel.x * 2.0, 0.0), 0.0);
|
||||||
|
color += textureLod(glow_color, uv + vec2(half_pixel.x, -half_pixel.y), 0.0) * 2.0;
|
||||||
|
color += textureLod(glow_color, uv + vec2(0.0, -half_pixel.y * 2.0), 0.0);
|
||||||
|
color += textureLod(glow_color, uv + vec2(-half_pixel.x, -half_pixel.y), 0.0) * 2.0;
|
||||||
|
|
||||||
|
return color / 12.0;
|
||||||
|
}
|
||||||
|
#endif // USE_GLOW
|
||||||
|
|
||||||
|
in vec2 uv_interp;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 frag_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
#ifdef USE_MULTIVIEW
|
||||||
|
vec4 color = texture(source_color, vec3(uv_interp, view));
|
||||||
|
#else
|
||||||
|
vec4 color = texture(source_color, uv_interp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLOW
|
||||||
|
vec4 glow = get_glow_color(uv_interp) * glow_intensity;
|
||||||
|
|
||||||
|
// Just use softlight...
|
||||||
|
glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
|
||||||
|
color.rgb = max((color.rgb + glow.rgb) - (color.rgb * glow.rgb), vec3(0.0));
|
||||||
|
#endif // USE_GLOW
|
||||||
|
|
||||||
|
#ifdef USE_LUMINANCE_MULTIPLIER
|
||||||
|
color = color / luminance_multiplier;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
color.rgb = srgb_to_linear(color.rgb);
|
||||||
|
color.rgb = apply_tonemapping(color.rgb, white);
|
||||||
|
color.rgb = linear_to_srgb(color.rgb);
|
||||||
|
|
||||||
|
#ifdef USE_BCS
|
||||||
|
color.rgb = apply_bcs(color.rgb, bcs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_COLOR_CORRECTION
|
||||||
|
color.rgb = apply_color_correction(color.rgb, color_correction);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
frag_color = color;
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ LIGHT_USE_PSSM4 = false
|
||||||
LIGHT_USE_PSSM_BLEND = false
|
LIGHT_USE_PSSM_BLEND = false
|
||||||
BASE_PASS = true
|
BASE_PASS = true
|
||||||
USE_ADDITIVE_LIGHTING = false
|
USE_ADDITIVE_LIGHTING = false
|
||||||
|
APPLY_TONEMAPPING = true
|
||||||
// We can only use one type of light per additive pass. This means that if USE_ADDITIVE_LIGHTING is defined, and
|
// We can only use one type of light per additive pass. This means that if USE_ADDITIVE_LIGHTING is defined, and
|
||||||
// these are false, we are doing a directional light pass.
|
// these are false, we are doing a directional light pass.
|
||||||
ADDITIVE_OMNI = false
|
ADDITIVE_OMNI = false
|
||||||
|
@ -185,18 +186,17 @@ layout(std140) uniform SceneData { // ubo:2
|
||||||
uint fog_mode;
|
uint fog_mode;
|
||||||
float fog_density;
|
float fog_density;
|
||||||
float fog_height;
|
float fog_height;
|
||||||
float fog_height_density;
|
|
||||||
|
|
||||||
|
float fog_height_density;
|
||||||
float fog_depth_curve;
|
float fog_depth_curve;
|
||||||
float pad;
|
float fog_sun_scatter;
|
||||||
float fog_depth_begin;
|
float fog_depth_begin;
|
||||||
|
|
||||||
vec3 fog_light_color;
|
vec3 fog_light_color;
|
||||||
float fog_depth_end;
|
float fog_depth_end;
|
||||||
|
|
||||||
float fog_sun_scatter;
|
|
||||||
|
|
||||||
float shadow_bias;
|
float shadow_bias;
|
||||||
|
float luminance_multiplier;
|
||||||
uint camera_visible_layers;
|
uint camera_visible_layers;
|
||||||
bool pancake_shadows;
|
bool pancake_shadows;
|
||||||
}
|
}
|
||||||
|
@ -676,18 +676,17 @@ layout(std140) uniform SceneData { // ubo:2
|
||||||
uint fog_mode;
|
uint fog_mode;
|
||||||
float fog_density;
|
float fog_density;
|
||||||
float fog_height;
|
float fog_height;
|
||||||
float fog_height_density;
|
|
||||||
|
|
||||||
|
float fog_height_density;
|
||||||
float fog_depth_curve;
|
float fog_depth_curve;
|
||||||
float pad;
|
float fog_sun_scatter;
|
||||||
float fog_depth_begin;
|
float fog_depth_begin;
|
||||||
|
|
||||||
vec3 fog_light_color;
|
vec3 fog_light_color;
|
||||||
float fog_depth_end;
|
float fog_depth_end;
|
||||||
|
|
||||||
float fog_sun_scatter;
|
|
||||||
|
|
||||||
float shadow_bias;
|
float shadow_bias;
|
||||||
|
float luminance_multiplier;
|
||||||
uint camera_visible_layers;
|
uint camera_visible_layers;
|
||||||
bool pancake_shadows;
|
bool pancake_shadows;
|
||||||
}
|
}
|
||||||
|
@ -1758,7 +1757,9 @@ void main() {
|
||||||
|
|
||||||
// Tonemap before writing as we are writing to an sRGB framebuffer
|
// Tonemap before writing as we are writing to an sRGB framebuffer
|
||||||
frag_color.rgb *= exposure;
|
frag_color.rgb *= exposure;
|
||||||
|
#ifdef APPLY_TONEMAPPING
|
||||||
frag_color.rgb = apply_tonemapping(frag_color.rgb, white);
|
frag_color.rgb = apply_tonemapping(frag_color.rgb, white);
|
||||||
|
#endif
|
||||||
frag_color.rgb = linear_to_srgb(frag_color.rgb);
|
frag_color.rgb = linear_to_srgb(frag_color.rgb);
|
||||||
|
|
||||||
#ifdef USE_BCS
|
#ifdef USE_BCS
|
||||||
|
@ -1973,7 +1974,9 @@ void main() {
|
||||||
|
|
||||||
// Tonemap before writing as we are writing to an sRGB framebuffer
|
// Tonemap before writing as we are writing to an sRGB framebuffer
|
||||||
additive_light_color *= exposure;
|
additive_light_color *= exposure;
|
||||||
|
#ifdef APPLY_TONEMAPPING
|
||||||
additive_light_color = apply_tonemapping(additive_light_color, white);
|
additive_light_color = apply_tonemapping(additive_light_color, white);
|
||||||
|
#endif
|
||||||
additive_light_color = linear_to_srgb(additive_light_color);
|
additive_light_color = linear_to_srgb(additive_light_color);
|
||||||
|
|
||||||
#ifdef USE_BCS
|
#ifdef USE_BCS
|
||||||
|
@ -1986,6 +1989,9 @@ void main() {
|
||||||
|
|
||||||
frag_color.rgb += additive_light_color;
|
frag_color.rgb += additive_light_color;
|
||||||
#endif // USE_ADDITIVE_LIGHTING
|
#endif // USE_ADDITIVE_LIGHTING
|
||||||
|
|
||||||
|
frag_color.rgb *= scene_data.luminance_multiplier;
|
||||||
|
|
||||||
#endif // !RENDER_MATERIAL
|
#endif // !RENDER_MATERIAL
|
||||||
#endif //!MODE_RENDER_DEPTH
|
#endif // !MODE_RENDER_DEPTH
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PA
|
||||||
|
|
||||||
USE_MULTIVIEW = false
|
USE_MULTIVIEW = false
|
||||||
USE_INVERTED_Y = true
|
USE_INVERTED_Y = true
|
||||||
|
APPLY_TONEMAPPING = true
|
||||||
|
|
||||||
#[vertex]
|
#[vertex]
|
||||||
|
|
||||||
|
@ -103,6 +104,7 @@ uniform mat4 orientation;
|
||||||
uniform vec4 projection;
|
uniform vec4 projection;
|
||||||
uniform vec3 position;
|
uniform vec3 position;
|
||||||
uniform float time;
|
uniform float time;
|
||||||
|
uniform float sky_energy_multiplier;
|
||||||
uniform float luminance_multiplier;
|
uniform float luminance_multiplier;
|
||||||
|
|
||||||
uniform float fog_aerial_perspective;
|
uniform float fog_aerial_perspective;
|
||||||
|
@ -195,12 +197,14 @@ void main() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
color *= luminance_multiplier;
|
color *= sky_energy_multiplier;
|
||||||
|
|
||||||
// Convert to Linear for tonemapping so color matches scene shader better
|
// Convert to Linear for tonemapping so color matches scene shader better
|
||||||
color = srgb_to_linear(color);
|
color = srgb_to_linear(color);
|
||||||
color *= exposure;
|
color *= exposure;
|
||||||
|
#ifdef APPLY_TONEMAPPING
|
||||||
color = apply_tonemapping(color, white);
|
color = apply_tonemapping(color, white);
|
||||||
|
#endif
|
||||||
color = linear_to_srgb(color);
|
color = linear_to_srgb(color);
|
||||||
|
|
||||||
#ifdef USE_BCS
|
#ifdef USE_BCS
|
||||||
|
@ -211,10 +215,10 @@ void main() {
|
||||||
color = apply_color_correction(color, color_correction);
|
color = apply_color_correction(color, color_correction);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
frag_color.rgb = color;
|
frag_color.rgb = color * luminance_multiplier;
|
||||||
frag_color.a = alpha;
|
frag_color.a = alpha;
|
||||||
|
|
||||||
#ifdef USE_DEBANDING
|
#ifdef USE_DEBANDING
|
||||||
frag_color.rgb += interleaved_gradient_noise(gl_FragCoord.xy) * luminance_multiplier;
|
frag_color.rgb += interleaved_gradient_noise(gl_FragCoord.xy) * sky_energy_multiplier * luminance_multiplier;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,13 @@
|
||||||
#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
|
#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
RenderSceneBuffersGLES3::RenderSceneBuffersGLES3() {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
glow.levels[i].color = 0;
|
||||||
|
glow.levels[i].fbo = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
|
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
|
||||||
free_render_buffer_data();
|
free_render_buffer_data();
|
||||||
}
|
}
|
||||||
|
@ -137,9 +144,22 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
//use_debanding = p_config->get_use_debanding();
|
//use_debanding = p_config->get_use_debanding();
|
||||||
view_count = config->multiview_supported ? p_config->get_view_count() : 1;
|
view_count = config->multiview_supported ? p_config->get_view_count() : 1;
|
||||||
|
|
||||||
ERR_FAIL_COND(view_count == 0);
|
|
||||||
bool use_multiview = view_count > 1;
|
bool use_multiview = view_count > 1;
|
||||||
|
|
||||||
|
// Get color format data from our render target so we match those
|
||||||
|
if (render_target.is_valid()) {
|
||||||
|
color_internal_format = texture_storage->render_target_get_color_internal_format(render_target);
|
||||||
|
color_format = texture_storage->render_target_get_color_format(render_target);
|
||||||
|
color_type = texture_storage->render_target_get_color_type(render_target);
|
||||||
|
color_format_size = texture_storage->render_target_get_color_format_size(render_target);
|
||||||
|
} else {
|
||||||
|
// reflection probe? or error?
|
||||||
|
color_internal_format = GL_RGBA8;
|
||||||
|
color_format = GL_RGBA;
|
||||||
|
color_type = GL_UNSIGNED_BYTE;
|
||||||
|
color_format_size = 4;
|
||||||
|
}
|
||||||
|
|
||||||
// Check our scaling mode
|
// Check our scaling mode
|
||||||
if (scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF && internal_size.x == 0 && internal_size.y == 0) {
|
if (scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF && internal_size.x == 0 && internal_size.y == 0) {
|
||||||
// Disable, no size set.
|
// Disable, no size set.
|
||||||
|
@ -153,14 +173,38 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
|
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_internal_buffer = scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF; // TODO also need this if doing post processing like glow
|
// Check if we support MSAA.
|
||||||
|
if (msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && internal_size.x == 0 && internal_size.y == 0) {
|
||||||
|
// Disable, no size set.
|
||||||
|
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||||
|
} else if (!use_multiview && msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && !config->msaa_supported && !config->rt_msaa_supported) {
|
||||||
|
WARN_PRINT_ONCE("MSAA is not supported on this device.");
|
||||||
|
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||||
|
} else if (use_multiview && msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && !config->msaa_multiview_supported && !config->rt_msaa_multiview_supported) {
|
||||||
|
WARN_PRINT_ONCE("Multiview MSAA is not supported on this device.");
|
||||||
|
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't create our buffers right away because post effects can be made active at any time and change our buffer configuration.
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSceneBuffersGLES3::_check_render_buffers() {
|
||||||
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
|
GLES3::Config *config = GLES3::Config::get_singleton();
|
||||||
|
|
||||||
|
ERR_FAIL_COND(view_count == 0);
|
||||||
|
|
||||||
|
bool use_internal_buffer = scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF || glow.glow_enabled;
|
||||||
|
uint32_t depth_format_size = 3;
|
||||||
|
bool use_multiview = view_count > 1;
|
||||||
|
|
||||||
|
if ((!use_internal_buffer || internal3d.color != 0) && (msaa3d.mode == RS::VIEWPORT_MSAA_DISABLED || msaa3d.color != 0)) {
|
||||||
|
// already setup!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (use_internal_buffer) {
|
if (use_internal_buffer) {
|
||||||
// Setup our internal buffer.
|
// Setup our internal buffer.
|
||||||
bool is_transparent = texture_storage->render_target_get_transparent(render_target);
|
|
||||||
GLuint color_internal_format = is_transparent ? GL_RGBA8 : GL_RGB10_A2;
|
|
||||||
GLuint color_format = GL_RGBA;
|
|
||||||
GLuint color_type = is_transparent ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
|
|
||||||
|
|
||||||
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
|
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
|
||||||
|
|
||||||
// Create our color buffer.
|
// Create our color buffer.
|
||||||
|
@ -178,7 +222,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
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(internal3d.color, internal_size.x * internal_size.y * view_count * 4, "3D color texture");
|
GLES3::Utilities::get_singleton()->texture_allocated_data(internal3d.color, internal_size.x * internal_size.y * view_count * color_format_size, "3D color texture");
|
||||||
|
|
||||||
// Create our depth buffer.
|
// Create our depth buffer.
|
||||||
glGenTextures(1, &internal3d.depth);
|
glGenTextures(1, &internal3d.depth);
|
||||||
|
@ -195,7 +239,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
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(internal3d.depth, internal_size.x * internal_size.y * view_count * 3, "3D depth texture");
|
GLES3::Utilities::get_singleton()->texture_allocated_data(internal3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size, "3D depth texture");
|
||||||
|
|
||||||
// Create our internal 3D FBO.
|
// Create our internal 3D FBO.
|
||||||
// Note that if MSAA is used and our rt_msaa_* extensions are available, this is only used for blitting and effects.
|
// Note that if MSAA is used and our rt_msaa_* extensions are available, this is only used for blitting and effects.
|
||||||
|
@ -224,18 +268,6 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we support MSAA.
|
|
||||||
if (msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && internal_size.x == 0 && internal_size.y == 0) {
|
|
||||||
// Disable, no size set.
|
|
||||||
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
|
||||||
} else if (!use_multiview && msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && !config->msaa_supported && !config->rt_msaa_supported) {
|
|
||||||
WARN_PRINT_ONCE("MSAA is not supported on this device.");
|
|
||||||
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
|
||||||
} else if (use_multiview && msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && !config->msaa_multiview_supported && !config->rt_msaa_multiview_supported) {
|
|
||||||
WARN_PRINT_ONCE("Multiview MSAA is not supported on this device.");
|
|
||||||
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED) {
|
if (msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED) {
|
||||||
// Setup MSAA.
|
// Setup MSAA.
|
||||||
const GLsizei samples[] = { 1, 2, 4, 8 };
|
const GLsizei samples[] = { 1, 2, 4, 8 };
|
||||||
|
@ -255,9 +287,6 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
msaa3d.needs_resolve = true;
|
msaa3d.needs_resolve = true;
|
||||||
msaa3d.check_fbo_cache = false;
|
msaa3d.check_fbo_cache = false;
|
||||||
|
|
||||||
bool is_transparent = texture_storage->render_target_get_transparent(render_target);
|
|
||||||
GLuint color_internal_format = is_transparent ? GL_RGBA8 : GL_RGB10_A2;
|
|
||||||
|
|
||||||
// Create our color buffer.
|
// Create our color buffer.
|
||||||
glGenRenderbuffers(1, &msaa3d.color);
|
glGenRenderbuffers(1, &msaa3d.color);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, msaa3d.color);
|
glBindRenderbuffer(GL_RENDERBUFFER, msaa3d.color);
|
||||||
|
@ -282,6 +311,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
_clear_msaa3d_buffers();
|
_clear_msaa3d_buffers();
|
||||||
|
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||||
WARN_PRINT("Could not create 3D MSAA buffers, status: " + texture_storage->get_framebuffer_error(status));
|
WARN_PRINT("Could not create 3D MSAA buffers, status: " + texture_storage->get_framebuffer_error(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,9 +323,6 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
msaa3d.needs_resolve = true;
|
msaa3d.needs_resolve = true;
|
||||||
msaa3d.check_fbo_cache = false;
|
msaa3d.check_fbo_cache = false;
|
||||||
|
|
||||||
bool is_transparent = texture_storage->render_target_get_transparent(render_target);
|
|
||||||
GLuint color_internal_format = is_transparent ? GL_RGBA8 : GL_RGB10_A2;
|
|
||||||
|
|
||||||
// Create our color buffer.
|
// Create our color buffer.
|
||||||
glGenTextures(1, &msaa3d.color);
|
glGenTextures(1, &msaa3d.color);
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.color);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.color);
|
||||||
|
@ -306,7 +333,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, color_internal_format, internal_size.x, internal_size.y, view_count, GL_TRUE);
|
glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, color_internal_format, internal_size.x, internal_size.y, view_count, GL_TRUE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLES3::Utilities::get_singleton()->texture_allocated_data(msaa3d.color, internal_size.x * internal_size.y * view_count * 4 * msaa3d.samples, "MSAA 3D color texture");
|
GLES3::Utilities::get_singleton()->texture_allocated_data(msaa3d.color, internal_size.x * internal_size.y * view_count * color_format_size * msaa3d.samples, "MSAA 3D color texture");
|
||||||
|
|
||||||
// Create our depth buffer.
|
// Create our depth buffer.
|
||||||
glGenTextures(1, &msaa3d.depth);
|
glGenTextures(1, &msaa3d.depth);
|
||||||
|
@ -318,7 +345,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
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, GL_DEPTH_COMPONENT24, 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 * 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");
|
||||||
|
|
||||||
// Create our MSAA 3D FBO.
|
// Create our MSAA 3D FBO.
|
||||||
glGenFramebuffers(1, &msaa3d.fbo);
|
glGenFramebuffers(1, &msaa3d.fbo);
|
||||||
|
@ -330,6 +357,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
_clear_msaa3d_buffers();
|
_clear_msaa3d_buffers();
|
||||||
|
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||||
WARN_PRINT("Could not create 3D MSAA buffers, status: " + texture_storage->get_framebuffer_error(status));
|
WARN_PRINT("Could not create 3D MSAA buffers, status: " + texture_storage->get_framebuffer_error(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,6 +386,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
_clear_msaa3d_buffers();
|
_clear_msaa3d_buffers();
|
||||||
|
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||||
WARN_PRINT("Could not create 3D MSAA framebuffer, status: " + texture_storage->get_framebuffer_error(status));
|
WARN_PRINT("Could not create 3D MSAA framebuffer, status: " + texture_storage->get_framebuffer_error(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,13 +464,9 @@ void RenderSceneBuffersGLES3::check_backbuffer(bool p_need_color, bool p_need_de
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, backbuffer3d.fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, backbuffer3d.fbo);
|
||||||
|
|
||||||
bool is_transparent = texture_storage->render_target_get_transparent(render_target);
|
|
||||||
GLuint color_internal_format = is_transparent ? GL_RGBA8 : GL_RGB10_A2;
|
|
||||||
GLuint color_format = GL_RGBA;
|
|
||||||
GLuint color_type = is_transparent ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
if (backbuffer3d.color == 0 && p_need_color) {
|
if (backbuffer3d.color == 0 && p_need_color) {
|
||||||
glGenTextures(1, &backbuffer3d.color);
|
glGenTextures(1, &backbuffer3d.color);
|
||||||
|
@ -458,7 +483,7 @@ void RenderSceneBuffersGLES3::check_backbuffer(bool p_need_color, bool p_need_de
|
||||||
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(backbuffer3d.color, internal_size.x * internal_size.y * view_count * 4, "3D Back buffer color texture");
|
GLES3::Utilities::get_singleton()->texture_allocated_data(backbuffer3d.color, internal_size.x * internal_size.y * view_count * color_format_size, "3D Back buffer color texture");
|
||||||
|
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
|
@ -486,7 +511,7 @@ void RenderSceneBuffersGLES3::check_backbuffer(bool p_need_color, bool p_need_de
|
||||||
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(backbuffer3d.depth, internal_size.x * internal_size.y * view_count * 3, "3D back buffer depth texture");
|
GLES3::Utilities::get_singleton()->texture_allocated_data(backbuffer3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size, "3D back buffer depth texture");
|
||||||
|
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
|
@ -526,21 +551,101 @@ void RenderSceneBuffersGLES3::_clear_back_buffers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderSceneBuffersGLES3::set_glow_enabled(bool p_glow_enabled) {
|
||||||
|
if (glow.glow_enabled != p_glow_enabled) {
|
||||||
|
glow.glow_enabled = p_glow_enabled;
|
||||||
|
|
||||||
|
// Clear our main buffers, this can impact them.
|
||||||
|
_clear_msaa3d_buffers();
|
||||||
|
_clear_intermediate_buffers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSceneBuffersGLES3::check_glow_buffers() {
|
||||||
|
if (glow.levels[0].color != 0) {
|
||||||
|
// already have these setup..
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
|
Size2i level_size = internal_size;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
level_size.x = MAX(level_size.x >> 1, 4);
|
||||||
|
level_size.y = MAX(level_size.y >> 1, 4);
|
||||||
|
|
||||||
|
glow.levels[i].size = level_size;
|
||||||
|
|
||||||
|
// Create our texture
|
||||||
|
glGenTextures(1, &glow.levels[i].color);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, glow.levels[i].color);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, level_size.x, level_size.y, 0, color_format, color_type, nullptr);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
|
||||||
|
GLES3::Utilities::get_singleton()->texture_allocated_data(glow.levels[i].color, level_size.x * level_size.y * color_format_size, String("Glow buffer ") + String::num_int64(i));
|
||||||
|
|
||||||
|
// Create our FBO
|
||||||
|
glGenFramebuffers(1, &glow.levels[i].fbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, glow.levels[i].fbo);
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glow.levels[i].color, 0);
|
||||||
|
|
||||||
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
WARN_PRINT("Could not create glow buffers, status: " + texture_storage->get_framebuffer_error(status));
|
||||||
|
_clear_glow_buffers();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSceneBuffersGLES3::_clear_glow_buffers() {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (glow.levels[i].fbo != 0) {
|
||||||
|
glDeleteFramebuffers(1, &glow.levels[i].fbo);
|
||||||
|
glow.levels[i].fbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glow.levels[i].color != 0) {
|
||||||
|
GLES3::Utilities::get_singleton()->texture_free_data(glow.levels[i].color);
|
||||||
|
glow.levels[i].color = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderSceneBuffersGLES3::free_render_buffer_data() {
|
void RenderSceneBuffersGLES3::free_render_buffer_data() {
|
||||||
_clear_msaa3d_buffers();
|
_clear_msaa3d_buffers();
|
||||||
_clear_intermediate_buffers();
|
_clear_intermediate_buffers();
|
||||||
_clear_back_buffers();
|
_clear_back_buffers();
|
||||||
|
_clear_glow_buffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint RenderSceneBuffersGLES3::get_render_fbo() {
|
GLuint RenderSceneBuffersGLES3::get_render_fbo() {
|
||||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
GLuint rt_fbo = 0;
|
GLuint rt_fbo = 0;
|
||||||
|
|
||||||
|
_check_render_buffers();
|
||||||
|
|
||||||
if (msaa3d.check_fbo_cache) {
|
if (msaa3d.check_fbo_cache) {
|
||||||
GLuint color = texture_storage->render_target_get_color(render_target);
|
GLuint color = texture_storage->render_target_get_color(render_target);
|
||||||
GLuint depth = texture_storage->render_target_get_depth(render_target);
|
GLuint depth = texture_storage->render_target_get_depth(render_target);
|
||||||
|
|
||||||
rt_fbo = _rt_get_cached_fbo(color, depth, msaa3d.samples, view_count);
|
rt_fbo = _rt_get_cached_fbo(color, depth, msaa3d.samples, view_count);
|
||||||
|
if (rt_fbo == 0) {
|
||||||
|
// Somehow couldn't obtain this? Just render without MSAA.
|
||||||
|
rt_fbo = texture_storage->render_target_get_fbo(render_target);
|
||||||
|
}
|
||||||
} else if (msaa3d.fbo != 0) {
|
} else if (msaa3d.fbo != 0) {
|
||||||
// We have an MSAA fbo, render to our MSAA buffer
|
// We have an MSAA fbo, render to our MSAA buffer
|
||||||
return msaa3d.fbo;
|
return msaa3d.fbo;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#ifdef GLES3_ENABLED
|
#ifdef GLES3_ENABLED
|
||||||
|
|
||||||
|
#include "drivers/gles3/effects/glow.h"
|
||||||
#include "servers/rendering/storage/render_scene_buffers.h"
|
#include "servers/rendering/storage/render_scene_buffers.h"
|
||||||
|
|
||||||
#include "platform_gl.h"
|
#include "platform_gl.h"
|
||||||
|
@ -52,6 +53,12 @@ public:
|
||||||
|
|
||||||
RID render_target;
|
RID render_target;
|
||||||
|
|
||||||
|
// Color format details from our render target
|
||||||
|
GLuint color_internal_format = GL_RGBA8;
|
||||||
|
GLuint color_format = GL_RGBA;
|
||||||
|
GLuint color_type = GL_UNSIGNED_BYTE;
|
||||||
|
uint32_t color_format_size = 4;
|
||||||
|
|
||||||
struct FBDEF {
|
struct FBDEF {
|
||||||
GLuint color = 0;
|
GLuint color = 0;
|
||||||
GLuint depth = 0;
|
GLuint depth = 0;
|
||||||
|
@ -74,31 +81,24 @@ public:
|
||||||
|
|
||||||
FBDEF backbuffer3d; // our back buffer
|
FBDEF backbuffer3d; // our back buffer
|
||||||
|
|
||||||
// Built-in textures used for ping pong image processing and blurring.
|
// Buffers for our glow implementation
|
||||||
struct Blur {
|
struct GLOW {
|
||||||
RID texture;
|
bool glow_enabled = false;
|
||||||
|
GLES3::Glow::GLOWLEVEL levels[4];
|
||||||
struct Mipmap {
|
} glow;
|
||||||
RID texture;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
GLuint fbo;
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector<Mipmap> mipmaps;
|
|
||||||
};
|
|
||||||
|
|
||||||
Blur blur[2]; //the second one starts from the first mipmap
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _check_render_buffers();
|
||||||
void _clear_msaa3d_buffers();
|
void _clear_msaa3d_buffers();
|
||||||
void _clear_intermediate_buffers();
|
void _clear_intermediate_buffers();
|
||||||
void _clear_back_buffers();
|
void _clear_back_buffers();
|
||||||
|
void _clear_glow_buffers();
|
||||||
|
|
||||||
void _rt_attach_textures(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count);
|
void _rt_attach_textures(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count);
|
||||||
GLuint _rt_get_cached_fbo(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count);
|
GLuint _rt_get_cached_fbo(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
RenderSceneBuffersGLES3();
|
||||||
virtual ~RenderSceneBuffersGLES3();
|
virtual ~RenderSceneBuffersGLES3();
|
||||||
virtual void configure(const RenderSceneBuffersConfiguration *p_config) override;
|
virtual void configure(const RenderSceneBuffersConfiguration *p_config) override;
|
||||||
|
|
||||||
|
@ -109,19 +109,45 @@ public:
|
||||||
void free_render_buffer_data();
|
void free_render_buffer_data();
|
||||||
|
|
||||||
void check_backbuffer(bool p_need_color, bool p_need_depth); // Check if we need to initialize our backbuffer.
|
void check_backbuffer(bool p_need_color, bool p_need_depth); // Check if we need to initialize our backbuffer.
|
||||||
|
void check_glow_buffers(); // Check if we need to initialise our glow buffers.
|
||||||
|
|
||||||
GLuint get_render_fbo();
|
GLuint get_render_fbo();
|
||||||
GLuint get_msaa3d_fbo() const { return msaa3d.fbo; }
|
GLuint get_msaa3d_fbo() {
|
||||||
GLuint get_msaa3d_color() const { return msaa3d.color; }
|
_check_render_buffers();
|
||||||
GLuint get_msaa3d_depth() const { return msaa3d.depth; }
|
return msaa3d.fbo;
|
||||||
bool get_msaa_needs_resolve() const { return msaa3d.needs_resolve; }
|
}
|
||||||
GLuint get_internal_fbo() const { return internal3d.fbo; }
|
GLuint get_msaa3d_color() {
|
||||||
GLuint get_internal_color() const { return internal3d.color; }
|
_check_render_buffers();
|
||||||
GLuint get_internal_depth() const { return internal3d.depth; }
|
return msaa3d.color;
|
||||||
|
}
|
||||||
|
GLuint get_msaa3d_depth() {
|
||||||
|
_check_render_buffers();
|
||||||
|
return msaa3d.depth;
|
||||||
|
}
|
||||||
|
bool get_msaa_needs_resolve() {
|
||||||
|
_check_render_buffers();
|
||||||
|
return msaa3d.needs_resolve;
|
||||||
|
}
|
||||||
|
GLuint get_internal_fbo() {
|
||||||
|
_check_render_buffers();
|
||||||
|
return internal3d.fbo;
|
||||||
|
}
|
||||||
|
GLuint get_internal_color() {
|
||||||
|
_check_render_buffers();
|
||||||
|
return internal3d.color;
|
||||||
|
}
|
||||||
|
GLuint get_internal_depth() {
|
||||||
|
_check_render_buffers();
|
||||||
|
return internal3d.depth;
|
||||||
|
}
|
||||||
GLuint get_backbuffer_fbo() const { return backbuffer3d.fbo; }
|
GLuint get_backbuffer_fbo() const { return backbuffer3d.fbo; }
|
||||||
GLuint get_backbuffer() const { return backbuffer3d.color; }
|
GLuint get_backbuffer() const { return backbuffer3d.color; }
|
||||||
GLuint get_backbuffer_depth() const { return backbuffer3d.depth; }
|
GLuint get_backbuffer_depth() const { return backbuffer3d.depth; }
|
||||||
|
|
||||||
|
bool get_glow_enabled() const { return glow.glow_enabled; }
|
||||||
|
void set_glow_enabled(bool p_glow_enabled);
|
||||||
|
const GLES3::Glow::GLOWLEVEL *get_glow_buffers() const { return &glow.levels[0]; }
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
|
|
||||||
_FORCE_INLINE_ RID get_render_target() const { return render_target; }
|
_FORCE_INLINE_ RID get_render_target() const { return render_target; }
|
||||||
|
|
|
@ -1981,10 +1981,25 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
|
||||||
|
|
||||||
Config *config = Config::get_singleton();
|
Config *config = Config::get_singleton();
|
||||||
|
|
||||||
rt->color_internal_format = rt->is_transparent ? GL_RGBA8 : GL_RGB10_A2;
|
if (rt->hdr) {
|
||||||
rt->color_format = GL_RGBA;
|
rt->color_internal_format = GL_RGBA16F;
|
||||||
rt->color_type = rt->is_transparent ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
|
rt->color_format = GL_RGBA;
|
||||||
rt->image_format = Image::FORMAT_RGBA8;
|
rt->color_type = GL_FLOAT;
|
||||||
|
rt->color_format_size = 8;
|
||||||
|
rt->image_format = Image::FORMAT_RGBAF;
|
||||||
|
} else if (rt->is_transparent) {
|
||||||
|
rt->color_internal_format = GL_RGBA8;
|
||||||
|
rt->color_format = GL_RGBA;
|
||||||
|
rt->color_type = GL_UNSIGNED_BYTE;
|
||||||
|
rt->color_format_size = 4;
|
||||||
|
rt->image_format = Image::FORMAT_RGBA8;
|
||||||
|
} else {
|
||||||
|
rt->color_internal_format = GL_RGB10_A2;
|
||||||
|
rt->color_format = GL_RGBA;
|
||||||
|
rt->color_type = GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||||
|
rt->color_format_size = 4;
|
||||||
|
rt->image_format = Image::FORMAT_RGBA8;
|
||||||
|
}
|
||||||
|
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
glColorMask(1, 1, 1, 1);
|
glColorMask(1, 1, 1, 1);
|
||||||
|
@ -2023,7 +2038,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
|
||||||
texture->gl_set_filter(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
|
texture->gl_set_filter(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
|
||||||
texture->gl_set_repeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
texture->gl_set_repeat(RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||||
|
|
||||||
GLES3::Utilities::get_singleton()->texture_allocated_data(rt->color, rt->size.x * rt->size.y * rt->view_count * 4, "Render target color texture");
|
GLES3::Utilities::get_singleton()->texture_allocated_data(rt->color, rt->size.x * rt->size.y * rt->view_count * rt->color_format_size, "Render target color texture");
|
||||||
}
|
}
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
if (use_multiview) {
|
if (use_multiview) {
|
||||||
|
@ -2194,7 +2209,7 @@ void GLES3::TextureStorage::check_backbuffer(RenderTarget *rt, const bool uses_s
|
||||||
} else {
|
} else {
|
||||||
glTexImage2D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr);
|
glTexImage2D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr);
|
||||||
}
|
}
|
||||||
GLES3::Utilities::get_singleton()->texture_allocated_data(rt->backbuffer, rt->size.x * rt->size.y * rt->view_count * 4, "Render target backbuffer color texture (3D)");
|
GLES3::Utilities::get_singleton()->texture_allocated_data(rt->backbuffer, rt->size.x * rt->size.y * rt->view_count * rt->color_format_size, "Render target backbuffer color texture (3D)");
|
||||||
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);
|
||||||
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
@ -2548,6 +2563,54 @@ RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) con
|
||||||
return rt->msaa;
|
return rt->msaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureStorage::render_target_set_use_hdr(RID p_render_target, bool p_use_hdr_2d) {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_NULL(rt);
|
||||||
|
ERR_FAIL_COND(rt->direct_to_screen);
|
||||||
|
if (p_use_hdr_2d == rt->hdr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_clear_render_target(rt);
|
||||||
|
rt->hdr = p_use_hdr_2d;
|
||||||
|
_update_render_target(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextureStorage::render_target_is_using_hdr(RID p_render_target) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_NULL_V(rt, false);
|
||||||
|
|
||||||
|
return rt->hdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint TextureStorage::render_target_get_color_internal_format(RID p_render_target) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_NULL_V(rt, GL_RGBA8);
|
||||||
|
|
||||||
|
return rt->color_internal_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint TextureStorage::render_target_get_color_format(RID p_render_target) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_NULL_V(rt, GL_RGBA);
|
||||||
|
|
||||||
|
return rt->color_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint TextureStorage::render_target_get_color_type(RID p_render_target) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_NULL_V(rt, GL_UNSIGNED_BYTE);
|
||||||
|
|
||||||
|
return rt->color_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TextureStorage::render_target_get_color_format_size(RID p_render_target) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_NULL_V(rt, 4);
|
||||||
|
|
||||||
|
return rt->color_format_size;
|
||||||
|
}
|
||||||
|
|
||||||
void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
|
void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
|
||||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
ERR_FAIL_NULL(rt);
|
ERR_FAIL_NULL(rt);
|
||||||
|
|
|
@ -347,9 +347,11 @@ struct RenderTarget {
|
||||||
GLuint backbuffer = 0;
|
GLuint backbuffer = 0;
|
||||||
GLuint backbuffer_depth = 0;
|
GLuint backbuffer_depth = 0;
|
||||||
|
|
||||||
|
bool hdr = false; // For Compatibility this effects both 2D and 3D rendering!
|
||||||
GLuint color_internal_format = GL_RGBA8;
|
GLuint color_internal_format = GL_RGBA8;
|
||||||
GLuint color_format = GL_RGBA;
|
GLuint color_format = GL_RGBA;
|
||||||
GLuint color_type = GL_UNSIGNED_BYTE;
|
GLuint color_type = GL_UNSIGNED_BYTE;
|
||||||
|
uint32_t color_format_size = 4;
|
||||||
Image::Format image_format = Image::FORMAT_RGBA8;
|
Image::Format image_format = Image::FORMAT_RGBA8;
|
||||||
|
|
||||||
GLuint sdf_texture_write = 0;
|
GLuint sdf_texture_write = 0;
|
||||||
|
@ -631,14 +633,19 @@ public:
|
||||||
virtual void render_target_set_msaa_needs_resolve(RID p_render_target, bool p_needs_resolve) override {}
|
virtual void render_target_set_msaa_needs_resolve(RID p_render_target, bool p_needs_resolve) override {}
|
||||||
virtual bool render_target_get_msaa_needs_resolve(RID p_render_target) const override { return false; }
|
virtual bool render_target_get_msaa_needs_resolve(RID p_render_target) const override { return false; }
|
||||||
virtual void render_target_do_msaa_resolve(RID p_render_target) override {}
|
virtual void render_target_do_msaa_resolve(RID p_render_target) override {}
|
||||||
virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr_2d) override {}
|
virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr_2d) override;
|
||||||
virtual bool render_target_is_using_hdr(RID p_render_target) const override { return false; }
|
virtual bool render_target_is_using_hdr(RID p_render_target) const override;
|
||||||
|
|
||||||
// new
|
// new
|
||||||
void render_target_set_as_unused(RID p_render_target) override {
|
void render_target_set_as_unused(RID p_render_target) override {
|
||||||
render_target_clear_used(p_render_target);
|
render_target_clear_used(p_render_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint render_target_get_color_internal_format(RID p_render_target) const;
|
||||||
|
GLuint render_target_get_color_format(RID p_render_target) const;
|
||||||
|
GLuint render_target_get_color_type(RID p_render_target) const;
|
||||||
|
uint32_t render_target_get_color_format_size(RID p_render_target) const;
|
||||||
|
|
||||||
void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
|
void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
|
||||||
bool render_target_is_clear_requested(RID p_render_target) override;
|
bool render_target_is_clear_requested(RID p_render_target) override;
|
||||||
Color render_target_get_clear_request_color(RID p_render_target) override;
|
Color render_target_get_clear_request_color(RID p_render_target) override;
|
||||||
|
|
|
@ -1131,8 +1131,15 @@ void Environment::_validate_property(PropertyInfo &p_property) const {
|
||||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) {
|
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
|
||||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
// Hide glow properties we do not support in GL Compatibility.
|
||||||
|
if (p_property.name.begins_with("glow_levels") || p_property.name == "glow_normalized" || p_property.name == "glow_strength" || p_property.name == "glow_mix" || p_property.name == "glow_blend_mode" || p_property.name == "glow_map_strength" || p_property.name == "glow_map") {
|
||||||
|
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (p_property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) {
|
||||||
|
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_property.name == "background_color") {
|
if (p_property.name == "background_color") {
|
||||||
|
|
|
@ -417,11 +417,6 @@ void RendererEnvironmentStorage::environment_set_glow(RID p_env, bool p_enable,
|
||||||
Environment *env = environment_owner.get_or_null(p_env);
|
Environment *env = environment_owner.get_or_null(p_env);
|
||||||
ERR_FAIL_NULL(env);
|
ERR_FAIL_NULL(env);
|
||||||
ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
|
ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" && p_enable) {
|
|
||||||
WARN_PRINT_ONCE_ED("Glow is not supported when using the GL Compatibility backend yet. Support will be added in a future release.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
env->glow_enabled = p_enable;
|
env->glow_enabled = p_enable;
|
||||||
env->glow_levels = p_levels;
|
env->glow_levels = p_levels;
|
||||||
env->glow_intensity = p_intensity;
|
env->glow_intensity = p_intensity;
|
||||||
|
|
Loading…
Reference in New Issue