mirror of
https://github.com/godotengine/godot.git
synced 2024-11-24 21:22:48 +00:00
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();
|
||||
}
|
||||
|
||||
void CopyEffects::copy_screen() {
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT);
|
||||
void CopyEffects::copy_screen(float p_multiply) {
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SCREEN);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::MULTIPLY, p_multiply, copy.shader_version, CopyShaderGLES3::MODE_SCREEN);
|
||||
|
||||
draw_screen_triangle();
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "drivers/gles3/shaders/copy.glsl.gen.h"
|
||||
#include "drivers/gles3/shaders/effects/copy.glsl.gen.h"
|
||||
|
||||
namespace GLES3 {
|
||||
|
||||
@ -64,7 +64,7 @@ public:
|
||||
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_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_panorama(float p_mip_level);
|
||||
void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region);
|
||||
|
172
drivers/gles3/effects/glow.cpp
Normal file
172
drivers/gles3/effects/glow.cpp
Normal file
@ -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
|
89
drivers/gles3/effects/glow.h
Normal file
89
drivers/gles3/effects/glow.h
Normal file
@ -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
|
152
drivers/gles3/effects/post_effects.cpp
Normal file
152
drivers/gles3/effects/post_effects.cpp
Normal file
@ -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
|
69
drivers/gles3/effects/post_effects.h
Normal file
69
drivers/gles3/effects/post_effects.h
Normal file
@ -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(gi);
|
||||
memdelete(fog);
|
||||
memdelete(post_effects);
|
||||
memdelete(glow);
|
||||
memdelete(copy_effects);
|
||||
memdelete(light_storage);
|
||||
memdelete(particles_storage);
|
||||
@ -347,6 +349,8 @@ RasterizerGLES3::RasterizerGLES3() {
|
||||
particles_storage = memnew(GLES3::ParticlesStorage);
|
||||
light_storage = memnew(GLES3::LightStorage);
|
||||
copy_effects = memnew(GLES3::CopyEffects);
|
||||
glow = memnew(GLES3::Glow);
|
||||
post_effects = memnew(GLES3::PostEffects);
|
||||
gi = memnew(GLES3::GI);
|
||||
fog = memnew(GLES3::Fog);
|
||||
canvas = memnew(RasterizerCanvasGLES3());
|
||||
|
@ -34,6 +34,8 @@
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "effects/copy_effects.h"
|
||||
#include "effects/glow.h"
|
||||
#include "effects/post_effects.h"
|
||||
#include "environment/fog.h"
|
||||
#include "environment/gi.h"
|
||||
#include "rasterizer_canvas_gles3.h"
|
||||
@ -67,6 +69,8 @@ protected:
|
||||
GLES3::GI *gi = nullptr;
|
||||
GLES3::Fog *fog = nullptr;
|
||||
GLES3::CopyEffects *copy_effects = nullptr;
|
||||
GLES3::Glow *glow = nullptr;
|
||||
GLES3::PostEffects *post_effects = nullptr;
|
||||
RasterizerCanvasGLES3 *canvas = nullptr;
|
||||
RasterizerSceneGLES3 *scene = nullptr;
|
||||
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();
|
||||
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) {
|
||||
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);
|
||||
|
||||
@ -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::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::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);
|
||||
|
||||
if (p_use_multiview) {
|
||||
@ -843,7 +848,7 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
|
||||
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();
|
||||
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::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::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);
|
||||
|
||||
glViewport(0, 0, sky->radiance_size, sky->radiance_size);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sky->radiance_framebuffer);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
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;
|
||||
scene_state.reset_gl_state();
|
||||
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||
scene_state.enable_gl_blend(false);
|
||||
|
||||
for (int i = 0; i < 6; 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
|
||||
}
|
||||
sky->processing_layer = 1;
|
||||
sky->baked_exposure = p_luminance_multiplier;
|
||||
sky->baked_exposure = p_sky_energy_multiplier;
|
||||
sky->reflection_dirty = false;
|
||||
} else {
|
||||
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
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;
|
||||
scene_state.reset_gl_state();
|
||||
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||
scene_state.enable_gl_blend(false);
|
||||
|
||||
_filter_sky_radiance(sky, 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[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.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);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
scene_state.reset_gl_state();
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
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);
|
||||
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());
|
||||
|
||||
glColorMask(1, 1, 1, 1);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
scene_state.enable_gl_depth_test(false);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
glDisable(GL_CULL_FACE);
|
||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@ -2315,15 +2311,32 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
GLES3::Config *config = GLES3::Config::get_singleton();
|
||||
RENDER_TIMESTAMP("Setup 3D Scene");
|
||||
|
||||
bool apply_color_adjustments_in_post = false;
|
||||
|
||||
Ref<RenderSceneBuffersGLES3> rb;
|
||||
if (p_render_buffers.is_valid()) {
|
||||
rb = p_render_buffers;
|
||||
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);
|
||||
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
|
||||
// Use the format from rendererRD
|
||||
RenderDataGLES3 render_data;
|
||||
@ -2359,6 +2372,13 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
// this should be the same for all cameras..
|
||||
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) {
|
||||
render_data.screen_mesh_lod_threshold = 0.0;
|
||||
} else {
|
||||
@ -2519,9 +2539,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glViewport(0, 0, rb->internal_size.x, rb->internal_size.y);
|
||||
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_CULL_FACE);
|
||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
||||
scene_state.reset_gl_state();
|
||||
|
||||
// Do depth prepass if it's explicitly enabled
|
||||
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");
|
||||
//pre z pass
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
scene_state.enable_gl_blend(false);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
scene_state.enable_gl_scissor_test(false);
|
||||
|
||||
glColorMask(0, 0, 0, 0);
|
||||
RasterizerGLES3::clear_depth(1.0);
|
||||
@ -2560,21 +2578,19 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
}
|
||||
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
||||
if (render_data.transparent_bg) {
|
||||
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 {
|
||||
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;
|
||||
|
||||
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);
|
||||
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;
|
||||
@ -2589,7 +2605,19 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
if (!keep_color) {
|
||||
clear_color.a = render_data.transparent_bg ? 0.0f : 1.0f;
|
||||
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");
|
||||
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) {
|
||||
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.
|
||||
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());
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED;
|
||||
scene_state.enable_gl_depth_draw(false);
|
||||
|
||||
if (draw_sky) {
|
||||
RENDER_TIMESTAMP("Render Sky");
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
scene_state.current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_ENABLED;
|
||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_blend(false);
|
||||
scene_state.set_gl_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) {
|
||||
@ -2674,7 +2704,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP("Render 3D Transparent Pass");
|
||||
glEnable(GL_BLEND);
|
||||
scene_state.enable_gl_blend(true);
|
||||
|
||||
//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);
|
||||
@ -2689,7 +2719,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
if (rb.is_valid()) {
|
||||
_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);
|
||||
|
||||
@ -2700,6 +2733,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
||||
|
||||
void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_render_data) {
|
||||
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;
|
||||
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_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) {
|
||||
// Resolve if needed.
|
||||
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);
|
||||
}
|
||||
|
||||
// Rendered to intermediate buffer, must copy to our render target
|
||||
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_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);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
|
||||
} else if ((fbo_msaa_3d != 0 && msaa3d_needs_resolve) || (fbo_int != 0)) {
|
||||
// TODO investigate if it's smarter to cache these FBOs
|
||||
GLuint fbos[2]; // read and write
|
||||
glGenFramebuffers(2, fbos);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
|
||||
GLuint fbos[3]; // read, write and post
|
||||
glGenFramebuffers(3, fbos);
|
||||
|
||||
// Resolve if needed.
|
||||
if (fbo_msaa_3d != 0 && msaa3d_needs_resolve) {
|
||||
GLuint read_color = rb->get_msaa3d_color();
|
||||
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);
|
||||
}
|
||||
|
||||
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_COLOR_ATTACHMENT0, read_color, 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) {
|
||||
GLuint read_color = rb->get_internal_color();
|
||||
GLuint read_depth = rb->get_internal_depth();
|
||||
// Apply glow/bloom if requested? then populate our glow buffers
|
||||
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_depth = texture_storage->render_target_get_depth(render_target);
|
||||
|
||||
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_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
|
||||
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
|
||||
|
||||
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, 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);
|
||||
}
|
||||
}
|
||||
|
||||
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 (scene_state.current_depth_test != shader->depth_test) {
|
||||
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;
|
||||
}
|
||||
scene_state.enable_gl_depth_test(shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_ENABLED);
|
||||
}
|
||||
|
||||
if constexpr (p_pass_mode != PASS_MODE_SHADOW) {
|
||||
if (scene_state.current_depth_draw != shader->depth_draw) {
|
||||
switch (shader->depth_draw) {
|
||||
case GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE: {
|
||||
glDepthMask((p_pass_mode == PASS_MODE_COLOR && !GLES3::Config::get_singleton()->use_depth_prepass) ||
|
||||
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;
|
||||
}
|
||||
if (shader->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE) {
|
||||
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);
|
||||
} else {
|
||||
scene_state.enable_gl_depth_draw(shader->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_ALWAYS);
|
||||
}
|
||||
|
||||
scene_state.current_depth_draw = shader->depth_draw;
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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())) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
scene_state.set_gl_cull_mode(cull_mode);
|
||||
|
||||
RS::PrimitiveType primitive = surf->primitive;
|
||||
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 (uses_additive_lighting && !p_render_data->transparent_bg) {
|
||||
// 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);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
scene_state.reset_gl_state();
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
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);
|
||||
|
||||
@ -3530,14 +3602,10 @@ void RasterizerSceneGLES3::_render_uv2(const PagedArray<RenderGeometryInstance *
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
scene_state.reset_gl_state();
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
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;
|
||||
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);
|
||||
glViewport(0, 0, shadow_atlas_size, shadow_atlas_size);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glDepthMask(GL_TRUE);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glDisable(GL_CULL_FACE);
|
||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
||||
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||
|
||||
// Loop through quadrants and copy shadows over.
|
||||
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_A, GL_ONE);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
scene_state.enable_gl_depth_test(false);
|
||||
scene_state.enable_gl_depth_draw(false);
|
||||
|
||||
copy_effects->copy_to_rect(Rect2(Vector2(), Vector2(0.5, 0.5)));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
|
||||
|
@ -127,6 +127,8 @@ struct RenderDataGLES3 {
|
||||
uint32_t spot_light_count = 0;
|
||||
uint32_t omni_light_count = 0;
|
||||
|
||||
float luminance_multiplier = 1.0;
|
||||
|
||||
RenderingMethod::RenderInfo *render_info = nullptr;
|
||||
|
||||
/* Shadow data */
|
||||
@ -404,15 +406,14 @@ private:
|
||||
|
||||
float fog_height_density;
|
||||
float fog_depth_curve;
|
||||
float pad;
|
||||
float fog_sun_scatter;
|
||||
float fog_depth_begin;
|
||||
|
||||
float fog_light_color[3];
|
||||
float fog_depth_end;
|
||||
|
||||
float fog_sun_scatter;
|
||||
|
||||
float shadow_bias;
|
||||
float luminance_multiplier;
|
||||
uint32_t camera_visible_layers;
|
||||
bool pancake_shadows;
|
||||
};
|
||||
@ -442,10 +443,85 @@ private:
|
||||
bool used_depth_prepass = false;
|
||||
|
||||
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;
|
||||
|
||||
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 used_screen_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 _invalidate_sky(Sky *p_sky);
|
||||
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 _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);
|
||||
|
||||
// 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
|
||||
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("copy.glsl")
|
||||
env.GLES3_GLSL("scene.glsl")
|
||||
env.GLES3_GLSL("sky.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_copy.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")
|
||||
|
17
drivers/gles3/shaders/effects/SCsub
Normal file
17
drivers/gles3/shaders/effects/SCsub
Normal file
@ -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_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_screen = #define MODE_SIMPLE_COPY \n#define MODE_MULTIPLY
|
||||
mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR
|
||||
mode_mipmap = #define MODE_MIPMAP
|
||||
mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION
|
||||
@ -55,6 +56,10 @@ uniform float lod;
|
||||
uniform vec4 color_in;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_MULTIPLY
|
||||
uniform float multiply;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_GAUSSIAN_BLUR
|
||||
// Defined in 0-1 coords.
|
||||
uniform highp vec2 pixel_size;
|
||||
@ -105,10 +110,14 @@ void main() {
|
||||
vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), lod);
|
||||
#else
|
||||
vec4 color = texture(source, uv_interp);
|
||||
#endif
|
||||
#endif // USE_TEXTURE_3D
|
||||
|
||||
#ifdef MODE_MULTIPLY
|
||||
color *= multiply;
|
||||
#endif // MODE_MULTIPLY
|
||||
|
||||
frag_color = color;
|
||||
#endif
|
||||
#endif // MODE_SIMPLE_COPY
|
||||
|
||||
#ifdef MODE_SIMPLE_COLOR
|
||||
frag_color = color_in;
|
113
drivers/gles3/shaders/effects/glow.glsl
Normal file
113
drivers/gles3/shaders/effects/glow.glsl
Normal file
@ -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
|
||||
}
|
96
drivers/gles3/shaders/effects/post.glsl
Normal file
96
drivers/gles3/shaders/effects/post.glsl
Normal file
@ -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
|
||||
BASE_PASS = true
|
||||
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
|
||||
// these are false, we are doing a directional light pass.
|
||||
ADDITIVE_OMNI = false
|
||||
@ -185,18 +186,17 @@ layout(std140) uniform SceneData { // ubo:2
|
||||
uint fog_mode;
|
||||
float fog_density;
|
||||
float fog_height;
|
||||
float fog_height_density;
|
||||
|
||||
float fog_height_density;
|
||||
float fog_depth_curve;
|
||||
float pad;
|
||||
float fog_sun_scatter;
|
||||
float fog_depth_begin;
|
||||
|
||||
vec3 fog_light_color;
|
||||
float fog_depth_end;
|
||||
|
||||
float fog_sun_scatter;
|
||||
|
||||
float shadow_bias;
|
||||
float luminance_multiplier;
|
||||
uint camera_visible_layers;
|
||||
bool pancake_shadows;
|
||||
}
|
||||
@ -676,18 +676,17 @@ layout(std140) uniform SceneData { // ubo:2
|
||||
uint fog_mode;
|
||||
float fog_density;
|
||||
float fog_height;
|
||||
float fog_height_density;
|
||||
|
||||
float fog_height_density;
|
||||
float fog_depth_curve;
|
||||
float pad;
|
||||
float fog_sun_scatter;
|
||||
float fog_depth_begin;
|
||||
|
||||
vec3 fog_light_color;
|
||||
float fog_depth_end;
|
||||
|
||||
float fog_sun_scatter;
|
||||
|
||||
float shadow_bias;
|
||||
float luminance_multiplier;
|
||||
uint camera_visible_layers;
|
||||
bool pancake_shadows;
|
||||
}
|
||||
@ -1758,7 +1757,9 @@ void main() {
|
||||
|
||||
// Tonemap before writing as we are writing to an sRGB framebuffer
|
||||
frag_color.rgb *= exposure;
|
||||
#ifdef APPLY_TONEMAPPING
|
||||
frag_color.rgb = apply_tonemapping(frag_color.rgb, white);
|
||||
#endif
|
||||
frag_color.rgb = linear_to_srgb(frag_color.rgb);
|
||||
|
||||
#ifdef USE_BCS
|
||||
@ -1973,7 +1974,9 @@ void main() {
|
||||
|
||||
// Tonemap before writing as we are writing to an sRGB framebuffer
|
||||
additive_light_color *= exposure;
|
||||
#ifdef APPLY_TONEMAPPING
|
||||
additive_light_color = apply_tonemapping(additive_light_color, white);
|
||||
#endif
|
||||
additive_light_color = linear_to_srgb(additive_light_color);
|
||||
|
||||
#ifdef USE_BCS
|
||||
@ -1986,6 +1989,9 @@ void main() {
|
||||
|
||||
frag_color.rgb += additive_light_color;
|
||||
#endif // USE_ADDITIVE_LIGHTING
|
||||
|
||||
frag_color.rgb *= scene_data.luminance_multiplier;
|
||||
|
||||
#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_INVERTED_Y = true
|
||||
APPLY_TONEMAPPING = true
|
||||
|
||||
#[vertex]
|
||||
|
||||
@ -103,6 +104,7 @@ uniform mat4 orientation;
|
||||
uniform vec4 projection;
|
||||
uniform vec3 position;
|
||||
uniform float time;
|
||||
uniform float sky_energy_multiplier;
|
||||
uniform float luminance_multiplier;
|
||||
|
||||
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
|
||||
color = srgb_to_linear(color);
|
||||
color *= exposure;
|
||||
#ifdef APPLY_TONEMAPPING
|
||||
color = apply_tonemapping(color, white);
|
||||
#endif
|
||||
color = linear_to_srgb(color);
|
||||
|
||||
#ifdef USE_BCS
|
||||
@ -211,10 +215,10 @@ void main() {
|
||||
color = apply_color_correction(color, color_correction);
|
||||
#endif
|
||||
|
||||
frag_color.rgb = color;
|
||||
frag_color.rgb = color * luminance_multiplier;
|
||||
frag_color.a = alpha;
|
||||
|
||||
#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
|
||||
}
|
||||
|
@ -47,6 +47,13 @@
|
||||
#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
|
||||
#endif
|
||||
|
||||
RenderSceneBuffersGLES3::RenderSceneBuffersGLES3() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glow.levels[i].color = 0;
|
||||
glow.levels[i].fbo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
|
||||
free_render_buffer_data();
|
||||
}
|
||||
@ -137,9 +144,22 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||
//use_debanding = p_config->get_use_debanding();
|
||||
view_count = config->multiview_supported ? p_config->get_view_count() : 1;
|
||||
|
||||
ERR_FAIL_COND(view_count == 0);
|
||||
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
|
||||
if (scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF && internal_size.x == 0 && internal_size.y == 0) {
|
||||
// Disable, no size set.
|
||||
@ -153,14 +173,38 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||
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) {
|
||||
// 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;
|
||||
|
||||
// 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_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.
|
||||
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_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.
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// Setup MSAA.
|
||||
const GLsizei samples[] = { 1, 2, 4, 8 };
|
||||
@ -255,9 +287,6 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||
msaa3d.needs_resolve = true;
|
||||
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.
|
||||
glGenRenderbuffers(1, &msaa3d.color);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, msaa3d.color);
|
||||
@ -282,6 +311,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
_clear_msaa3d_buffers();
|
||||
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||
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.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.
|
||||
glGenTextures(1, &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);
|
||||
#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.
|
||||
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);
|
||||
#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.
|
||||
glGenFramebuffers(1, &msaa3d.fbo);
|
||||
@ -330,6 +357,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
_clear_msaa3d_buffers();
|
||||
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||
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);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
_clear_msaa3d_buffers();
|
||||
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
|
||||
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);
|
||||
|
||||
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;
|
||||
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) {
|
||||
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_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
|
||||
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_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
|
||||
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() {
|
||||
_clear_msaa3d_buffers();
|
||||
_clear_intermediate_buffers();
|
||||
_clear_back_buffers();
|
||||
_clear_glow_buffers();
|
||||
}
|
||||
|
||||
GLuint RenderSceneBuffersGLES3::get_render_fbo() {
|
||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||
GLuint rt_fbo = 0;
|
||||
|
||||
_check_render_buffers();
|
||||
|
||||
if (msaa3d.check_fbo_cache) {
|
||||
GLuint color = texture_storage->render_target_get_color(render_target);
|
||||
GLuint depth = texture_storage->render_target_get_depth(render_target);
|
||||
|
||||
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) {
|
||||
// We have an MSAA fbo, render to our MSAA buffer
|
||||
return msaa3d.fbo;
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "drivers/gles3/effects/glow.h"
|
||||
#include "servers/rendering/storage/render_scene_buffers.h"
|
||||
|
||||
#include "platform_gl.h"
|
||||
@ -52,6 +53,12 @@ public:
|
||||
|
||||
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 {
|
||||
GLuint color = 0;
|
||||
GLuint depth = 0;
|
||||
@ -74,31 +81,24 @@ public:
|
||||
|
||||
FBDEF backbuffer3d; // our back buffer
|
||||
|
||||
// Built-in textures used for ping pong image processing and blurring.
|
||||
struct Blur {
|
||||
RID texture;
|
||||
|
||||
struct Mipmap {
|
||||
RID texture;
|
||||
int width;
|
||||
int height;
|
||||
GLuint fbo;
|
||||
};
|
||||
|
||||
Vector<Mipmap> mipmaps;
|
||||
};
|
||||
|
||||
Blur blur[2]; //the second one starts from the first mipmap
|
||||
// Buffers for our glow implementation
|
||||
struct GLOW {
|
||||
bool glow_enabled = false;
|
||||
GLES3::Glow::GLOWLEVEL levels[4];
|
||||
} glow;
|
||||
|
||||
private:
|
||||
void _check_render_buffers();
|
||||
void _clear_msaa3d_buffers();
|
||||
void _clear_intermediate_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);
|
||||
GLuint _rt_get_cached_fbo(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count);
|
||||
|
||||
public:
|
||||
RenderSceneBuffersGLES3();
|
||||
virtual ~RenderSceneBuffersGLES3();
|
||||
virtual void configure(const RenderSceneBuffersConfiguration *p_config) override;
|
||||
|
||||
@ -109,19 +109,45 @@ public:
|
||||
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_glow_buffers(); // Check if we need to initialise our glow buffers.
|
||||
|
||||
GLuint get_render_fbo();
|
||||
GLuint get_msaa3d_fbo() const { return msaa3d.fbo; }
|
||||
GLuint get_msaa3d_color() const { return msaa3d.color; }
|
||||
GLuint get_msaa3d_depth() const { return msaa3d.depth; }
|
||||
bool get_msaa_needs_resolve() const { return msaa3d.needs_resolve; }
|
||||
GLuint get_internal_fbo() const { return internal3d.fbo; }
|
||||
GLuint get_internal_color() const { return internal3d.color; }
|
||||
GLuint get_internal_depth() const { return internal3d.depth; }
|
||||
GLuint get_msaa3d_fbo() {
|
||||
_check_render_buffers();
|
||||
return msaa3d.fbo;
|
||||
}
|
||||
GLuint get_msaa3d_color() {
|
||||
_check_render_buffers();
|
||||
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() const { return backbuffer3d.color; }
|
||||
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
|
||||
|
||||
_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();
|
||||
|
||||
rt->color_internal_format = rt->is_transparent ? GL_RGBA8 : GL_RGB10_A2;
|
||||
rt->color_format = GL_RGBA;
|
||||
rt->color_type = rt->is_transparent ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
rt->image_format = Image::FORMAT_RGBA8;
|
||||
if (rt->hdr) {
|
||||
rt->color_internal_format = GL_RGBA16F;
|
||||
rt->color_format = GL_RGBA;
|
||||
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);
|
||||
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_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
|
||||
if (use_multiview) {
|
||||
@ -2194,7 +2209,7 @@ void GLES3::TextureStorage::check_backbuffer(RenderTarget *rt, const bool uses_s
|
||||
} else {
|
||||
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_MIN_FILTER, GL_NEAREST);
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL(rt);
|
||||
|
@ -347,9 +347,11 @@ struct RenderTarget {
|
||||
GLuint backbuffer = 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_format = GL_RGBA;
|
||||
GLuint color_type = GL_UNSIGNED_BYTE;
|
||||
uint32_t color_format_size = 4;
|
||||
Image::Format image_format = Image::FORMAT_RGBA8;
|
||||
|
||||
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 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_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 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;
|
||||
|
||||
// new
|
||||
void render_target_set_as_unused(RID p_render_target) override {
|
||||
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;
|
||||
bool render_target_is_clear_requested(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;
|
||||
}
|
||||
|
||||
if (p_property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) {
|
||||
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
|
||||
// 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") {
|
||||
|
@ -417,11 +417,6 @@ void RendererEnvironmentStorage::environment_set_glow(RID p_env, bool p_enable,
|
||||
Environment *env = environment_owner.get_or_null(p_env);
|
||||
ERR_FAIL_NULL(env);
|
||||
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_levels = p_levels;
|
||||
env->glow_intensity = p_intensity;
|
||||
|
Loading…
Reference in New Issue
Block a user