Several fixes to make GLES2 on HTML5 work much better.
Changed math class error reporting to be a bit less paranoid.
This commit is contained in:
parent
51c1d55cf9
commit
a32b26dfa2
16 changed files with 315 additions and 100 deletions
|
@ -141,6 +141,7 @@ opts.Add(EnumVariable('target', "Compilation target", 'debug', ('debug', 'releas
|
|||
opts.Add(EnumVariable('optimize', "Optimization type", 'speed', ('speed', 'size')))
|
||||
opts.Add(BoolVariable('tools', "Build the tools (a.k.a. the Godot editor)", True))
|
||||
opts.Add(BoolVariable('use_lto', 'Use link-time optimization', False))
|
||||
opts.Add(BoolVariable('use_precise_math_checks', 'Math checks use very precise epsilon (useful to debug the engine)', False))
|
||||
|
||||
# Components
|
||||
opts.Add(BoolVariable('deprecated', "Enable deprecated features", True))
|
||||
|
@ -224,6 +225,9 @@ env_base.Append(CPPPATH=['#editor', '#'])
|
|||
env_base.platform_exporters = platform_exporters
|
||||
env_base.platform_apis = platform_apis
|
||||
|
||||
if (env_base["use_precise_math_checks"]):
|
||||
env_base.Append(CPPDEFINES=['PRECISE_MATH_CHECKS'])
|
||||
|
||||
if (env_base['target'] == 'debug'):
|
||||
env_base.Append(CPPDEFINES=['DEBUG_MEMORY_ALLOC','DISABLE_FORCED_INLINE'])
|
||||
|
||||
|
|
|
@ -76,15 +76,23 @@ void Basis::invert() {
|
|||
}
|
||||
|
||||
void Basis::orthonormalize() {
|
||||
/* this check is undesired, the matrix could be wrong but we still may want to generate a valid one
|
||||
* for practical purposes
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND(determinant() == 0);
|
||||
#endif
|
||||
*/
|
||||
// Gram-Schmidt Process
|
||||
|
||||
Vector3 x = get_axis(0);
|
||||
Vector3 y = get_axis(1);
|
||||
Vector3 z = get_axis(2);
|
||||
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND(x.length_squared() == 0);
|
||||
ERR_FAIL_COND(y.length_squared() == 0);
|
||||
ERR_FAIL_COND(z.length_squared() == 0);
|
||||
#endif
|
||||
x.normalize();
|
||||
y = (y - x * (x.dot(y)));
|
||||
y.normalize();
|
||||
|
@ -118,16 +126,16 @@ bool Basis::is_diagonal() const {
|
|||
}
|
||||
|
||||
bool Basis::is_rotation() const {
|
||||
return Math::is_equal_approx(determinant(), 1) && is_orthogonal();
|
||||
return Math::is_equal_approx(determinant(), 1, UNIT_EPSILON) && is_orthogonal();
|
||||
}
|
||||
|
||||
bool Basis::is_symmetric() const {
|
||||
|
||||
if (!Math::is_equal_approx(elements[0][1], elements[1][0]))
|
||||
if (!Math::is_equal_approx_ratio(elements[0][1], elements[1][0], UNIT_EPSILON))
|
||||
return false;
|
||||
if (!Math::is_equal_approx(elements[0][2], elements[2][0]))
|
||||
if (!Math::is_equal_approx_ratio(elements[0][2], elements[2][0], UNIT_EPSILON))
|
||||
return false;
|
||||
if (!Math::is_equal_approx(elements[1][2], elements[2][1]))
|
||||
if (!Math::is_equal_approx_ratio(elements[1][2], elements[2][1], UNIT_EPSILON))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -488,6 +496,11 @@ void Basis::set_euler_xyz(const Vector3 &p_euler) {
|
|||
// as the x, y, and z components of a Vector3 respectively.
|
||||
Vector3 Basis::get_euler_yxz() const {
|
||||
|
||||
/* checking this is a bad idea, because obtaining from scaled transform is a valid use case
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND(!is_rotation());
|
||||
#endif
|
||||
*/
|
||||
// Euler angles in YXZ convention.
|
||||
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
|
||||
//
|
||||
|
@ -496,9 +509,7 @@ Vector3 Basis::get_euler_yxz() const {
|
|||
// cy*sx*sz-cz*sy cy*cz*sx+sy*sz cy*cx
|
||||
|
||||
Vector3 euler;
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V(!is_rotation(), euler);
|
||||
#endif
|
||||
|
||||
real_t m12 = elements[1][2];
|
||||
|
||||
if (m12 < 1) {
|
||||
|
@ -556,7 +567,7 @@ bool Basis::is_equal_approx(const Basis &a, const Basis &b) const {
|
|||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (!Math::is_equal_approx(a.elements[i][j], b.elements[i][j]))
|
||||
if (!Math::is_equal_approx_ratio(a.elements[i][j], b.elements[i][j], UNIT_EPSILON))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -599,10 +610,14 @@ Basis::operator String() const {
|
|||
}
|
||||
|
||||
Quat Basis::get_quat() const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V(!is_rotation(), Quat());
|
||||
#endif
|
||||
real_t trace = elements[0][0] + elements[1][1] + elements[2][2];
|
||||
|
||||
/* Allow getting a quaternion from an unnormalized transform */
|
||||
Basis m = *this;
|
||||
m.elements[0].normalize();
|
||||
m.elements[1].normalize();
|
||||
m.elements[2].normalize();
|
||||
|
||||
real_t trace = m.elements[0][0] + m.elements[1][1] + m.elements[2][2];
|
||||
real_t temp[4];
|
||||
|
||||
if (trace > 0.0) {
|
||||
|
@ -610,23 +625,23 @@ Quat Basis::get_quat() const {
|
|||
temp[3] = (s * 0.5);
|
||||
s = 0.5 / s;
|
||||
|
||||
temp[0] = ((elements[2][1] - elements[1][2]) * s);
|
||||
temp[1] = ((elements[0][2] - elements[2][0]) * s);
|
||||
temp[2] = ((elements[1][0] - elements[0][1]) * s);
|
||||
temp[0] = ((m.elements[2][1] - m.elements[1][2]) * s);
|
||||
temp[1] = ((m.elements[0][2] - m.elements[2][0]) * s);
|
||||
temp[2] = ((m.elements[1][0] - m.elements[0][1]) * s);
|
||||
} else {
|
||||
int i = elements[0][0] < elements[1][1] ?
|
||||
(elements[1][1] < elements[2][2] ? 2 : 1) :
|
||||
(elements[0][0] < elements[2][2] ? 2 : 0);
|
||||
int i = m.elements[0][0] < m.elements[1][1] ?
|
||||
(m.elements[1][1] < m.elements[2][2] ? 2 : 1) :
|
||||
(m.elements[0][0] < m.elements[2][2] ? 2 : 0);
|
||||
int j = (i + 1) % 3;
|
||||
int k = (i + 2) % 3;
|
||||
|
||||
real_t s = Math::sqrt(elements[i][i] - elements[j][j] - elements[k][k] + 1.0);
|
||||
real_t s = Math::sqrt(m.elements[i][i] - m.elements[j][j] - m.elements[k][k] + 1.0);
|
||||
temp[i] = s * 0.5;
|
||||
s = 0.5 / s;
|
||||
|
||||
temp[3] = (elements[k][j] - elements[j][k]) * s;
|
||||
temp[j] = (elements[j][i] + elements[i][j]) * s;
|
||||
temp[k] = (elements[k][i] + elements[i][k]) * s;
|
||||
temp[3] = (m.elements[k][j] - m.elements[j][k]) * s;
|
||||
temp[j] = (m.elements[j][i] + m.elements[i][j]) * s;
|
||||
temp[k] = (m.elements[k][i] + m.elements[i][k]) * s;
|
||||
}
|
||||
|
||||
return Quat(temp[0], temp[1], temp[2], temp[3]);
|
||||
|
@ -696,9 +711,11 @@ void Basis::set_orthogonal_index(int p_index) {
|
|||
}
|
||||
|
||||
void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
|
||||
/* checking this is a bad idea, because obtaining from scaled transform is a valid use case
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND(!is_rotation());
|
||||
#endif
|
||||
*/
|
||||
real_t angle, x, y, z; // variables for result
|
||||
real_t epsilon = 0.01; // margin to allow for rounding errors
|
||||
real_t epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees
|
||||
|
@ -835,14 +852,15 @@ void Basis::set_diagonal(const Vector3 p_diag) {
|
|||
}
|
||||
|
||||
Basis Basis::slerp(const Basis &target, const real_t &t) const {
|
||||
// TODO: implement this directly without using quaternions to make it more efficient
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V(!is_rotation(), Basis());
|
||||
ERR_FAIL_COND_V(!target.is_rotation(), Basis());
|
||||
#endif
|
||||
|
||||
//consider scale
|
||||
Quat from(*this);
|
||||
Quat to(target);
|
||||
|
||||
return Basis(from.slerp(to, t));
|
||||
Basis b(from.slerp(to, t));
|
||||
b.elements[0] *= Math::lerp(elements[0].length(), target.elements[0].length(), t);
|
||||
b.elements[1] *= Math::lerp(elements[1].length(), target.elements[1].length(), t);
|
||||
b.elements[2] *= Math::lerp(elements[2].length(), target.elements[2].length(), t);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#define CMP_EPSILON 0.00001
|
||||
#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
|
||||
|
||||
#define CMP_NORMALIZE_TOLERANCE 0.000001
|
||||
#define CMP_POINT_IN_PLANE_EPSILON 0.00001
|
||||
|
||||
|
@ -49,6 +50,14 @@
|
|||
#define MATH_CHECKS
|
||||
#endif
|
||||
|
||||
//this epsilon is for values related to a unit size (scalar or vector len)
|
||||
#ifdef PRECISE_MATH_CHECKS
|
||||
#define UNIT_EPSILON 0.00001
|
||||
#else
|
||||
//tolerate some more floating point error normally
|
||||
#define UNIT_EPSILON 0.001
|
||||
#endif
|
||||
|
||||
#define USEC_TO_SEC(m_usec) ((m_usec) / 1000000.0)
|
||||
|
||||
enum ClockDirection {
|
||||
|
|
|
@ -249,13 +249,25 @@ public:
|
|||
static float random(float from, float to);
|
||||
static real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); }
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) {
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx_ratio(real_t a, real_t b, real_t epsilon = CMP_EPSILON) {
|
||||
// this is an approximate way to check that numbers are close, as a ratio of their average size
|
||||
// helps compare approximate numbers that may be very big or very small
|
||||
real_t diff = abs(a - b);
|
||||
if (diff == 0.0) {
|
||||
return true;
|
||||
}
|
||||
real_t avg_size = (abs(a) + abs(b)) / 2.0;
|
||||
diff /= avg_size;
|
||||
return diff < epsilon;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b, real_t epsilon = CMP_EPSILON) {
|
||||
// TODO: Comparing floats for approximate-equality is non-trivial.
|
||||
// Using epsilon should cover the typical cases in Godot (where a == b is used to compare two reals), such as matrix and vector comparison operators.
|
||||
// A proper implementation in terms of ULPs should eventually replace the contents of this function.
|
||||
// See https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ for details.
|
||||
|
||||
return abs(a - b) < CMP_EPSILON;
|
||||
return abs(a - b) < epsilon;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float absf(float g) {
|
||||
|
|
|
@ -135,7 +135,7 @@ Quat Quat::normalized() const {
|
|||
}
|
||||
|
||||
bool Quat::is_normalized() const {
|
||||
return Math::is_equal_approx(length_squared(), 1.0);
|
||||
return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); //use less epsilon
|
||||
}
|
||||
|
||||
Quat Quat::inverse() const {
|
||||
|
|
|
@ -65,7 +65,7 @@ Vector2 Vector2::normalized() const {
|
|||
|
||||
bool Vector2::is_normalized() const {
|
||||
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
|
||||
return Math::is_equal_approx(length_squared(), 1.0);
|
||||
return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
|
||||
}
|
||||
|
||||
real_t Vector2::distance_to(const Vector2 &p_vector2) const {
|
||||
|
|
|
@ -414,7 +414,7 @@ Vector3 Vector3::normalized() const {
|
|||
|
||||
bool Vector3::is_normalized() const {
|
||||
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
|
||||
return Math::is_equal_approx(length_squared(), 1.0);
|
||||
return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
|
||||
}
|
||||
|
||||
Vector3 Vector3::inverse() const {
|
||||
|
|
|
@ -2019,6 +2019,7 @@ void RasterizerCanvasGLES2::initialize() {
|
|||
state.canvas_shader.init();
|
||||
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
|
||||
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);
|
||||
|
||||
state.canvas_shader.bind();
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ RID RasterizerSceneGLES2::shadow_atlas_create() {
|
|||
ShadowAtlas *shadow_atlas = memnew(ShadowAtlas);
|
||||
shadow_atlas->fbo = 0;
|
||||
shadow_atlas->depth = 0;
|
||||
shadow_atlas->color = 0;
|
||||
shadow_atlas->size = 0;
|
||||
shadow_atlas->smallest_subdiv = 0;
|
||||
|
||||
|
@ -86,9 +87,13 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
|
|||
if (shadow_atlas->fbo) {
|
||||
glDeleteTextures(1, &shadow_atlas->depth);
|
||||
glDeleteFramebuffers(1, &shadow_atlas->fbo);
|
||||
if (shadow_atlas->color) {
|
||||
glDeleteTextures(1, &shadow_atlas->color);
|
||||
}
|
||||
|
||||
shadow_atlas->fbo = 0;
|
||||
shadow_atlas->depth = 0;
|
||||
shadow_atlas->color = 0;
|
||||
}
|
||||
|
||||
// erase shadow atlast references from lights
|
||||
|
@ -119,6 +124,16 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
|
|||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0);
|
||||
|
||||
if (storage->config.use_rgba_3d_shadows) {
|
||||
glGenTextures(1, &shadow_atlas->color);
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shadow_atlas->size, shadow_atlas->size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_atlas->color, 0);
|
||||
}
|
||||
glViewport(0, 0, shadow_atlas->size, shadow_atlas->size);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
|
@ -459,10 +474,10 @@ RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) {
|
|||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glGenFramebuffers(1, &rpi->fbo[i]);
|
||||
glGenTextures(1, &rpi->color[i]);
|
||||
}
|
||||
|
||||
glGenFramebuffers(1, &rpi->fbo_blur);
|
||||
glGenRenderbuffers(1, &rpi->depth);
|
||||
glGenTextures(1, &rpi->depth);
|
||||
rpi->cubemap = 0;
|
||||
//glGenTextures(1, &rpi->cubemap);
|
||||
|
||||
|
@ -510,9 +525,14 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
|
|||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, rpi->depth);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
|
||||
|
||||
if (rpi->cubemap != 0) {
|
||||
glDeleteTextures(1, &rpi->cubemap);
|
||||
}
|
||||
|
||||
glGenTextures(1, &rpi->cubemap);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
|
||||
#if 1
|
||||
|
@ -523,17 +543,15 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
|
|||
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); //resize depth buffer
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size);
|
||||
#else
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, size, size);
|
||||
#endif
|
||||
|
||||
//Generate framebuffers for rendering
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth);
|
||||
glBindTexture(GL_TEXTURE_2D, rpi->color[i]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size, 0, format, type, NULL);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rpi->color[i], 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rpi->depth, 0);
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -570,6 +588,8 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
|
|||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -579,6 +599,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
|
|||
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND_V(!rpi, false);
|
||||
ERR_FAIL_COND_V(rpi->current_resolution == 0, false);
|
||||
|
||||
int size = rpi->probe_ptr->resolution;
|
||||
|
||||
|
@ -596,16 +617,23 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
|
|||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to
|
||||
|
||||
//first of all, copy rendered textures to cubemap
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]);
|
||||
glViewport(0, 0, size, size);
|
||||
glCopyTexImage2D(_cube_side_enum[i], 0, GL_RGB, 0, 0, size, size, 0);
|
||||
}
|
||||
//do filtering
|
||||
//vdc cache
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->resources.radical_inverse_vdc_cache_tex);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo_blur);
|
||||
// now render to the framebuffer, mipmap level for mipmap level
|
||||
int lod = 1;
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, rpi->cubemap);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //use linear, no mipmaps so it does not read from what is being written to
|
||||
|
||||
size >>= 1;
|
||||
int mipmaps = 6;
|
||||
|
@ -613,13 +641,20 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
|
|||
storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
|
||||
storage->shaders.cubemap_filter.bind();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->resources.mipmap_blur_fbo);
|
||||
|
||||
//blur
|
||||
while (size >= 1) {
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, lod);
|
||||
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->resources.mipmap_blur_color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, storage->resources.mipmap_blur_color, 0);
|
||||
glViewport(0, 0, size, size);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
|
||||
storage->bind_quad_array();
|
||||
storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i);
|
||||
float roughness = CLAMP(lod / (float)(mipmaps - 1), 0, 1);
|
||||
|
@ -627,6 +662,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
|
|||
storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glCopyTexImage2D(_cube_side_enum[i], lod, GL_RGB, 0, 0, size, size, 0);
|
||||
}
|
||||
|
||||
size >>= 1;
|
||||
|
@ -635,9 +671,14 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst
|
|||
}
|
||||
|
||||
// restore ranges
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE3); //back to panorama
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1751,7 +1792,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
|
|||
if (!state.render_no_shadows && p_light->light_ptr->shadow) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
|
||||
if (storage->config.use_rgba_3d_shadows) {
|
||||
glBindTexture(GL_TEXTURE_2D, directional_shadow.color);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
|
||||
}
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
|
||||
}
|
||||
|
@ -1763,7 +1808,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
|
|||
if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
|
||||
if (storage->config.use_rgba_3d_shadows) {
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
|
||||
}
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
|
||||
}
|
||||
|
@ -1774,7 +1823,11 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas
|
|||
if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SHADOW, true);
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
|
||||
if (storage->config.use_rgba_3d_shadows) {
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
|
||||
}
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
|
||||
}
|
||||
|
@ -2041,7 +2094,7 @@ void RasterizerSceneGLES2::_setup_refprobes(ReflectionProbeInstance *p_refprobe1
|
|||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_USE_BOX_PROJECT, p_refprobe2->probe_ptr->box_projection);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_EXTENTS, p_refprobe2->probe_ptr->extents);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_BOX_OFFSET, p_refprobe2->probe_ptr->origin_offset);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_EXTERIOR, !p_refprobe2->probe_ptr->interior);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_EXTERIOR, p_refprobe2->probe_ptr->interior);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES2::REFPROBE2_INTENSITY, p_refprobe2->probe_ptr->intensity);
|
||||
|
||||
Color ambient;
|
||||
|
@ -2737,6 +2790,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
|
||||
if (probe_interior) {
|
||||
env_radiance_tex = 0; //do not use radiance texture on interiors
|
||||
state.default_ambient = Color(0, 0, 0, 1); //black as default ambient for interior
|
||||
}
|
||||
|
||||
// render opaque things first
|
||||
|
@ -2994,7 +3048,9 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
if (!storage->config.use_rgba_3d_shadows) {
|
||||
glColorMask(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (custom_vp_size) {
|
||||
glViewport(0, 0, custom_vp_size, custom_vp_size);
|
||||
|
@ -3070,8 +3126,10 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
|
|||
if (storage->frame.current_rt) {
|
||||
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
|
||||
}
|
||||
if (!storage->config.use_rgba_3d_shadows) {
|
||||
glColorMask(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) {
|
||||
scene_pass = p_pass;
|
||||
|
@ -3108,6 +3166,16 @@ bool RasterizerSceneGLES2::free(RID p_rid) {
|
|||
|
||||
ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.get(p_rid);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glDeleteFramebuffers(1, &reflection_instance->fbo[i]);
|
||||
glDeleteTextures(1, &reflection_instance->color[i]);
|
||||
}
|
||||
|
||||
if (reflection_instance->cubemap != 0) {
|
||||
glDeleteTextures(1, &reflection_instance->cubemap);
|
||||
}
|
||||
glDeleteTextures(1, &reflection_instance->depth);
|
||||
|
||||
reflection_probe_release_atlas_index(p_rid);
|
||||
reflection_probe_instance_owner.free(p_rid);
|
||||
memdelete(reflection_instance);
|
||||
|
@ -3124,6 +3192,8 @@ void RasterizerSceneGLES2::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_dra
|
|||
|
||||
void RasterizerSceneGLES2::initialize() {
|
||||
state.scene_shader.init();
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_3d_shadows);
|
||||
state.cube_to_dp_shader.init();
|
||||
|
||||
render_list.init();
|
||||
|
@ -3202,6 +3272,7 @@ void RasterizerSceneGLES2::initialize() {
|
|||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube.cubemap);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
|
||||
glTexImage2D(_cube_side_enum[i], 0, GL_DEPTH_COMPONENT, cube_size, cube_size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
|
||||
}
|
||||
|
||||
|
@ -3245,6 +3316,17 @@ void RasterizerSceneGLES2::initialize() {
|
|||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0);
|
||||
|
||||
if (storage->config.use_rgba_3d_shadows) {
|
||||
glGenTextures(1, &directional_shadow.color);
|
||||
glBindTexture(GL_TEXTURE_2D, directional_shadow.color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, directional_shadow.size, directional_shadow.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, directional_shadow.color, 0);
|
||||
}
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
ERR_PRINT("Directional shadow framebuffer status invalid");
|
||||
|
|
|
@ -256,6 +256,7 @@ public:
|
|||
|
||||
GLuint fbo;
|
||||
GLuint depth;
|
||||
GLuint color;
|
||||
|
||||
Map<RID, uint32_t> shadow_owners;
|
||||
};
|
||||
|
@ -279,6 +280,7 @@ public:
|
|||
struct DirectionalShadow {
|
||||
GLuint fbo;
|
||||
GLuint depth;
|
||||
GLuint color;
|
||||
|
||||
int light_count;
|
||||
int size;
|
||||
|
@ -311,10 +313,9 @@ public:
|
|||
int reflection_index;
|
||||
|
||||
GLuint fbo[6];
|
||||
GLuint cubemap;
|
||||
GLuint color[6];
|
||||
GLuint depth;
|
||||
|
||||
GLuint fbo_blur;
|
||||
GLuint cubemap;
|
||||
|
||||
int current_resolution;
|
||||
mutable bool dirty;
|
||||
|
|
|
@ -1026,18 +1026,8 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
|
|||
glGenTextures(1, &sky->radiance);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance);
|
||||
|
||||
// Now we create a new framebuffer. The new cubemap images will be used as
|
||||
// attachements for it, so we can fill them by issuing draw calls.
|
||||
GLuint tmp_fb;
|
||||
|
||||
int size = p_radiance_size / 4; //divide by four because its a cubemap (this is an approximation because GLES3 uses a dual paraboloid)
|
||||
|
||||
int lod = 0;
|
||||
|
||||
int mipmaps = 6;
|
||||
|
||||
int mm_level = mipmaps;
|
||||
|
||||
GLenum internal_format = GL_RGB;
|
||||
GLenum format = GL_RGB;
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
|
@ -1050,6 +1040,12 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
|
|||
}
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
//no filters for now
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
#else
|
||||
while (size >= 1) {
|
||||
|
||||
|
@ -1063,39 +1059,50 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
|
|||
}
|
||||
#endif
|
||||
//framebuffer
|
||||
glGenFramebuffers(1, &tmp_fb);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
|
||||
|
||||
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, texture->target == GL_TEXTURE_2D);
|
||||
|
||||
shaders.cubemap_filter.bind();
|
||||
lod = 0;
|
||||
mm_level = mipmaps;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.mipmap_blur_fbo);
|
||||
|
||||
int mipmaps = 6;
|
||||
int lod = 0;
|
||||
int mm_level = mipmaps;
|
||||
size = p_radiance_size;
|
||||
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, true);
|
||||
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, true);
|
||||
shaders.cubemap_filter.bind();
|
||||
|
||||
// now render to the framebuffer, mipmap level for mipmap level
|
||||
// third, render to the framebuffer using separate textures, then copy to mipmaps
|
||||
while (size >= 1) {
|
||||
//make framebuffer size the texture size, need to use a separate texture for compatibility
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_2D, resources.mipmap_blur_color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resources.mipmap_blur_color, 0);
|
||||
if (lod == 1) {
|
||||
//bind panorama for smaller lods
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, sky->radiance);
|
||||
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
|
||||
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, false);
|
||||
shaders.cubemap_filter.bind();
|
||||
}
|
||||
glViewport(0, 0, size, size);
|
||||
bind_quad_array();
|
||||
|
||||
glActiveTexture(GL_TEXTURE2); //back to panorama
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], sky->radiance, lod);
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
break; //may be too small
|
||||
}
|
||||
|
||||
glViewport(0, 0, size, size);
|
||||
|
||||
bind_quad_array();
|
||||
|
||||
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::FACE_ID, i);
|
||||
|
||||
float roughness = mm_level ? lod / (float)(mipmaps - 1) : 1;
|
||||
float roughness = mm_level >= 0 ? lod / (float)(mipmaps - 1) : 1;
|
||||
roughness = MIN(1.0, roughness); //keep max at 1
|
||||
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::ROUGHNESS, roughness);
|
||||
shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES2::Z_FLIP, false);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
glCopyTexImage2D(_cube_side_enum[i], lod, GL_RGB, 0, 0, size, size, 0);
|
||||
}
|
||||
|
||||
size >>= 1;
|
||||
|
@ -1105,16 +1112,28 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra
|
|||
lod++;
|
||||
}
|
||||
|
||||
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false);
|
||||
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_DIRECT_WRITE, false);
|
||||
|
||||
// restore ranges
|
||||
glActiveTexture(GL_TEXTURE2); //back to panorama
|
||||
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE3); //back to panorama
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// Framebuffer did its job. thank mr framebuffer
|
||||
glActiveTexture(GL_TEXTURE0); //back to panorama
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
|
||||
glDeleteFramebuffers(1, &tmp_fb);
|
||||
}
|
||||
|
||||
/* SHADER API */
|
||||
|
@ -2438,7 +2457,6 @@ AABB RasterizerStorageGLES2::mesh_surface_get_aabb(RID p_mesh, int p_surface) co
|
|||
}
|
||||
|
||||
Vector<PoolVector<uint8_t> > RasterizerStorageGLES2::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const {
|
||||
WARN_PRINT("GLES2 mesh_surface_get_blend_shapes is not implemented");
|
||||
return Vector<PoolVector<uint8_t> >();
|
||||
}
|
||||
Vector<AABB> RasterizerStorageGLES2::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
|
||||
|
@ -3662,6 +3680,7 @@ RID RasterizerStorageGLES2::reflection_probe_create() {
|
|||
reflection_probe->intensity = 1.0;
|
||||
reflection_probe->interior_ambient = Color();
|
||||
reflection_probe->interior_ambient_energy = 1.0;
|
||||
reflection_probe->interior_ambient_probe_contrib = 0.0;
|
||||
reflection_probe->max_distance = 0;
|
||||
reflection_probe->extents = Vector3(1, 1, 1);
|
||||
reflection_probe->origin_offset = Vector3(0, 0, 0);
|
||||
|
@ -3747,6 +3766,7 @@ void RasterizerStorageGLES2::reflection_probe_set_as_interior(RID p_probe, bool
|
|||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior = p_enable;
|
||||
reflection_probe->instance_change_notify(true, false);
|
||||
}
|
||||
void RasterizerStorageGLES2::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
|
||||
|
||||
|
@ -4962,8 +4982,10 @@ void RasterizerStorageGLES2::initialize() {
|
|||
#endif
|
||||
#ifdef GLES_OVER_GL
|
||||
config.use_rgba_2d_shadows = false;
|
||||
config.use_rgba_3d_shadows = false;
|
||||
#else
|
||||
config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg"));
|
||||
config.use_rgba_3d_shadows = config.extensions.has("GL_OES_depth_texture");
|
||||
#endif
|
||||
|
||||
#ifdef GLES_OVER_GL
|
||||
|
@ -4974,6 +4996,8 @@ void RasterizerStorageGLES2::initialize() {
|
|||
|
||||
#ifdef GLES_OVER_GL
|
||||
config.support_write_depth = true;
|
||||
#elif defined(JAVASCRIPT_ENABLED)
|
||||
config.support_write_depth = false;
|
||||
#else
|
||||
config.support_write_depth = config.extensions.has("GL_EXT_frag_depth");
|
||||
#endif
|
||||
|
@ -4995,7 +5019,7 @@ void RasterizerStorageGLES2::initialize() {
|
|||
|
||||
shaders.copy.init();
|
||||
shaders.cubemap_filter.init();
|
||||
bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx.mobile");
|
||||
bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
|
||||
shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::LOW_QUALITY, !ggx_hq);
|
||||
|
||||
{
|
||||
|
@ -5115,10 +5139,20 @@ void RasterizerStorageGLES2::initialize() {
|
|||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 512, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, radical_inverse);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
glGenFramebuffers(1, &resources.mipmap_blur_fbo);
|
||||
glGenTextures(1, &resources.mipmap_blur_color);
|
||||
}
|
||||
|
||||
#ifdef GLES_OVER_GL
|
||||
//this needs to be enabled manually in OpenGL 2.1
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
bool force_vertex_shading;
|
||||
|
||||
bool use_rgba_2d_shadows;
|
||||
bool use_rgba_3d_shadows;
|
||||
|
||||
bool support_32_bits_indices;
|
||||
bool support_write_depth;
|
||||
|
@ -92,6 +93,9 @@ public:
|
|||
GLuint normal_tex;
|
||||
GLuint aniso_tex;
|
||||
|
||||
GLuint mipmap_blur_fbo;
|
||||
GLuint mipmap_blur_color;
|
||||
|
||||
GLuint radical_inverse_vdc_cache_tex;
|
||||
bool use_rgba_2d_shadows;
|
||||
|
||||
|
|
|
@ -187,6 +187,18 @@ void main() {
|
|||
vec2 uv = (uv_interp * 2.0) - 1.0;
|
||||
vec3 N = texelCoordToVec(uv, face_id);
|
||||
|
||||
#ifdef USE_DIRECT_WRITE
|
||||
|
||||
#ifdef USE_SOURCE_PANORAMA
|
||||
|
||||
gl_FragColor = vec4(texturePanorama(source_panorama, N).rgb, 1.0);
|
||||
#else
|
||||
|
||||
gl_FragColor = vec4(textureCube(source_cube,N).rgb, 1.0);
|
||||
#endif //USE_SOURCE_PANORAMA
|
||||
|
||||
#else
|
||||
|
||||
vec4 sum = vec4(0.0);
|
||||
|
||||
for (int sample_num = 0; sample_num < SAMPLE_COUNT; sample_num++) {
|
||||
|
@ -221,4 +233,5 @@ void main() {
|
|||
sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308))));
|
||||
|
||||
gl_FragColor = vec4(sum.rgb, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -96,6 +96,10 @@ uniform float light_normal_bias;
|
|||
// varyings
|
||||
//
|
||||
|
||||
#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS)
|
||||
varying highp vec4 position_interp;
|
||||
#endif
|
||||
|
||||
varying highp vec3 vertex_interp;
|
||||
varying vec3 normal_interp;
|
||||
|
||||
|
@ -355,7 +359,7 @@ void main() {
|
|||
uv2_interp = uv2_attrib;
|
||||
#endif
|
||||
|
||||
#ifdef OVERRIDE_POSITION
|
||||
#if defined(OVERRIDE_POSITION)
|
||||
highp vec4 position;
|
||||
#endif
|
||||
|
||||
|
@ -647,11 +651,16 @@ VERTEX_SHADER_CODE
|
|||
|
||||
#endif //use vertex lighting
|
||||
|
||||
#ifdef OVERRIDE_POSITION
|
||||
#if defined(OVERRIDE_POSITION)
|
||||
gl_Position = position;
|
||||
#else
|
||||
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
|
||||
#endif
|
||||
|
||||
#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS)
|
||||
position_interp = gl_Position;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
|
@ -975,6 +984,10 @@ uniform vec4 light_clamp;
|
|||
// varyings
|
||||
//
|
||||
|
||||
#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS)
|
||||
varying highp vec4 position_interp;
|
||||
#endif
|
||||
|
||||
varying highp vec3 vertex_interp;
|
||||
varying vec3 normal_interp;
|
||||
|
||||
|
@ -1335,8 +1348,21 @@ LIGHT_SHADER_CODE
|
|||
|
||||
#ifdef USE_SHADOW
|
||||
|
||||
#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, texture2D(p_shadow, p_pos).r)
|
||||
#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, texture2DProj(p_shadow, p_pos).r)
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
|
||||
#define SHADOW_DEPTH(m_val) dot(m_val, vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0))
|
||||
|
||||
#else
|
||||
|
||||
#define SHADOW_DEPTH(m_val) (m_val).r
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, SHADOW_DEPTH(texture2D(p_shadow, p_pos)))
|
||||
#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, SHADOW_DEPTH(texture2DProj(p_shadow, p_pos)))
|
||||
|
||||
|
||||
|
||||
float sample_shadow(highp sampler2D shadow, highp vec4 spos) {
|
||||
|
||||
|
@ -2105,5 +2131,15 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#endif // defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
|
||||
|
||||
#endif // not RENDER_DEPTH
|
||||
#else // not RENDER_DEPTH
|
||||
//depth render
|
||||
#ifdef USE_RGBA_SHADOWS
|
||||
|
||||
highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias
|
||||
highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
|
||||
comp -= comp.xxyz * vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
|
||||
gl_FragColor = comp;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -5522,6 +5522,7 @@ void RasterizerStorageGLES3::reflection_probe_set_as_interior(RID p_probe, bool
|
|||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->interior = p_enable;
|
||||
reflection_probe->instance_change_notify(true, false);
|
||||
}
|
||||
void RasterizerStorageGLES3::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
|
||||
|
||||
|
|
|
@ -721,7 +721,7 @@ void SpatialMaterial::_update_shader() {
|
|||
code += "\tvec2 base_uv2 = UV2;\n";
|
||||
}
|
||||
|
||||
if (features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar
|
||||
if (!VisualServer::get_singleton()->is_low_end() && features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar
|
||||
code += "\t{\n";
|
||||
code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,-BINORMAL*depth_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-)
|
||||
|
||||
|
|
Loading…
Reference in a new issue