initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
6
drivers/gles3/effects/SCsub
Normal file
6
drivers/gles3/effects/SCsub
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
env.add_source_files(env.drivers_sources, "*.cpp")
|
335
drivers/gles3/effects/copy_effects.cpp
Normal file
335
drivers/gles3/effects/copy_effects.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
/**************************************************************************/
|
||||
/* copy_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 "copy_effects.h"
|
||||
#include "../storage/texture_storage.h"
|
||||
|
||||
using namespace GLES3;
|
||||
|
||||
CopyEffects *CopyEffects::singleton = nullptr;
|
||||
|
||||
CopyEffects *CopyEffects::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
CopyEffects::CopyEffects() {
|
||||
singleton = this;
|
||||
|
||||
copy.shader.initialize();
|
||||
copy.shader_version = copy.shader.version_create();
|
||||
copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::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
|
||||
}
|
||||
|
||||
{ // Screen Quad
|
||||
|
||||
glGenBuffers(1, &quad);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quad);
|
||||
|
||||
const float qv[12] = {
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
1.0f,
|
||||
-1.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
-1.0f,
|
||||
1.0f,
|
||||
};
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 12, qv, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||
|
||||
glGenVertexArrays(1, &quad_array);
|
||||
glBindVertexArray(quad_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quad);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
CopyEffects::~CopyEffects() {
|
||||
singleton = nullptr;
|
||||
glDeleteBuffers(1, &screen_triangle);
|
||||
glDeleteVertexArrays(1, &screen_triangle_array);
|
||||
glDeleteBuffers(1, &quad);
|
||||
glDeleteVertexArrays(1, &quad_array);
|
||||
copy.shader.version_free(copy.shader_version);
|
||||
}
|
||||
|
||||
void CopyEffects::copy_to_rect(const Rect2 &p_rect, bool p_linear_to_srgb) {
|
||||
uint64_t specializations = p_linear_to_srgb ? CopyShaderGLES3::CONVERT_LINEAR_TO_SRGB : 0;
|
||||
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION, specializations);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION, specializations);
|
||||
draw_screen_quad();
|
||||
}
|
||||
|
||||
void CopyEffects::copy_to_rect_3d(const Rect2 &p_rect, float p_layer, int p_type, float p_lod, bool p_linear_to_srgb) {
|
||||
ERR_FAIL_COND(p_type != Texture::TYPE_LAYERED && p_type != Texture::TYPE_3D);
|
||||
|
||||
CopyShaderGLES3::ShaderVariant variant = p_type == Texture::TYPE_LAYERED
|
||||
? CopyShaderGLES3::MODE_COPY_SECTION_2D_ARRAY
|
||||
: CopyShaderGLES3::MODE_COPY_SECTION_3D;
|
||||
uint64_t specializations = p_linear_to_srgb ? CopyShaderGLES3::CONVERT_LINEAR_TO_SRGB : 0;
|
||||
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, variant, specializations);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::LAYER, p_layer, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::LOD, p_lod, copy.shader_version, variant, specializations);
|
||||
draw_screen_quad();
|
||||
}
|
||||
|
||||
void CopyEffects::copy_with_lens_distortion(const Rect2 &p_rect, float p_layer, const Vector2 &p_eye_center, float p_k1, float p_k2, float p_upscale, float p_aspect_ration, bool p_linear_to_srgb) {
|
||||
CopyShaderGLES3::ShaderVariant variant = CopyShaderGLES3::MODE_LENS_DISTORTION;
|
||||
|
||||
uint64_t specializations = p_linear_to_srgb ? CopyShaderGLES3::CONVERT_LINEAR_TO_SRGB : 0;
|
||||
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, variant, specializations);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::LAYER, p_layer, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::LOD, 0.0, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::EYE_CENTER, p_eye_center.x, p_eye_center.y, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::K1, p_k1, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::K2, p_k1, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::UPSCALE, p_upscale, copy.shader_version, variant, specializations);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::ASPECT_RATIO, p_aspect_ration, copy.shader_version, variant, specializations);
|
||||
|
||||
draw_screen_quad();
|
||||
}
|
||||
|
||||
void CopyEffects::copy_to_and_from_rect(const Rect2 &p_rect) {
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION_SOURCE);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION_SOURCE);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::SOURCE_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION_SOURCE);
|
||||
|
||||
draw_screen_quad();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void CopyEffects::copy_cube_to_rect(const Rect2 &p_rect) {
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_OCTAHEDRAL);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_OCTAHEDRAL);
|
||||
draw_screen_quad();
|
||||
}
|
||||
|
||||
void CopyEffects::copy_cube_to_panorama(float p_mip_level) {
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_PANORAMA);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::MIP_LEVEL, p_mip_level, copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_PANORAMA);
|
||||
draw_screen_quad();
|
||||
}
|
||||
|
||||
// Intended for efficiently mipmapping textures.
|
||||
void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region) {
|
||||
GLuint framebuffers[2];
|
||||
glGenFramebuffers(2, framebuffers);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, 0);
|
||||
|
||||
Rect2i source_region = p_region;
|
||||
Rect2i dest_region = p_region;
|
||||
for (int i = 1; i < p_mipmap_count; i++) {
|
||||
dest_region.position.x >>= 1;
|
||||
dest_region.position.y >>= 1;
|
||||
dest_region.size = Size2i(dest_region.size.x >> 1, dest_region.size.y >> 1).maxi(1);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[i % 2]);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, i);
|
||||
glBlitFramebuffer(source_region.position.x, source_region.position.y, source_region.position.x + source_region.size.x, source_region.position.y + source_region.size.y,
|
||||
dest_region.position.x, dest_region.position.y, dest_region.position.x + dest_region.size.x, dest_region.position.y + dest_region.size.y, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[i % 2]);
|
||||
source_region = dest_region;
|
||||
}
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
||||
glDeleteFramebuffers(2, framebuffers);
|
||||
}
|
||||
|
||||
// Intended for approximating a gaussian blur. Used for 2D backbuffer mipmaps. Slightly less efficient than bilinear_blur().
|
||||
void CopyEffects::gaussian_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region, const Size2i &p_size) {
|
||||
GLuint framebuffer;
|
||||
glGenFramebuffers(1, &framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, p_source_texture);
|
||||
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);
|
||||
|
||||
Size2i base_size = p_size;
|
||||
|
||||
Rect2i source_region = p_region;
|
||||
Rect2i dest_region = p_region;
|
||||
|
||||
Size2 float_size = Size2(p_size);
|
||||
Rect2 normalized_source_region = Rect2(p_region);
|
||||
normalized_source_region.position = normalized_source_region.position / float_size;
|
||||
normalized_source_region.size = normalized_source_region.size / float_size;
|
||||
Rect2 normalized_dest_region = Rect2(p_region);
|
||||
for (int i = 1; i < p_mipmap_count; i++) {
|
||||
dest_region.position.x >>= 1;
|
||||
dest_region.position.y >>= 1;
|
||||
dest_region.size = Size2i(dest_region.size.x >> 1, dest_region.size.y >> 1).maxi(1);
|
||||
base_size.x >>= 1;
|
||||
base_size.y >>= 1;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, p_source_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, i - 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, i);
|
||||
#ifdef DEV_ENABLED
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
WARN_PRINT("Could not bind Gaussian blur framebuffer, status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status));
|
||||
}
|
||||
#endif
|
||||
|
||||
glViewport(0, 0, base_size.x, base_size.y);
|
||||
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_GAUSSIAN_BLUR);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
float_size = Size2(base_size);
|
||||
normalized_dest_region.position = Size2(dest_region.position) / float_size;
|
||||
normalized_dest_region.size = Size2(dest_region.size) / float_size;
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, normalized_dest_region.position.x, normalized_dest_region.position.y, normalized_dest_region.size.x, normalized_dest_region.size.y, copy.shader_version, CopyShaderGLES3::MODE_GAUSSIAN_BLUR);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::SOURCE_SECTION, normalized_source_region.position.x, normalized_source_region.position.y, normalized_source_region.size.x, normalized_source_region.size.y, copy.shader_version, CopyShaderGLES3::MODE_GAUSSIAN_BLUR);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::PIXEL_SIZE, 1.0 / float_size.x, 1.0 / float_size.y, copy.shader_version, CopyShaderGLES3::MODE_GAUSSIAN_BLUR);
|
||||
|
||||
draw_screen_quad();
|
||||
|
||||
source_region = dest_region;
|
||||
normalized_source_region = normalized_dest_region;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
||||
glDeleteFramebuffers(1, &framebuffer);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, p_mipmap_count - 1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glViewport(0, 0, p_size.x, p_size.y);
|
||||
}
|
||||
|
||||
void CopyEffects::set_color(const Color &p_color, const Rect2i &p_region) {
|
||||
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_region.position.x, p_region.position.y, p_region.size.x, p_region.size.y, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
|
||||
copy.shader.version_set_uniform(CopyShaderGLES3::COLOR_IN, p_color, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
|
||||
draw_screen_quad();
|
||||
}
|
||||
|
||||
void CopyEffects::draw_screen_triangle() {
|
||||
glBindVertexArray(screen_triangle_array);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void CopyEffects::draw_screen_quad() {
|
||||
glBindVertexArray(quad_array);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
#endif // GLES3_ENABLED
|
79
drivers/gles3/effects/copy_effects.h
Normal file
79
drivers/gles3/effects/copy_effects.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**************************************************************************/
|
||||
/* copy_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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "drivers/gles3/shaders/effects/copy.glsl.gen.h"
|
||||
|
||||
namespace GLES3 {
|
||||
|
||||
class CopyEffects {
|
||||
private:
|
||||
struct Copy {
|
||||
CopyShaderGLES3 shader;
|
||||
RID shader_version;
|
||||
} copy;
|
||||
|
||||
static CopyEffects *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;
|
||||
|
||||
// Use for rect-based effects.
|
||||
GLuint quad = 0;
|
||||
GLuint quad_array = 0;
|
||||
|
||||
public:
|
||||
static CopyEffects *get_singleton();
|
||||
|
||||
CopyEffects();
|
||||
~CopyEffects();
|
||||
|
||||
// These functions assume that a framebuffer and texture are bound already. They only manage the shader, uniforms, and vertex array.
|
||||
void copy_to_rect(const Rect2 &p_rect, bool p_linear_to_srgb = false);
|
||||
void copy_to_rect_3d(const Rect2 &p_rect, float p_layer, int p_type, float p_lod = 0.0f, bool p_linear_to_srgb = false);
|
||||
void copy_with_lens_distortion(const Rect2 &p_rect, float p_layer, const Vector2 &p_eye_center, float p_k1, float p_k2, float p_upscale, float p_aspect_ration, bool p_linear_to_srgb = false);
|
||||
void copy_to_and_from_rect(const Rect2 &p_rect);
|
||||
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);
|
||||
void gaussian_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region, const Size2i &p_size);
|
||||
void set_color(const Color &p_color, const Rect2i &p_region);
|
||||
void draw_screen_triangle();
|
||||
void draw_screen_quad();
|
||||
};
|
||||
|
||||
} //namespace GLES3
|
||||
|
||||
#endif // GLES3_ENABLED
|
213
drivers/gles3/effects/cubemap_filter.cpp
Normal file
213
drivers/gles3/effects/cubemap_filter.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/**************************************************************************/
|
||||
/* cubemap_filter.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 "cubemap_filter.h"
|
||||
|
||||
#include "../storage/texture_storage.h"
|
||||
#include "core/config/project_settings.h"
|
||||
|
||||
using namespace GLES3;
|
||||
|
||||
CubemapFilter *CubemapFilter::singleton = nullptr;
|
||||
|
||||
CubemapFilter::CubemapFilter() {
|
||||
singleton = this;
|
||||
// Use a factor 4 larger for the compatibility renderer to make up for the fact
|
||||
// That we don't use an array texture. We will reduce samples on low roughness
|
||||
// to compensate.
|
||||
ggx_samples = 4 * uint32_t(GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples"));
|
||||
|
||||
{
|
||||
String defines;
|
||||
defines += "\n#define MAX_SAMPLE_COUNT " + itos(ggx_samples) + "\n";
|
||||
cubemap_filter.shader.initialize(defines);
|
||||
cubemap_filter.shader_version = cubemap_filter.shader.version_create();
|
||||
}
|
||||
|
||||
{ // Screen Triangle.
|
||||
glGenBuffers(1, &screen_triangle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, screen_triangle);
|
||||
|
||||
const float qv[6] = {
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
3.0f,
|
||||
3.0f,
|
||||
-1.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
|
||||
}
|
||||
}
|
||||
|
||||
CubemapFilter::~CubemapFilter() {
|
||||
glDeleteBuffers(1, &screen_triangle);
|
||||
glDeleteVertexArrays(1, &screen_triangle_array);
|
||||
|
||||
cubemap_filter.shader.version_free(cubemap_filter.shader_version);
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
// Helper functions for IBL filtering
|
||||
|
||||
Vector3 importance_sample_GGX(Vector2 xi, float roughness4) {
|
||||
// Compute distribution direction
|
||||
float phi = 2.0 * Math::PI * xi.x;
|
||||
float cos_theta = std::sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y));
|
||||
float sin_theta = std::sqrt(1.0 - cos_theta * cos_theta);
|
||||
|
||||
// Convert to spherical direction
|
||||
Vector3 half_vector;
|
||||
half_vector.x = sin_theta * std::cos(phi);
|
||||
half_vector.y = sin_theta * std::sin(phi);
|
||||
half_vector.z = cos_theta;
|
||||
|
||||
return half_vector;
|
||||
}
|
||||
|
||||
float distribution_GGX(float NdotH, float roughness4) {
|
||||
float NdotH2 = NdotH * NdotH;
|
||||
float denom = (NdotH2 * (roughness4 - 1.0) + 1.0);
|
||||
denom = Math::PI * denom * denom;
|
||||
|
||||
return roughness4 / denom;
|
||||
}
|
||||
|
||||
float radical_inverse_vdC(uint32_t bits) {
|
||||
bits = (bits << 16) | (bits >> 16);
|
||||
bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1);
|
||||
bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2);
|
||||
bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4);
|
||||
bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8);
|
||||
|
||||
return float(bits) * 2.3283064365386963e-10;
|
||||
}
|
||||
|
||||
Vector2 hammersley(uint32_t i, uint32_t N) {
|
||||
return Vector2(float(i) / float(N), radical_inverse_vdC(i));
|
||||
}
|
||||
|
||||
void CubemapFilter::filter_radiance(GLuint p_source_cubemap, GLuint p_dest_cubemap, GLuint p_dest_framebuffer, int p_source_size, int p_mipmap_count, int p_layer) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, p_source_cubemap);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, p_dest_framebuffer);
|
||||
|
||||
CubemapFilterShaderGLES3::ShaderVariant mode = CubemapFilterShaderGLES3::MODE_DEFAULT;
|
||||
|
||||
if (p_layer == 0) {
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
// Copy over base layer without filtering.
|
||||
mode = CubemapFilterShaderGLES3::MODE_COPY;
|
||||
}
|
||||
|
||||
int size = p_source_size >> p_layer;
|
||||
glViewport(0, 0, size, size);
|
||||
glBindVertexArray(screen_triangle_array);
|
||||
|
||||
bool success = cubemap_filter.shader.version_bind_shader(cubemap_filter.shader_version, mode);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_layer > 0) {
|
||||
const uint32_t sample_counts[5] = { 1, ggx_samples / 16, ggx_samples / 8, ggx_samples / 4, ggx_samples };
|
||||
uint32_t sample_count = sample_counts[MIN(4, p_layer)];
|
||||
|
||||
float roughness = float(p_layer) / (p_mipmap_count - 1);
|
||||
roughness *= roughness; // Convert to non-perceptual roughness.
|
||||
float roughness4 = roughness * roughness;
|
||||
roughness4 *= roughness4;
|
||||
|
||||
float solid_angle_texel = 4.0 * Math::PI / float(6 * size * size);
|
||||
|
||||
LocalVector<float> sample_directions;
|
||||
sample_directions.resize(4 * sample_count);
|
||||
|
||||
uint32_t index = 0;
|
||||
float weight = 0.0;
|
||||
for (uint32_t i = 0; i < sample_count; i++) {
|
||||
Vector2 xi = hammersley(i, sample_count);
|
||||
Vector3 dir = importance_sample_GGX(xi, roughness4);
|
||||
Vector3 light_vec = (2.0 * dir.z * dir - Vector3(0.0, 0.0, 1.0));
|
||||
|
||||
if (light_vec.z <= 0.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sample_directions[index * 4] = light_vec.x;
|
||||
sample_directions[index * 4 + 1] = light_vec.y;
|
||||
sample_directions[index * 4 + 2] = light_vec.z;
|
||||
|
||||
float D = distribution_GGX(dir.z, roughness4);
|
||||
float pdf = D * dir.z / (4.0 * dir.z) + 0.0001;
|
||||
|
||||
float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001);
|
||||
|
||||
float mip_level = MAX(0.5 * std::log2(solid_angle_sample / solid_angle_texel) + float(MAX(1, p_layer - 3)), 1.0);
|
||||
|
||||
sample_directions[index * 4 + 3] = mip_level;
|
||||
weight += light_vec.z;
|
||||
index++;
|
||||
}
|
||||
|
||||
glUniform4fv(cubemap_filter.shader.version_get_uniform(CubemapFilterShaderGLES3::SAMPLE_DIRECTIONS_MIP, cubemap_filter.shader_version, mode), sample_count, sample_directions.ptr());
|
||||
cubemap_filter.shader.version_set_uniform(CubemapFilterShaderGLES3::WEIGHT, weight, cubemap_filter.shader_version, mode);
|
||||
cubemap_filter.shader.version_set_uniform(CubemapFilterShaderGLES3::SAMPLE_COUNT, index, cubemap_filter.shader_version, mode);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, p_dest_cubemap, p_layer);
|
||||
#ifdef DEBUG_ENABLED
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
WARN_PRINT("Could not bind sky radiance face: " + itos(i) + ", status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status));
|
||||
}
|
||||
#endif
|
||||
cubemap_filter.shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_ID, i, cubemap_filter.shader_version, mode);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
||||
}
|
||||
|
||||
#endif // GLES3_ENABLED
|
67
drivers/gles3/effects/cubemap_filter.h
Normal file
67
drivers/gles3/effects/cubemap_filter.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**************************************************************************/
|
||||
/* cubemap_filter.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "drivers/gles3/shaders/effects/cubemap_filter.glsl.gen.h"
|
||||
|
||||
namespace GLES3 {
|
||||
|
||||
class CubemapFilter {
|
||||
private:
|
||||
struct CMF {
|
||||
CubemapFilterShaderGLES3 shader;
|
||||
RID shader_version;
|
||||
} cubemap_filter;
|
||||
|
||||
static CubemapFilter *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;
|
||||
|
||||
uint32_t ggx_samples = 128;
|
||||
|
||||
public:
|
||||
static CubemapFilter *get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
CubemapFilter();
|
||||
~CubemapFilter();
|
||||
|
||||
void filter_radiance(GLuint p_source_cubemap, GLuint p_dest_cubemap, GLuint p_dest_framebuffer, int p_source_size, int p_mipmap_count, int p_layer);
|
||||
};
|
||||
|
||||
} //namespace GLES3
|
||||
|
||||
#endif // GLES3_ENABLED
|
128
drivers/gles3/effects/feed_effects.cpp
Normal file
128
drivers/gles3/effects/feed_effects.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/**************************************************************************/
|
||||
/* feed_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 "feed_effects.h"
|
||||
|
||||
#ifdef ANDROID_ENABLED
|
||||
#include <GLES3/gl3ext.h>
|
||||
#endif
|
||||
|
||||
#define GL_PROGRAM_POINT_SIZE 0x8642
|
||||
|
||||
using namespace GLES3;
|
||||
|
||||
FeedEffects *FeedEffects::singleton = nullptr;
|
||||
|
||||
FeedEffects *FeedEffects::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
FeedEffects::FeedEffects() {
|
||||
singleton = this;
|
||||
|
||||
feed.shader.initialize();
|
||||
feed.shader_version = feed.shader.version_create();
|
||||
feed.shader.version_bind_shader(feed.shader_version, FeedShaderGLES3::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
|
||||
}
|
||||
}
|
||||
|
||||
FeedEffects::~FeedEffects() {
|
||||
singleton = nullptr;
|
||||
glDeleteBuffers(1, &screen_triangle);
|
||||
glDeleteVertexArrays(1, &screen_triangle_array);
|
||||
feed.shader.version_free(feed.shader_version);
|
||||
}
|
||||
|
||||
Transform3D transform3D_from_mat4(const float *p_mat4) {
|
||||
Transform3D res;
|
||||
|
||||
res.basis.rows[0][0] = p_mat4[0];
|
||||
res.basis.rows[1][0] = p_mat4[1];
|
||||
res.basis.rows[2][0] = p_mat4[2];
|
||||
// p_mat4[3] = 0;
|
||||
res.basis.rows[0][1] = p_mat4[4];
|
||||
res.basis.rows[1][1] = p_mat4[5];
|
||||
res.basis.rows[2][1] = p_mat4[6];
|
||||
// p_mat4[7] = 0;
|
||||
res.basis.rows[0][2] = p_mat4[8];
|
||||
res.basis.rows[1][2] = p_mat4[9];
|
||||
res.basis.rows[2][2] = p_mat4[10];
|
||||
// p_mat4[11] = 0;
|
||||
res.origin.x = p_mat4[12];
|
||||
res.origin.y = p_mat4[13];
|
||||
res.origin.z = p_mat4[14];
|
||||
// p_mat4[15] = 1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void FeedEffects::draw() {
|
||||
bool success = feed.shader.version_bind_shader(feed.shader_version, FeedShaderGLES3::MODE_DEFAULT, FeedShaderGLES3::USE_EXTERNAL_SAMPLER);
|
||||
if (!success) {
|
||||
OS::get_singleton()->print("Godot : FeedShaderGLES3 Could not bind version_bind_shader USE_EXTERNAL_SAMPLER");
|
||||
return;
|
||||
}
|
||||
|
||||
draw_screen_triangle();
|
||||
}
|
||||
|
||||
void FeedEffects::draw_screen_triangle() {
|
||||
glBindVertexArray(screen_triangle_array);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
#endif // GLES3_ENABLED
|
66
drivers/gles3/effects/feed_effects.h
Normal file
66
drivers/gles3/effects/feed_effects.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**************************************************************************/
|
||||
/* feed_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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "drivers/gles3/shader_gles3.h"
|
||||
#include "drivers/gles3/shaders/feed.glsl.gen.h"
|
||||
|
||||
namespace GLES3 {
|
||||
|
||||
class FeedEffects {
|
||||
private:
|
||||
struct Feed {
|
||||
FeedShaderGLES3 shader;
|
||||
RID shader_version;
|
||||
} feed;
|
||||
|
||||
static FeedEffects *singleton;
|
||||
|
||||
GLuint screen_triangle = 0;
|
||||
GLuint screen_triangle_array = 0;
|
||||
|
||||
public:
|
||||
static FeedEffects *get_singleton();
|
||||
|
||||
FeedEffects();
|
||||
~FeedEffects();
|
||||
|
||||
void draw();
|
||||
|
||||
private:
|
||||
void draw_screen_triangle();
|
||||
};
|
||||
|
||||
} // namespace GLES3
|
||||
|
||||
#endif // GLES3_ENABLED
|
173
drivers/gles3/effects/glow.cpp
Normal file
173
drivers/gles3/effects/glow.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/**************************************************************************/
|
||||
/* 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"
|
||||
#include "../storage/texture_storage.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, GLES3::TextureStorage::system_fbo);
|
||||
}
|
||||
|
||||
#endif // GLES3_ENABLED
|
86
drivers/gles3/effects/glow.h
Normal file
86
drivers/gles3/effects/glow.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************/
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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
|
153
drivers/gles3/effects/post_effects.cpp
Normal file
153
drivers/gles3/effects/post_effects.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/**************************************************************************/
|
||||
/* 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"
|
||||
#include "../storage/texture_storage.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, uint64_t p_spec_constants) {
|
||||
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 = p_spec_constants;
|
||||
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, GLES3::TextureStorage::system_fbo);
|
||||
}
|
||||
|
||||
#endif // GLES3_ENABLED
|
66
drivers/gles3/effects/post_effects.h
Normal file
66
drivers/gles3/effects/post_effects.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**************************************************************************/
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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, uint64_t p_spec_constants = 0);
|
||||
};
|
||||
|
||||
} //namespace GLES3
|
||||
|
||||
#endif // GLES3_ENABLED
|
Reference in New Issue
Block a user