feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,10 @@ CubemapFilter *CubemapFilter::singleton = nullptr;
|
|||
|
||||
CubemapFilter::CubemapFilter() {
|
||||
singleton = this;
|
||||
ggx_samples = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples");
|
||||
// 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;
|
||||
|
|
@ -57,10 +60,10 @@ CubemapFilter::CubemapFilter() {
|
|||
const float qv[6] = {
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
3.0f,
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
3.0f,
|
||||
3.0f,
|
||||
-1.0f,
|
||||
};
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, qv, GL_STATIC_DRAW);
|
||||
|
|
@ -146,10 +149,11 @@ void CubemapFilter::filter_radiance(GLuint p_source_cubemap, GLuint p_dest_cubem
|
|||
}
|
||||
|
||||
if (p_layer > 0) {
|
||||
const uint32_t sample_counts[4] = { 1, ggx_samples / 4, ggx_samples / 2, ggx_samples };
|
||||
uint32_t sample_count = sample_counts[MIN(3, p_layer)];
|
||||
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);
|
||||
float roughness = float(p_layer) / (p_mipmap_count - 1);
|
||||
roughness *= roughness; // Convert to non-perceptual roughness.
|
||||
float roughness4 = roughness * roughness;
|
||||
roughness4 *= roughness4;
|
||||
|
||||
|
|
@ -165,7 +169,7 @@ void CubemapFilter::filter_radiance(GLuint p_source_cubemap, GLuint p_dest_cubem
|
|||
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) {
|
||||
if (light_vec.z <= 0.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
128
engine/drivers/gles3/effects/feed_effects.cpp
Normal file
128
engine/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
|
||||
69
engine/drivers/gles3/effects/feed_effects.h
Normal file
69
engine/drivers/gles3/effects/feed_effects.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/**************************************************************************/
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef FEED_EFFECTS_GLES3_H
|
||||
#define FEED_EFFECTS_GLES3_H
|
||||
|
||||
#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
|
||||
|
||||
#endif // FEED_EFFECTS_GLES3_H
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,6 @@
|
|||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/templates/self_list.h"
|
||||
#include "servers/rendering/environment/renderer_fog.h"
|
||||
|
||||
namespace GLES3 {
|
||||
|
|
|
|||
|
|
@ -33,13 +33,8 @@
|
|||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/templates/self_list.h"
|
||||
#include "servers/rendering/environment/renderer_gi.h"
|
||||
|
||||
#include "platform_gl.h"
|
||||
|
||||
namespace GLES3 {
|
||||
|
||||
class GI : public RendererGI {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include "rasterizer_gles3.h"
|
||||
#include "rasterizer_scene_gles3.h"
|
||||
|
||||
|
|
@ -468,7 +467,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
|||
update_skeletons = false;
|
||||
}
|
||||
// Canvas group begins here, render until before this item
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false, r_render_info);
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false, r_render_info, material_screen_texture_mipmaps_cached);
|
||||
item_count = 0;
|
||||
|
||||
if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
|
||||
|
|
@ -499,7 +498,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
|||
mesh_storage->update_mesh_instances();
|
||||
update_skeletons = false;
|
||||
}
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, true, r_render_info);
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, true, r_render_info, material_screen_texture_mipmaps_cached);
|
||||
item_count = 0;
|
||||
|
||||
if (ci->canvas_group->blur_mipmaps) {
|
||||
|
|
@ -523,7 +522,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
|||
}
|
||||
//render anything pending, including clearing if no items
|
||||
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false, r_render_info);
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false, r_render_info, material_screen_texture_mipmaps_cached);
|
||||
item_count = 0;
|
||||
|
||||
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
|
||||
|
|
@ -553,7 +552,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
|||
mesh_storage->update_mesh_instances();
|
||||
update_skeletons = false;
|
||||
}
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, canvas_group_owner != nullptr, r_render_info);
|
||||
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, canvas_group_owner != nullptr, r_render_info, material_screen_texture_mipmaps_cached);
|
||||
//then reset
|
||||
item_count = 0;
|
||||
}
|
||||
|
|
@ -573,10 +572,10 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
|||
state.current_instance_buffer_index = 0;
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer, RenderingMethod::RenderInfo *r_render_info) {
|
||||
void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer, RenderingMethod::RenderInfo *r_render_info, bool p_backbuffer_has_mipmaps) {
|
||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||
|
||||
canvas_begin(p_to_render_target, p_to_backbuffer);
|
||||
canvas_begin(p_to_render_target, p_to_backbuffer, p_backbuffer_has_mipmaps);
|
||||
|
||||
if (p_item_count <= 0) {
|
||||
// Nothing to draw, just call canvas_begin() to clear the render target and return.
|
||||
|
|
@ -647,25 +646,22 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
|||
_record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken, r_sdf_used, Point2());
|
||||
} else {
|
||||
Point2 start_pos = ci->repeat_size * -(ci->repeat_times / 2);
|
||||
Point2 end_pos = ci->repeat_size * ci->repeat_times + ci->repeat_size + start_pos;
|
||||
Point2 pos = start_pos;
|
||||
Point2 offset;
|
||||
|
||||
do {
|
||||
do {
|
||||
_record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken, r_sdf_used, pos);
|
||||
pos.y += ci->repeat_size.y;
|
||||
} while (pos.y < end_pos.y);
|
||||
|
||||
pos.x += ci->repeat_size.x;
|
||||
pos.y = start_pos.y;
|
||||
} while (pos.x < end_pos.x);
|
||||
int repeat_times_x = ci->repeat_size.x ? ci->repeat_times : 0;
|
||||
int repeat_times_y = ci->repeat_size.y ? ci->repeat_times : 0;
|
||||
for (int ry = 0; ry <= repeat_times_y; ry++) {
|
||||
offset.y = start_pos.y + ry * ci->repeat_size.y;
|
||||
for (int rx = 0; rx <= repeat_times_x; rx++) {
|
||||
offset.x = start_pos.x + rx * ci->repeat_size.x;
|
||||
_record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken, r_sdf_used, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
// Nothing to render, just return.
|
||||
state.current_batch_index = 0;
|
||||
state.canvas_instance_batches.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -688,6 +684,8 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
|||
|
||||
state.current_tex = RID();
|
||||
|
||||
const uint64_t base_specialization = GLES3::Config::get_singleton()->float_texture_supported ? 0 : CanvasShaderGLES3::USE_RGBA_SHADOWS;
|
||||
|
||||
for (uint32_t i = 0; i <= state.current_batch_index; i++) {
|
||||
// Skipping when there is no instances.
|
||||
if (state.canvas_instance_batches[i].instance_count == 0) {
|
||||
|
|
@ -706,10 +704,9 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
|||
}
|
||||
|
||||
GLES3::CanvasMaterialData *material_data = state.canvas_instance_batches[i].material_data;
|
||||
CanvasShaderGLES3::ShaderVariant variant = state.canvas_instance_batches[i].shader_variant;
|
||||
uint64_t specialization = 0;
|
||||
specialization |= uint64_t(state.canvas_instance_batches[i].lights_disabled);
|
||||
specialization |= uint64_t(!GLES3::Config::get_singleton()->float_texture_supported) << 1;
|
||||
CanvasShaderGLES3::ShaderVariant variant = CanvasShaderGLES3::MODE_DEFAULT;
|
||||
uint64_t specialization = state.canvas_instance_batches[i].specialization;
|
||||
specialization |= base_specialization;
|
||||
RID shader_version = data.canvas_shader_default_version;
|
||||
|
||||
if (material_data) {
|
||||
|
|
@ -720,11 +717,15 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
|||
}
|
||||
}
|
||||
|
||||
bool success = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization);
|
||||
bool success = material_storage->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization);
|
||||
if (!success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bind per-batch uniforms.
|
||||
material_storage->shaders.canvas_shader.version_set_uniform(CanvasShaderGLES3::BATCH_FLAGS, state.canvas_instance_batches[i].flags, shader_version, variant, specialization);
|
||||
material_storage->shaders.canvas_shader.version_set_uniform(CanvasShaderGLES3::SPECULAR_SHININESS_IN, state.canvas_instance_batches[i].specular_shininess, shader_version, variant, specialization);
|
||||
|
||||
GLES3::CanvasShaderData::BlendMode blend_mode = state.canvas_instance_batches[i].blend_mode;
|
||||
Color blend_color = state.canvas_instance_batches[i].blend_color;
|
||||
|
||||
|
|
@ -809,8 +810,9 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
|||
state.last_item_index += index;
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, const Point2 &p_offset) {
|
||||
void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, const Point2 &p_repeat_offset) {
|
||||
RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter;
|
||||
const uint64_t specialization_command_mask = ~(CanvasShaderGLES3::USE_NINEPATCH | CanvasShaderGLES3::USE_PRIMITIVE | CanvasShaderGLES3::USE_ATTRIBUTES | CanvasShaderGLES3::USE_INSTANCING);
|
||||
|
||||
if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) {
|
||||
_new_batch(r_batch_broken);
|
||||
|
|
@ -826,11 +828,11 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
state.canvas_instance_batches[state.current_batch_index].repeat = texture_repeat;
|
||||
}
|
||||
|
||||
Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform;
|
||||
|
||||
if (p_offset.x || p_offset.y) {
|
||||
base_transform *= Transform2D(0, p_offset / p_item->xform_curr.get_scale()); // TODO: Interpolate or explain why not needed.
|
||||
Transform2D base_transform = p_item->final_transform;
|
||||
if (p_item->repeat_source_item && (p_repeat_offset.x || p_repeat_offset.y)) {
|
||||
base_transform.columns[2] += p_item->repeat_source_item->final_transform.basis_xform(p_repeat_offset);
|
||||
}
|
||||
base_transform = p_canvas_transform_inverse * base_transform;
|
||||
|
||||
Transform2D draw_transform; // Used by transform command
|
||||
|
||||
|
|
@ -846,15 +848,20 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
uint32_t lights[4] = { 0, 0, 0, 0 };
|
||||
|
||||
uint16_t light_count = 0;
|
||||
uint16_t shadow_mask = 0;
|
||||
|
||||
{
|
||||
Light *light = p_lights;
|
||||
|
||||
while (light) {
|
||||
if (light->render_index_cache >= 0 && p_item->light_mask & light->item_mask && p_item->z_final >= light->z_min && p_item->z_final <= light->z_max && p_item->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) {
|
||||
if (light->render_index_cache >= 0 && p_item->light_mask & light->item_mask && p_item->z_final >= light->z_min && p_item->z_final <= light->z_max && p_item->global_rect_cache.intersects(light->rect_cache)) {
|
||||
uint32_t light_index = light->render_index_cache;
|
||||
lights[light_count >> 2] |= light_index << ((light_count & 3) * 8);
|
||||
|
||||
if (p_item->light_mask & light->item_shadow_mask) {
|
||||
shadow_mask |= 1 << light_count;
|
||||
}
|
||||
|
||||
light_count++;
|
||||
|
||||
if (light_count == data.max_lights_per_item - 1) {
|
||||
|
|
@ -864,14 +871,15 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
light = light->next_ptr;
|
||||
}
|
||||
|
||||
base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT;
|
||||
base_flags |= light_count << INSTANCE_FLAGS_LIGHT_COUNT_SHIFT;
|
||||
base_flags |= shadow_mask << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT;
|
||||
}
|
||||
|
||||
bool lights_disabled = light_count == 0 && !state.using_directional_lights;
|
||||
|
||||
if (lights_disabled != state.canvas_instance_batches[state.current_batch_index].lights_disabled) {
|
||||
if (lights_disabled != bool(state.canvas_instance_batches[state.current_batch_index].specialization & CanvasShaderGLES3::DISABLE_LIGHTING)) {
|
||||
_new_batch(r_batch_broken);
|
||||
state.canvas_instance_batches[state.current_batch_index].lights_disabled = lights_disabled;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization ^= CanvasShaderGLES3::DISABLE_LIGHTING;
|
||||
}
|
||||
|
||||
const Item::Command *c = p_item->commands;
|
||||
|
|
@ -897,15 +905,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0;
|
||||
state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0;
|
||||
|
||||
state.instance_data_array[r_index].pad[0] = 0.0;
|
||||
state.instance_data_array[r_index].pad[1] = 0.0;
|
||||
|
||||
state.instance_data_array[r_index].lights[0] = lights[0];
|
||||
state.instance_data_array[r_index].lights[1] = lights[1];
|
||||
state.instance_data_array[r_index].lights[2] = lights[2];
|
||||
state.instance_data_array[r_index].lights[3] = lights[3];
|
||||
|
||||
state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); // Reset on each command for safety, keep canvastexture binding config.
|
||||
state.instance_data_array[r_index].flags = base_flags;
|
||||
state.instance_data_array[r_index].instance_uniforms_ofs = p_item->instance_allocated_shader_uniforms_offset;
|
||||
|
||||
Color blend_color = base_color;
|
||||
GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode;
|
||||
|
|
@ -937,7 +943,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
state.canvas_instance_batches[state.current_batch_index].tex = rect->texture;
|
||||
state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_RECT;
|
||||
state.canvas_instance_batches[state.current_batch_index].command = c;
|
||||
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_QUAD;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags = 0;
|
||||
}
|
||||
|
||||
_prepare_canvas_texture(rect->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
|
||||
|
|
@ -960,20 +967,18 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
|
||||
if (rect->flags & CANVAS_RECT_FLIP_H) {
|
||||
src_rect.size.x *= -1;
|
||||
state.instance_data_array[r_index].flags |= FLAGS_FLIP_H;
|
||||
}
|
||||
|
||||
if (rect->flags & CANVAS_RECT_FLIP_V) {
|
||||
src_rect.size.y *= -1;
|
||||
state.instance_data_array[r_index].flags |= FLAGS_FLIP_V;
|
||||
}
|
||||
|
||||
if (rect->flags & CANVAS_RECT_TRANSPOSE) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_TRANSPOSE_RECT;
|
||||
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_TRANSPOSE_RECT;
|
||||
}
|
||||
|
||||
if (rect->flags & CANVAS_RECT_CLIP_UV) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_CLIP_RECT_UV;
|
||||
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_CLIP_RECT_UV;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -992,13 +997,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
}
|
||||
|
||||
if (rect->flags & CANVAS_RECT_MSDF) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_USE_MSDF;
|
||||
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_USE_MSDF;
|
||||
state.instance_data_array[r_index].msdf[0] = rect->px_range; // Pixel range.
|
||||
state.instance_data_array[r_index].msdf[1] = rect->outline; // Outline size.
|
||||
state.instance_data_array[r_index].msdf[2] = 0.f; // Reserved.
|
||||
state.instance_data_array[r_index].msdf[3] = 0.f; // Reserved.
|
||||
} else if (rect->flags & CANVAS_RECT_LCD) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_USE_LCD;
|
||||
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_USE_LCD;
|
||||
}
|
||||
|
||||
state.instance_data_array[r_index].modulation[0] = rect->modulate.r * base_color.r;
|
||||
|
|
@ -1027,7 +1032,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
state.canvas_instance_batches[state.current_batch_index].tex = np->texture;
|
||||
state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_NINEPATCH;
|
||||
state.canvas_instance_batches[state.current_batch_index].command = c;
|
||||
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_NINEPATCH;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_NINEPATCH;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags = 0;
|
||||
}
|
||||
|
||||
_prepare_canvas_texture(np->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
|
||||
|
|
@ -1065,11 +1072,11 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
state.instance_data_array[r_index].dst_rect[2] = dst_rect.size.width;
|
||||
state.instance_data_array[r_index].dst_rect[3] = dst_rect.size.height;
|
||||
|
||||
state.instance_data_array[r_index].flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT;
|
||||
state.instance_data_array[r_index].flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT;
|
||||
state.instance_data_array[r_index].flags |= int(np->axis_x) << INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT;
|
||||
state.instance_data_array[r_index].flags |= int(np->axis_y) << INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT;
|
||||
|
||||
if (np->draw_center) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_NINEPACH_DRAW_CENTER;
|
||||
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_NINEPACH_DRAW_CENTER;
|
||||
}
|
||||
|
||||
state.instance_data_array[r_index].ninepatch_margins[0] = np->margin[SIDE_LEFT];
|
||||
|
|
@ -1093,7 +1100,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
state.canvas_instance_batches[state.current_batch_index].tex = polygon->texture;
|
||||
state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_POLYGON;
|
||||
state.canvas_instance_batches[state.current_batch_index].command = c;
|
||||
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags = 0;
|
||||
|
||||
_prepare_canvas_texture(polygon->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
|
||||
|
||||
|
|
@ -1120,7 +1129,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
state.canvas_instance_batches[state.current_batch_index].primitive_points = primitive->point_count;
|
||||
state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_PRIMITIVE;
|
||||
state.canvas_instance_batches[state.current_batch_index].command = c;
|
||||
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_PRIMITIVE;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_PRIMITIVE;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags = 0;
|
||||
}
|
||||
|
||||
_prepare_canvas_texture(state.canvas_instance_batches[state.current_batch_index].tex, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
|
||||
|
|
@ -1161,11 +1172,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
case Item::Command::TYPE_MESH:
|
||||
case Item::Command::TYPE_MULTIMESH:
|
||||
case Item::Command::TYPE_PARTICLES: {
|
||||
// Mesh's can't be batched, so always create a new batch
|
||||
// Meshes can't be batched, so always create a new batch.
|
||||
_new_batch(r_batch_broken);
|
||||
|
||||
Color modulate(1, 1, 1, 1);
|
||||
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags = 0;
|
||||
if (c->type == Item::Command::TYPE_MESH) {
|
||||
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
|
||||
state.canvas_instance_batches[state.current_batch_index].tex = m->texture;
|
||||
|
|
@ -1175,13 +1188,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
|
||||
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
|
||||
state.canvas_instance_batches[state.current_batch_index].tex = mm->texture;
|
||||
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING;
|
||||
|
||||
if (GLES3::MeshStorage::get_singleton()->multimesh_uses_colors(mm->multimesh)) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS;
|
||||
}
|
||||
if (GLES3::MeshStorage::get_singleton()->multimesh_uses_custom_data(mm->multimesh)) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA;
|
||||
}
|
||||
} else if (c->type == Item::Command::TYPE_PARTICLES) {
|
||||
GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
|
||||
|
|
@ -1190,9 +1203,9 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
|||
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
|
||||
RID particles = pt->particles;
|
||||
state.canvas_instance_batches[state.current_batch_index].tex = pt->texture;
|
||||
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
|
||||
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS;
|
||||
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
|
||||
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA;
|
||||
|
||||
if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
|
||||
// Pass collision information.
|
||||
|
|
@ -1554,7 +1567,9 @@ void RasterizerCanvasGLES3::_add_to_batch(uint32_t &r_index, bool &r_batch_broke
|
|||
|
||||
void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken) {
|
||||
if (state.canvas_instance_batches.size() == 0) {
|
||||
state.canvas_instance_batches.push_back(Batch());
|
||||
Batch new_batch;
|
||||
new_batch.instance_buffer_index = state.current_instance_buffer_index;
|
||||
state.canvas_instance_batches.push_back(new_batch);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1619,7 +1634,7 @@ void RasterizerCanvasGLES3::light_set_use_shadow(RID p_rid, bool p_enable) {
|
|||
cl->shadow.enabled = p_enable;
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) {
|
||||
void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, const Rect2 &p_light_rect) {
|
||||
GLES3::Config *config = GLES3::Config::get_singleton();
|
||||
|
||||
CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
|
||||
|
|
@ -1655,28 +1670,39 @@ void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, c
|
|||
return;
|
||||
}
|
||||
|
||||
Projection projection;
|
||||
{
|
||||
real_t fov = 90;
|
||||
real_t nearp = p_near;
|
||||
real_t farp = p_far;
|
||||
real_t aspect = 1.0;
|
||||
|
||||
real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5));
|
||||
real_t ymin = -ymax;
|
||||
real_t xmin = ymin * aspect;
|
||||
real_t xmax = ymax * aspect;
|
||||
|
||||
projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
|
||||
}
|
||||
|
||||
// Precomputed:
|
||||
// Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
|
||||
// projection = projection * Projection(Transform3D().looking_at(cam_targets[i], Vector3(0, 0, -1)).affine_inverse());
|
||||
const Projection projections[4] = {
|
||||
projection * Projection(Vector4(0, 0, -1, 0), Vector4(1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)),
|
||||
|
||||
projection * Projection(Vector4(-1, 0, 0, 0), Vector4(0, 0, -1, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)),
|
||||
|
||||
projection * Projection(Vector4(0, 0, 1, 0), Vector4(-1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)),
|
||||
|
||||
projection * Projection(Vector4(1, 0, 0, 0), Vector4(0, 0, 1, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1))
|
||||
|
||||
};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glViewport((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
|
||||
|
||||
Projection projection;
|
||||
{
|
||||
real_t fov = 90;
|
||||
real_t nearp = p_near;
|
||||
real_t farp = p_far;
|
||||
real_t aspect = 1.0;
|
||||
|
||||
real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5));
|
||||
real_t ymin = -ymax;
|
||||
real_t xmin = ymin * aspect;
|
||||
real_t xmax = ymax * aspect;
|
||||
|
||||
projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
|
||||
}
|
||||
|
||||
Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
|
||||
|
||||
projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
|
||||
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::PROJECTION, projection, shadow_render.shader_version, variant);
|
||||
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::PROJECTION, projections[i], shadow_render.shader_version, variant);
|
||||
|
||||
static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) };
|
||||
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::DIRECTION, directions[i].x, directions[i].y, shadow_render.shader_version, variant);
|
||||
|
|
@ -1735,7 +1761,7 @@ void RasterizerCanvasGLES3::light_update_directional_shadow(RID p_rid, int p_sha
|
|||
|
||||
Vector2 center = p_clip_rect.get_center();
|
||||
|
||||
float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(light_dir)) - light_dir.dot(center));
|
||||
float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(-light_dir)) - light_dir.dot(center));
|
||||
|
||||
Vector2 from_pos = center - light_dir * (to_edge_distance + p_cull_distance);
|
||||
float distance = to_edge_distance * 2.0 + p_cull_distance;
|
||||
|
|
@ -2170,7 +2196,7 @@ bool RasterizerCanvasGLES3::free(RID p_rid) {
|
|||
void RasterizerCanvasGLES3::update() {
|
||||
}
|
||||
|
||||
void RasterizerCanvasGLES3::canvas_begin(RID p_to_render_target, bool p_to_backbuffer) {
|
||||
void RasterizerCanvasGLES3::canvas_begin(RID p_to_render_target, bool p_to_backbuffer, bool p_backbuffer_has_mipmaps) {
|
||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||
GLES3::Config *config = GLES3::Config::get_singleton();
|
||||
|
||||
|
|
@ -2185,6 +2211,9 @@ void RasterizerCanvasGLES3::canvas_begin(RID p_to_render_target, bool p_to_backb
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, render_target->fbo);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 4);
|
||||
glBindTexture(GL_TEXTURE_2D, render_target->backbuffer);
|
||||
if (render_target->backbuffer != 0) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, p_backbuffer_has_mipmaps ? render_target->mipmap_count - 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (render_target->is_transparent || p_to_backbuffer) {
|
||||
|
|
@ -2345,21 +2374,21 @@ void RasterizerCanvasGLES3::_prepare_canvas_texture(RID p_texture, RS::CanvasIte
|
|||
GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map);
|
||||
|
||||
if (ct->specular_color.a < 0.999) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED;
|
||||
} else {
|
||||
state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_SPECULAR_MAP_USED;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags &= ~BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED;
|
||||
}
|
||||
|
||||
if (normal_map) {
|
||||
state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED;
|
||||
} else {
|
||||
state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_NORMAL_MAP_USED;
|
||||
state.canvas_instance_batches[state.current_batch_index].flags &= ~BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED;
|
||||
}
|
||||
|
||||
state.instance_data_array[r_index].specular_shininess = uint32_t(CLAMP(ct->specular_color.a * 255.0, 0, 255)) << 24;
|
||||
state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.b * 255.0, 0, 255)) << 16;
|
||||
state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.g * 255.0, 0, 255)) << 8;
|
||||
state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.r * 255.0, 0, 255));
|
||||
state.canvas_instance_batches[state.current_batch_index].specular_shininess = uint32_t(CLAMP(ct->specular_color.a * 255.0, 0, 255)) << 24;
|
||||
state.canvas_instance_batches[state.current_batch_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.b * 255.0, 0, 255)) << 16;
|
||||
state.canvas_instance_batches[state.current_batch_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.g * 255.0, 0, 255)) << 8;
|
||||
state.canvas_instance_batches[state.current_batch_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.r * 255.0, 0, 255));
|
||||
|
||||
r_texpixel_size.x = 1.0 / float(size_cache.x);
|
||||
r_texpixel_size.y = 1.0 / float(size_cache.y);
|
||||
|
|
|
|||
|
|
@ -54,29 +54,27 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
|
|||
_FORCE_INLINE_ void _update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4);
|
||||
|
||||
enum {
|
||||
INSTANCE_FLAGS_LIGHT_COUNT_SHIFT = 0, // 4 bits for light count.
|
||||
|
||||
FLAGS_INSTANCING_MASK = 0x7F,
|
||||
FLAGS_INSTANCING_HAS_COLORS = (1 << 7),
|
||||
FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8),
|
||||
INSTANCE_FLAGS_CLIP_RECT_UV = (1 << 4),
|
||||
INSTANCE_FLAGS_TRANSPOSE_RECT = (1 << 5),
|
||||
INSTANCE_FLAGS_USE_MSDF = (1 << 6),
|
||||
INSTANCE_FLAGS_USE_LCD = (1 << 7),
|
||||
|
||||
FLAGS_CLIP_RECT_UV = (1 << 9),
|
||||
FLAGS_TRANSPOSE_RECT = (1 << 10),
|
||||
INSTANCE_FLAGS_NINEPACH_DRAW_CENTER = (1 << 8),
|
||||
INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT = 9,
|
||||
INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT = 11,
|
||||
|
||||
FLAGS_NINEPACH_DRAW_CENTER = (1 << 12),
|
||||
INSTANCE_FLAGS_SHADOW_MASKED_SHIFT = 13, // 16 bits.
|
||||
};
|
||||
|
||||
FLAGS_USE_SKELETON = (1 << 15),
|
||||
FLAGS_NINEPATCH_H_MODE_SHIFT = 16,
|
||||
FLAGS_NINEPATCH_V_MODE_SHIFT = 18,
|
||||
FLAGS_LIGHT_COUNT_SHIFT = 20,
|
||||
enum {
|
||||
BATCH_FLAGS_INSTANCING_MASK = 0x7F,
|
||||
BATCH_FLAGS_INSTANCING_HAS_COLORS = (1 << 7),
|
||||
BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8),
|
||||
|
||||
FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26),
|
||||
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
|
||||
|
||||
FLAGS_USE_MSDF = (1 << 28),
|
||||
FLAGS_USE_LCD = (1 << 29),
|
||||
|
||||
FLAGS_FLIP_H = (1 << 30),
|
||||
FLAGS_FLIP_V = (1 << 31),
|
||||
BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 9),
|
||||
BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 10),
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -229,7 +227,7 @@ public:
|
|||
};
|
||||
};
|
||||
uint32_t flags;
|
||||
uint32_t specular_shininess;
|
||||
uint32_t instance_uniforms_ofs;
|
||||
uint32_t lights[4];
|
||||
};
|
||||
|
||||
|
|
@ -273,13 +271,16 @@ public:
|
|||
|
||||
RID material;
|
||||
GLES3::CanvasMaterialData *material_data = nullptr;
|
||||
CanvasShaderGLES3::ShaderVariant shader_variant = CanvasShaderGLES3::MODE_QUAD;
|
||||
uint64_t vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_COLOR | RS::ARRAY_FORMAT_TEX_UV;
|
||||
uint64_t specialization = 0;
|
||||
|
||||
const Item::Command *command = nullptr;
|
||||
Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch.
|
||||
uint32_t primitive_points = 0;
|
||||
|
||||
uint32_t flags = 0;
|
||||
uint32_t specular_shininess = 0.0;
|
||||
|
||||
bool lights_disabled = false;
|
||||
};
|
||||
|
||||
|
|
@ -335,7 +336,7 @@ public:
|
|||
|
||||
typedef void Texture;
|
||||
|
||||
void canvas_begin(RID p_to_render_target, bool p_to_backbuffer);
|
||||
void canvas_begin(RID p_to_render_target, bool p_to_backbuffer, bool p_backbuffer_has_mipmaps);
|
||||
|
||||
//virtual void draw_window_margins(int *black_margin, RID *black_image) override;
|
||||
void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
|
||||
|
|
@ -345,7 +346,7 @@ public:
|
|||
RID light_create() override;
|
||||
void light_set_texture(RID p_rid, RID p_texture) override;
|
||||
void light_set_use_shadow(RID p_rid, bool p_enable) override;
|
||||
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override;
|
||||
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, const Rect2 &p_light_rect) override;
|
||||
void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override;
|
||||
|
||||
void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override;
|
||||
|
|
@ -361,8 +362,8 @@ public:
|
|||
void _prepare_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, Size2 &r_texpixel_size);
|
||||
|
||||
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info = nullptr) override;
|
||||
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr);
|
||||
void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch, bool &r_sdf_used, const Point2 &p_offset);
|
||||
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr, bool p_backbuffer_has_mipmaps = false);
|
||||
void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch, bool &r_sdf_used, const Point2 &p_repeat_offset);
|
||||
void _render_batch(Light *p_lights, uint32_t p_index, RenderingMethod::RenderInfo *r_render_info = nullptr);
|
||||
bool _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization);
|
||||
void _new_batch(bool &r_batch_broken);
|
||||
|
|
@ -375,10 +376,12 @@ public:
|
|||
|
||||
virtual void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) override {
|
||||
if (p_enabled) {
|
||||
WARN_PRINT_ONCE("Debug CanvasItem Redraw is not available yet when using the GL Compatibility backend.");
|
||||
WARN_PRINT_ONCE("Debug CanvasItem Redraw is not available yet when using the Compatibility renderer.");
|
||||
}
|
||||
}
|
||||
|
||||
virtual uint32_t get_pipeline_compilations(RS::PipelineSource p_source) override { return 0; }
|
||||
|
||||
static RasterizerCanvasGLES3 *get_singleton();
|
||||
RasterizerCanvasGLES3();
|
||||
~RasterizerCanvasGLES3();
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "storage/texture_storage.h"
|
||||
|
||||
|
|
@ -62,6 +63,10 @@
|
|||
#define _EXT_DEBUG_SEVERITY_LOW_ARB 0x9148
|
||||
#define _EXT_DEBUG_OUTPUT 0x92E0
|
||||
|
||||
#ifndef GL_FRAMEBUFFER_SRGB
|
||||
#define GL_FRAMEBUFFER_SRGB 0x8DB9
|
||||
#endif
|
||||
|
||||
#ifndef GLAPIENTRY
|
||||
#if defined(WINDOWS_ENABLED)
|
||||
#define GLAPIENTRY APIENTRY
|
||||
|
|
@ -82,6 +87,10 @@
|
|||
#define strcpy strcpy_s
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
bool RasterizerGLES3::screen_flipped_y = false;
|
||||
#endif
|
||||
|
||||
bool RasterizerGLES3::gles_over_gl = true;
|
||||
|
||||
void RasterizerGLES3::begin_frame(double frame_step) {
|
||||
|
|
@ -209,6 +218,7 @@ void RasterizerGLES3::finalize() {
|
|||
memdelete(glow);
|
||||
memdelete(cubemap_filter);
|
||||
memdelete(copy_effects);
|
||||
memdelete(feed_effects);
|
||||
memdelete(light_storage);
|
||||
memdelete(particles_storage);
|
||||
memdelete(mesh_storage);
|
||||
|
|
@ -357,10 +367,16 @@ RasterizerGLES3::RasterizerGLES3() {
|
|||
cubemap_filter = memnew(GLES3::CubemapFilter);
|
||||
glow = memnew(GLES3::Glow);
|
||||
post_effects = memnew(GLES3::PostEffects);
|
||||
feed_effects = memnew(GLES3::FeedEffects);
|
||||
gi = memnew(GLES3::GI);
|
||||
fog = memnew(GLES3::Fog);
|
||||
canvas = memnew(RasterizerCanvasGLES3());
|
||||
scene = memnew(RasterizerSceneGLES3());
|
||||
|
||||
// Disable OpenGL linear to sRGB conversion, because Godot will always do this conversion itself.
|
||||
if (config->srgb_framebuffer_supported) {
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
}
|
||||
|
||||
RasterizerGLES3::~RasterizerGLES3() {
|
||||
|
|
@ -380,6 +396,12 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
|
|||
flip_y = false;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
if (screen_flipped_y) {
|
||||
flip_y = !flip_y;
|
||||
}
|
||||
#endif
|
||||
|
||||
GLuint read_fbo = 0;
|
||||
glGenFramebuffers(1, &read_fbo);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo);
|
||||
|
|
@ -448,9 +470,9 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
||||
glViewport(0, 0, win_size.width, win_size.height);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
|
||||
glDepthMask(GL_FALSE);
|
||||
glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
|
||||
glClearColor(p_color.r, p_color.g, p_color.b, OS::get_singleton()->is_layered_allowed() ? p_color.a : 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
RID texture = texture_storage->texture_allocate();
|
||||
|
|
@ -476,9 +498,14 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
|
|||
screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor();
|
||||
}
|
||||
|
||||
// Flip Y.
|
||||
screenrect.position.y = win_size.y - screenrect.position.y;
|
||||
screenrect.size.y = -screenrect.size.y;
|
||||
#ifdef WINDOWS_ENABLED
|
||||
if (!screen_flipped_y)
|
||||
#endif
|
||||
{
|
||||
// Flip Y.
|
||||
screenrect.position.y = win_size.y - screenrect.position.y;
|
||||
screenrect.size.y = -screenrect.size.y;
|
||||
}
|
||||
|
||||
// Normalize texture coordinates to window size.
|
||||
screenrect.position /= win_size;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "effects/copy_effects.h"
|
||||
#include "effects/cubemap_filter.h"
|
||||
#include "effects/feed_effects.h"
|
||||
#include "effects/glow.h"
|
||||
#include "effects/post_effects.h"
|
||||
#include "environment/fog.h"
|
||||
|
|
@ -58,6 +59,10 @@ private:
|
|||
double time_total = 0.0;
|
||||
bool flip_xy_workaround = false;
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
static bool screen_flipped_y;
|
||||
#endif
|
||||
|
||||
static bool gles_over_gl;
|
||||
|
||||
protected:
|
||||
|
|
@ -74,6 +79,7 @@ protected:
|
|||
GLES3::CubemapFilter *cubemap_filter = nullptr;
|
||||
GLES3::Glow *glow = nullptr;
|
||||
GLES3::PostEffects *post_effects = nullptr;
|
||||
GLES3::FeedEffects *feed_effects = nullptr;
|
||||
RasterizerCanvasGLES3 *canvas = nullptr;
|
||||
RasterizerSceneGLES3 *scene = nullptr;
|
||||
static RasterizerGLES3 *singleton;
|
||||
|
|
@ -113,13 +119,21 @@ public:
|
|||
|
||||
static void make_current(bool p_gles_over_gl) {
|
||||
gles_over_gl = p_gles_over_gl;
|
||||
OS::get_singleton()->set_gles_over_gl(gles_over_gl);
|
||||
_create_func = _create_current;
|
||||
low_end = true;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
static void set_screen_flipped_y(bool p_flipped) {
|
||||
screen_flipped_y = p_flipped;
|
||||
}
|
||||
#endif
|
||||
|
||||
_ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
|
||||
_ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; }
|
||||
_ALWAYS_INLINE_ double get_total_time() const { return time_total; }
|
||||
_ALWAYS_INLINE_ bool can_create_resources_async() const { return false; }
|
||||
|
||||
static RasterizerGLES3 *get_singleton() { return singleton; }
|
||||
RasterizerGLES3();
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "rasterizer_scene_gles3.h"
|
||||
|
||||
#include "drivers/gles3/effects/copy_effects.h"
|
||||
#include "drivers/gles3/effects/feed_effects.h"
|
||||
#include "rasterizer_gles3.h"
|
||||
#include "storage/config.h"
|
||||
#include "storage/mesh_storage.h"
|
||||
|
|
@ -39,6 +40,8 @@
|
|||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/templates/sort_array.h"
|
||||
#include "servers/camera/camera_feed.h"
|
||||
#include "servers/camera_server.h"
|
||||
#include "servers/rendering/rendering_server_default.h"
|
||||
#include "servers/rendering/rendering_server_globals.h"
|
||||
|
||||
|
|
@ -235,7 +238,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
|
|||
|
||||
GLES3::SceneMaterialData *material_shadow = nullptr;
|
||||
void *surface_shadow = nullptr;
|
||||
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_world_coordinates) {
|
||||
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_world_coordinates && !p_material->shader_data->wireframe) {
|
||||
flags |= GeometryInstanceSurface::FLAG_USES_SHARED_SHADOW_MATERIAL;
|
||||
material_shadow = static_cast<GLES3::SceneMaterialData *>(GLES3::MaterialStorage::get_singleton()->material_get_data(scene_globals.default_material, RS::SHADER_SPATIAL));
|
||||
|
||||
|
|
@ -777,7 +780,6 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
|
|||
ERR_FAIL_COND(p_env.is_null());
|
||||
|
||||
Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env));
|
||||
ERR_FAIL_NULL(sky);
|
||||
|
||||
GLES3::SkyMaterialData *material_data = nullptr;
|
||||
RID sky_material;
|
||||
|
|
@ -851,6 +853,15 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
|
|||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::SKY_ENERGY_MULTIPLIER, p_sky_energy_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
|
||||
Color fog_color = environment_get_fog_light_color(p_env).srgb_to_linear() * environment_get_fog_light_energy(p_env);
|
||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_ENABLED, environment_get_fog_enabled(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_AERIAL_PERSPECTIVE, environment_get_fog_aerial_perspective(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_LIGHT_COLOR, fog_color, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_SUN_SCATTER, environment_get_fog_sun_scatter(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_DENSITY, environment_get_fog_density(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_SKY_AFFECT, environment_get_fog_sky_affect(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::DIRECTIONAL_LIGHT_COUNT, sky_globals.directional_light_count, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants);
|
||||
|
||||
if (p_use_multiview) {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
|
@ -904,7 +915,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
|
|||
RS::SkyMode sky_mode = sky->mode;
|
||||
|
||||
if (sky_mode == RS::SKY_MODE_AUTOMATIC) {
|
||||
if (shader_data->uses_time || shader_data->uses_position) {
|
||||
if ((shader_data->uses_time || shader_data->uses_position) && sky->radiance_size == 256) {
|
||||
update_single_frame = true;
|
||||
sky_mode = RS::SKY_MODE_REALTIME;
|
||||
} else if (shader_data->uses_light || shader_data->ubo_size > 0) {
|
||||
|
|
@ -925,7 +936,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
|
|||
int max_processing_layer = sky->mipmap_count;
|
||||
|
||||
// Update radiance cubemap
|
||||
if (sky->reflection_dirty && (sky->processing_layer > max_processing_layer || update_single_frame)) {
|
||||
if (sky->reflection_dirty && (sky->processing_layer >= max_processing_layer || update_single_frame)) {
|
||||
static const Vector3 view_normals[6] = {
|
||||
Vector3(+1, 0, 0),
|
||||
Vector3(-1, 0, 0),
|
||||
|
|
@ -966,7 +977,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, sky->radiance_framebuffer);
|
||||
|
||||
scene_state.reset_gl_state();
|
||||
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||
scene_state.set_gl_cull_mode(RS::CULL_MODE_DISABLED);
|
||||
scene_state.enable_gl_blend(false);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
|
|
@ -989,7 +1000,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
|
|||
} else {
|
||||
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
|
||||
scene_state.reset_gl_state();
|
||||
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||
scene_state.set_gl_cull_mode(RS::CULL_MODE_DISABLED);
|
||||
scene_state.enable_gl_blend(false);
|
||||
|
||||
cubemap_filter->filter_radiance(sky->raw_radiance, sky->radiance, sky->radiance_framebuffer, sky->radiance_size, sky->mipmap_count, sky->processing_layer);
|
||||
|
|
@ -1291,15 +1302,12 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
|
|||
int32_t shadow_id = light_storage->light_instance_get_shadow_id(light_instance);
|
||||
|
||||
if (light_storage->light_has_shadow(light) && shadow_id >= 0) {
|
||||
// Skip static lights when a lightmap is used.
|
||||
if (!inst->lightmap_instance.is_valid() || light_storage->light_get_bake_mode(light) != RenderingServer::LIGHT_BAKE_STATIC) {
|
||||
GeometryInstanceGLES3::LightPass pass;
|
||||
pass.light_id = light_storage->light_instance_get_gl_id(light_instance);
|
||||
pass.shadow_id = shadow_id;
|
||||
pass.light_instance_rid = light_instance;
|
||||
pass.is_omni = true;
|
||||
inst->light_passes.push_back(pass);
|
||||
}
|
||||
GeometryInstanceGLES3::LightPass pass;
|
||||
pass.light_id = light_storage->light_instance_get_gl_id(light_instance);
|
||||
pass.shadow_id = shadow_id;
|
||||
pass.light_instance_rid = light_instance;
|
||||
pass.is_omni = true;
|
||||
inst->light_passes.push_back(pass);
|
||||
} else {
|
||||
// Lights without shadow can all go in base pass.
|
||||
inst->omni_light_gl_cache.push_back((uint32_t)light_storage->light_instance_get_gl_id(light_instance));
|
||||
|
|
@ -1317,14 +1325,11 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
|
|||
int32_t shadow_id = light_storage->light_instance_get_shadow_id(light_instance);
|
||||
|
||||
if (light_storage->light_has_shadow(light) && shadow_id >= 0) {
|
||||
// Skip static lights when a lightmap is used.
|
||||
if (!inst->lightmap_instance.is_valid() || light_storage->light_get_bake_mode(light) != RenderingServer::LIGHT_BAKE_STATIC) {
|
||||
GeometryInstanceGLES3::LightPass pass;
|
||||
pass.light_id = light_storage->light_instance_get_gl_id(light_instance);
|
||||
pass.shadow_id = shadow_id;
|
||||
pass.light_instance_rid = light_instance;
|
||||
inst->light_passes.push_back(pass);
|
||||
}
|
||||
GeometryInstanceGLES3::LightPass pass;
|
||||
pass.light_id = light_storage->light_instance_get_gl_id(light_instance);
|
||||
pass.shadow_id = shadow_id;
|
||||
pass.light_instance_rid = light_instance;
|
||||
inst->light_passes.push_back(pass);
|
||||
} else {
|
||||
// Lights without shadow can all go in base pass.
|
||||
inst->spot_light_gl_cache.push_back((uint32_t)light_storage->light_instance_get_gl_id(light_instance));
|
||||
|
|
@ -1355,38 +1360,25 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
|
|||
|
||||
GeometryInstanceSurface *surf = inst->surface_caches;
|
||||
|
||||
float lod_distance = 0.0;
|
||||
|
||||
if (p_render_data->cam_orthogonal) {
|
||||
lod_distance = 1.0;
|
||||
} else {
|
||||
Vector3 aabb_min = inst->transformed_aabb.position;
|
||||
Vector3 aabb_max = inst->transformed_aabb.position + inst->transformed_aabb.size;
|
||||
Vector3 camera_position = p_render_data->main_cam_transform.origin;
|
||||
Vector3 surface_distance = Vector3(0.0, 0.0, 0.0).max(aabb_min - camera_position).max(camera_position - aabb_max);
|
||||
|
||||
lod_distance = surface_distance.length();
|
||||
}
|
||||
|
||||
while (surf) {
|
||||
// LOD
|
||||
|
||||
if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
|
||||
float distance = 0.0;
|
||||
|
||||
// Check if camera is NOT inside the mesh AABB.
|
||||
if (!inst->transformed_aabb.has_point(p_render_data->main_cam_transform.origin)) {
|
||||
// Get the LOD support points on the mesh AABB.
|
||||
Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z));
|
||||
Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z));
|
||||
|
||||
// Get the distances to those points on the AABB from the camera origin.
|
||||
float distance_min = (float)p_render_data->main_cam_transform.origin.distance_to(lod_support_min);
|
||||
float distance_max = (float)p_render_data->main_cam_transform.origin.distance_to(lod_support_max);
|
||||
|
||||
if (distance_min * distance_max < 0.0) {
|
||||
//crossing plane
|
||||
distance = 0.0;
|
||||
} else if (distance_min >= 0.0) {
|
||||
distance = distance_min;
|
||||
} else if (distance_max <= 0.0) {
|
||||
distance = -distance_max;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_render_data->cam_orthogonal) {
|
||||
distance = 1.0;
|
||||
}
|
||||
|
||||
uint32_t indices = 0;
|
||||
surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, indices);
|
||||
surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, lod_distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, indices);
|
||||
surf->index_count = indices;
|
||||
|
||||
if (p_render_data->render_info) {
|
||||
|
|
@ -1441,6 +1433,10 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
|
|||
if (surf->flags & GeometryInstanceSurface::FLAG_PASS_SHADOW) {
|
||||
rl->add_element(surf);
|
||||
}
|
||||
} else if (p_pass_mode == PASS_MODE_MATERIAL) {
|
||||
if (surf->flags & (GeometryInstanceSurface::FLAG_PASS_DEPTH | GeometryInstanceSurface::FLAG_PASS_OPAQUE | GeometryInstanceSurface::FLAG_PASS_ALPHA)) {
|
||||
rl->add_element(surf);
|
||||
}
|
||||
} else {
|
||||
if (surf->flags & (GeometryInstanceSurface::FLAG_PASS_DEPTH | GeometryInstanceSurface::FLAG_PASS_OPAQUE)) {
|
||||
rl->add_element(surf);
|
||||
|
|
@ -2137,7 +2133,7 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
|
|||
light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass);
|
||||
shadow_size = shadow_size / 2;
|
||||
} else {
|
||||
ERR_FAIL_MSG("Dual paraboloid shadow mode not supported in GL Compatibility renderer. Please use Cubemap shadow mode instead.");
|
||||
ERR_FAIL_MSG("Dual paraboloid shadow mode not supported in the Compatibility renderer. Please use CubeMap shadow mode instead.");
|
||||
}
|
||||
|
||||
shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
|
||||
|
|
@ -2218,7 +2214,7 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
|
|||
scene_state.enable_gl_depth_test(false);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
glDisable(GL_CULL_FACE);
|
||||
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
||||
scene_state.cull_mode = RS::CULL_MODE_DISABLED;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
||||
}
|
||||
|
||||
|
|
@ -2258,12 +2254,18 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
RenderDataGLES3 render_data;
|
||||
{
|
||||
render_data.render_buffers = rb;
|
||||
render_data.transparent_bg = rt ? rt->is_transparent : false;
|
||||
|
||||
if (rt) {
|
||||
render_data.transparent_bg = rt->is_transparent;
|
||||
render_data.render_region = rt->render_region;
|
||||
}
|
||||
|
||||
// Our first camera is used by default
|
||||
render_data.cam_transform = p_camera_data->main_transform;
|
||||
render_data.inv_cam_transform = render_data.cam_transform.affine_inverse();
|
||||
render_data.cam_projection = p_camera_data->main_projection;
|
||||
render_data.cam_orthogonal = p_camera_data->is_orthogonal;
|
||||
render_data.cam_frustum = p_camera_data->is_frustum;
|
||||
render_data.camera_visible_layers = p_camera_data->visible_layers;
|
||||
render_data.main_cam_transform = p_camera_data->main_transform;
|
||||
|
||||
|
|
@ -2387,7 +2389,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
bool draw_sky = false;
|
||||
bool draw_sky_fog_only = false;
|
||||
bool keep_color = false;
|
||||
bool draw_canvas = false;
|
||||
bool draw_feed = false;
|
||||
float sky_energy_multiplier = 1.0;
|
||||
int camera_feed_id = -1;
|
||||
|
||||
if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW)) {
|
||||
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
|
||||
|
|
@ -2426,12 +2431,15 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
draw_sky = !render_data.transparent_bg;
|
||||
} break;
|
||||
case RS::ENV_BG_CANVAS: {
|
||||
keep_color = true;
|
||||
draw_canvas = true;
|
||||
} break;
|
||||
case RS::ENV_BG_KEEP: {
|
||||
keep_color = true;
|
||||
} break;
|
||||
case RS::ENV_BG_CAMERA_FEED: {
|
||||
camera_feed_id = environment_get_camera_feed_id(render_data.environment);
|
||||
draw_feed = true;
|
||||
keep_color = true;
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
|
|
@ -2490,6 +2498,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
RENDER_TIMESTAMP("Depth Prepass");
|
||||
//pre z pass
|
||||
|
||||
if (render_data.render_region != Rect2i()) {
|
||||
glViewport(render_data.render_region.position.x, render_data.render_region.position.y, render_data.render_region.size.width, render_data.render_region.size.height);
|
||||
}
|
||||
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
scene_state.enable_gl_blend(false);
|
||||
|
|
@ -2543,10 +2555,14 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
if (!keep_color) {
|
||||
// Need to clear framebuffer unless:
|
||||
// a) We explicitly request not to (i.e. ENV_BG_KEEP).
|
||||
// b) We are rendering to a non-intermediate framebuffer with ENV_BG_CANVAS (shared between 2D and 3D).
|
||||
if (!keep_color && (!draw_canvas || fbo != rt->fbo)) {
|
||||
clear_color.a = render_data.transparent_bg ? 0.0f : 1.0f;
|
||||
glClearBufferfv(GL_COLOR, 0, clear_color.components);
|
||||
} else if (fbo != rt->fbo) {
|
||||
}
|
||||
if ((keep_color || draw_canvas) && fbo != rt->fbo) {
|
||||
// Need to copy our current contents to our intermediate/MSAA buffer
|
||||
GLES3::CopyEffects *copy_effects = GLES3::CopyEffects::get_singleton();
|
||||
|
||||
|
|
@ -2557,11 +2573,18 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
glBindTexture(rt->view_count > 1 ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D, rt->color);
|
||||
|
||||
copy_effects->copy_screen(render_data.luminance_multiplier);
|
||||
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP("Render Opaque Pass");
|
||||
uint64_t spec_constant_base_flags = 0;
|
||||
|
||||
if (render_data.render_region != Rect2i()) {
|
||||
glViewport(render_data.render_region.position.x, render_data.render_region.position.y, render_data.render_region.size.width, render_data.render_region.size.height);
|
||||
}
|
||||
|
||||
{
|
||||
// Specialization Constants that apply for entire rendering pass.
|
||||
if (render_data.directional_light_count == 0) {
|
||||
|
|
@ -2580,6 +2603,29 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
spec_constant_base_flags |= SceneShaderGLES3::APPLY_TONEMAPPING;
|
||||
}
|
||||
}
|
||||
|
||||
if (draw_feed && camera_feed_id > -1) {
|
||||
RENDER_TIMESTAMP("Render Camera feed");
|
||||
|
||||
scene_state.enable_gl_depth_draw(false);
|
||||
scene_state.enable_gl_depth_test(false);
|
||||
scene_state.enable_gl_blend(false);
|
||||
scene_state.set_gl_cull_mode(RS::CULL_MODE_BACK);
|
||||
|
||||
Ref<CameraFeed> feed = CameraServer::get_singleton()->get_feed_by_id(camera_feed_id);
|
||||
|
||||
if (feed.is_valid()) {
|
||||
RID camera_YCBCR = feed->get_texture(CameraServer::FEED_YCBCR_IMAGE);
|
||||
GLES3::TextureStorage::get_singleton()->texture_bind(camera_YCBCR, 0);
|
||||
|
||||
GLES3::FeedEffects *feed_effects = GLES3::FeedEffects::get_singleton();
|
||||
feed_effects->draw();
|
||||
}
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_blend(true);
|
||||
}
|
||||
|
||||
// Render Opaque Objects.
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe);
|
||||
|
||||
|
|
@ -2587,21 +2633,25 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
|
||||
scene_state.enable_gl_depth_draw(false);
|
||||
|
||||
if (draw_sky) {
|
||||
if (draw_sky || draw_sky_fog_only) {
|
||||
RENDER_TIMESTAMP("Render Sky");
|
||||
|
||||
scene_state.enable_gl_depth_test(true);
|
||||
scene_state.enable_gl_blend(false);
|
||||
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_BACK);
|
||||
scene_state.set_gl_cull_mode(RS::CULL_MODE_BACK);
|
||||
|
||||
Transform3D transform = render_data.cam_transform;
|
||||
Projection projection = render_data.cam_projection;
|
||||
if (is_reflection_probe) {
|
||||
Projection correction;
|
||||
correction.columns[1][1] = -1.0;
|
||||
projection = correction * render_data.cam_projection;
|
||||
} else if (render_data.cam_frustum) {
|
||||
// Sky is drawn upside down, the frustum offset doesn't know the image is upside down so needs a flip.
|
||||
projection[2].y = -projection[2].y;
|
||||
}
|
||||
|
||||
_draw_sky(render_data.environment, projection, render_data.cam_transform, sky_energy_multiplier, render_data.luminance_multiplier, p_camera_data->view_count > 1, flip_y, apply_color_adjustments_in_post);
|
||||
_draw_sky(render_data.environment, projection, transform, sky_energy_multiplier, render_data.luminance_multiplier, p_camera_data->view_count > 1, flip_y, apply_color_adjustments_in_post);
|
||||
}
|
||||
|
||||
if (rt && (scene_state.used_screen_texture || scene_state.used_depth_texture)) {
|
||||
|
|
@ -2633,14 +2683,14 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
|
|||
glBlitFramebuffer(0, 0, size.x, size.y,
|
||||
0, 0, size.x, size.y,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 5);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 6);
|
||||
glBindTexture(GL_TEXTURE_2D, backbuffer);
|
||||
}
|
||||
if (scene_state.used_depth_texture) {
|
||||
glBlitFramebuffer(0, 0, size.x, size.y,
|
||||
0, 0, size.x, size.y,
|
||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 6);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 7);
|
||||
glBindTexture(GL_TEXTURE_2D, backbuffer_depth);
|
||||
}
|
||||
}
|
||||
|
|
@ -3072,19 +3122,19 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
}
|
||||
|
||||
// Find cull variant.
|
||||
GLES3::SceneShaderData::Cull cull_mode = shader->cull_mode;
|
||||
RS::CullMode cull_mode = shader->cull_mode;
|
||||
|
||||
if (p_pass_mode == PASS_MODE_MATERIAL || (surf->flags & GeometryInstanceSurface::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {
|
||||
cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
|
||||
cull_mode = RS::CULL_MODE_DISABLED;
|
||||
} else {
|
||||
bool mirror = inst->mirror;
|
||||
if (p_params->reverse_cull) {
|
||||
mirror = !mirror;
|
||||
}
|
||||
if (cull_mode == GLES3::SceneShaderData::CULL_FRONT && mirror) {
|
||||
cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
||||
} else if (cull_mode == GLES3::SceneShaderData::CULL_BACK && mirror) {
|
||||
cull_mode = GLES3::SceneShaderData::CULL_FRONT;
|
||||
if (cull_mode == RS::CULL_MODE_FRONT && mirror) {
|
||||
cull_mode = RS::CULL_MODE_BACK;
|
||||
} else if (cull_mode == RS::CULL_MODE_BACK && mirror) {
|
||||
cull_mode = RS::CULL_MODE_FRONT;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3124,7 +3174,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
}
|
||||
|
||||
bool use_wireframe = false;
|
||||
if (p_params->force_wireframe) {
|
||||
if (p_params->force_wireframe || shader->wireframe) {
|
||||
GLuint wireframe_index_array_gl = mesh_storage->mesh_surface_get_index_buffer_wireframe(mesh_surface);
|
||||
if (wireframe_index_array_gl) {
|
||||
index_array_gl = wireframe_index_array_gl;
|
||||
|
|
@ -3202,6 +3252,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
if (lm->uses_spherical_harmonics) {
|
||||
spec_constants |= SceneShaderGLES3::USE_SH_LIGHTMAP;
|
||||
}
|
||||
|
||||
if (lightmap_bicubic_upscale) {
|
||||
spec_constants |= SceneShaderGLES3::LIGHTMAP_BICUBIC_FILTER;
|
||||
}
|
||||
} else if (inst->lightmap_sh) {
|
||||
spec_constants |= SceneShaderGLES3::USE_LIGHTMAP_CAPTURE;
|
||||
} else {
|
||||
|
|
@ -3214,8 +3268,28 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_OMNI;
|
||||
spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_SPOT;
|
||||
spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL;
|
||||
spec_constants |= SceneShaderGLES3::DISABLE_LIGHTMAP;
|
||||
spec_constants |= SceneShaderGLES3::DISABLE_REFLECTION_PROBE;
|
||||
|
||||
bool disable_lightmaps = true;
|
||||
|
||||
// Additive directional passes may use shadowmasks, so enable lightmaps for them.
|
||||
if (pass >= int32_t(inst->light_passes.size()) && inst->lightmap_instance.is_valid()) {
|
||||
GLES3::LightmapInstance *li = GLES3::LightStorage::get_singleton()->get_lightmap_instance(inst->lightmap_instance);
|
||||
GLES3::Lightmap *lm = GLES3::LightStorage::get_singleton()->get_lightmap(li->lightmap);
|
||||
|
||||
if (lm->shadowmask_mode != RS::SHADOWMASK_MODE_NONE) {
|
||||
spec_constants |= SceneShaderGLES3::USE_LIGHTMAP;
|
||||
disable_lightmaps = false;
|
||||
|
||||
if (lightmap_bicubic_upscale) {
|
||||
spec_constants |= SceneShaderGLES3::LIGHTMAP_BICUBIC_FILTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (disable_lightmaps) {
|
||||
spec_constants |= SceneShaderGLES3::DISABLE_LIGHTMAP;
|
||||
}
|
||||
}
|
||||
|
||||
if (uses_additive_lighting) {
|
||||
|
|
@ -3277,10 +3351,6 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
}
|
||||
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, instance_variant, spec_constants);
|
||||
|
||||
prev_shader = shader;
|
||||
prev_variant = instance_variant;
|
||||
prev_spec_constants = spec_constants;
|
||||
}
|
||||
|
||||
// Pass in lighting uniforms.
|
||||
|
|
@ -3314,11 +3384,38 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
GLuint tex = GLES3::LightStorage::get_singleton()->directional_shadow_get_texture();
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 3);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
if (inst->lightmap_instance.is_valid()) {
|
||||
// Use shadowmasks for directional light passes.
|
||||
GLES3::LightmapInstance *li = GLES3::LightStorage::get_singleton()->get_lightmap_instance(inst->lightmap_instance);
|
||||
GLES3::Lightmap *lm = GLES3::LightStorage::get_singleton()->get_lightmap(li->lightmap);
|
||||
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_SLICE, inst->lightmap_slice_index, shader->version, instance_variant, spec_constants);
|
||||
|
||||
Vector4 uv_scale(inst->lightmap_uv_scale.position.x, inst->lightmap_uv_scale.position.y, inst->lightmap_uv_scale.size.x, inst->lightmap_uv_scale.size.y);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_UV_SCALE, uv_scale, shader->version, instance_variant, spec_constants);
|
||||
|
||||
if (lightmap_bicubic_upscale) {
|
||||
Vector2 light_texture_size(lm->light_texture_size.x, lm->light_texture_size.y);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_TEXTURE_SIZE, light_texture_size, shader->version, instance_variant, spec_constants);
|
||||
}
|
||||
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_SHADOWMASK_MODE, (uint32_t)lm->shadowmask_mode, shader->version, instance_variant, spec_constants);
|
||||
|
||||
if (lm->shadow_texture.is_valid()) {
|
||||
tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lm->shadow_texture);
|
||||
} else {
|
||||
tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(GLES3::TextureStorage::get_singleton()->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_2D_ARRAY_WHITE));
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 5);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass light count and array of light indices for base pass.
|
||||
if ((prev_inst != inst || prev_shader != shader || prev_variant != instance_variant) && pass == 0) {
|
||||
if ((prev_inst != inst || prev_shader != shader || prev_variant != instance_variant || prev_spec_constants != spec_constants) && pass == 0) {
|
||||
// Rebind the light indices.
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_gl_cache.size(), shader->version, instance_variant, spec_constants);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_gl_cache.size(), shader->version, instance_variant, spec_constants);
|
||||
|
|
@ -3344,6 +3441,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
Vector4 uv_scale(inst->lightmap_uv_scale.position.x, inst->lightmap_uv_scale.position.y, inst->lightmap_uv_scale.size.x, inst->lightmap_uv_scale.size.y);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_UV_SCALE, uv_scale, shader->version, instance_variant, spec_constants);
|
||||
|
||||
if (lightmap_bicubic_upscale) {
|
||||
Vector2 light_texture_size(lm->light_texture_size.x, lm->light_texture_size.y);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_TEXTURE_SIZE, light_texture_size, shader->version, instance_variant, spec_constants);
|
||||
}
|
||||
|
||||
float exposure_normalization = 1.0;
|
||||
if (p_render_data->camera_attributes.is_valid()) {
|
||||
float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
|
||||
|
|
@ -3367,14 +3469,18 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
};
|
||||
glUniformMatrix3fv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::LIGHTMAP_NORMAL_XFORM, shader->version, instance_variant, spec_constants), 1, GL_FALSE, matrix);
|
||||
}
|
||||
|
||||
} else if (inst->lightmap_sh) {
|
||||
glUniform4fv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::LIGHTMAP_CAPTURES, shader->version, instance_variant, spec_constants), 9, reinterpret_cast<const GLfloat *>(inst->lightmap_sh->sh));
|
||||
}
|
||||
|
||||
prev_inst = inst;
|
||||
}
|
||||
}
|
||||
|
||||
prev_shader = shader;
|
||||
prev_variant = instance_variant;
|
||||
prev_spec_constants = spec_constants;
|
||||
|
||||
// Pass in reflection probe data
|
||||
if constexpr (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
|
||||
if (pass == 0 && inst->reflection_probe_rid_cache.size() > 0) {
|
||||
|
|
@ -3394,8 +3500,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::REFPROBE1_AMBIENT_MODE, int(probe->ambient_mode), shader->version, instance_variant, spec_constants);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::REFPROBE1_AMBIENT_COLOR, probe->ambient_color * probe->ambient_color_energy, shader->version, instance_variant, spec_constants);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::REFPROBE1_LOCAL_MATRIX, inst->reflection_probes_local_transform_cache[0], shader->version, instance_variant, spec_constants);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::REFPROBE1_BLEND_DISTANCE, probe->blend_distance, shader->version, instance_variant, spec_constants);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 7);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 8);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, light_storage->reflection_probe_instance_get_texture(inst->reflection_probe_rid_cache[0]));
|
||||
}
|
||||
|
||||
|
|
@ -3412,8 +3519,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::REFPROBE2_AMBIENT_MODE, int(probe->ambient_mode), shader->version, instance_variant, spec_constants);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::REFPROBE2_AMBIENT_COLOR, probe->ambient_color * probe->ambient_color_energy, shader->version, instance_variant, spec_constants);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::REFPROBE2_LOCAL_MATRIX, inst->reflection_probes_local_transform_cache[1], shader->version, instance_variant, spec_constants);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::REFPROBE2_BLEND_DISTANCE, probe->blend_distance, shader->version, instance_variant, spec_constants);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 8);
|
||||
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 9);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, light_storage->reflection_probe_instance_get_texture(inst->reflection_probe_rid_cache[1]));
|
||||
|
||||
spec_constants |= SceneShaderGLES3::SECOND_REFLECTION_PROBE;
|
||||
|
|
@ -3436,6 +3544,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
|||
}
|
||||
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::MODEL_FLAGS, inst->flags_cache, shader->version, instance_variant, spec_constants);
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::INSTANCE_OFFSET, uint32_t(inst->shader_uniforms_offset), shader->version, instance_variant, spec_constants);
|
||||
|
||||
if (p_pass_mode == PASS_MODE_MATERIAL) {
|
||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::UV_OFFSET, p_params->uv_offset, shader->version, instance_variant, spec_constants);
|
||||
|
|
@ -3746,7 +3855,7 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
scene_state.enable_gl_depth_draw(true);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
|
||||
scene_state.set_gl_cull_mode(RS::CULL_MODE_DISABLED);
|
||||
|
||||
// Loop through quadrants and copy shadows over.
|
||||
for (int quadrant = 0; quadrant < 4; quadrant++) {
|
||||
|
|
@ -3882,7 +3991,7 @@ TypedArray<Image> RasterizerSceneGLES3::bake_render_uv2(RID p_base, const TypedA
|
|||
// Consider rendering to RGBA8 encoded as RGBE, then manually convert to RGBAH on CPU.
|
||||
glBindTexture(GL_TEXTURE_2D, emission_tex);
|
||||
if (config->float_texture_supported) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, p_image_size.width, p_image_size.height, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, p_image_size.width, p_image_size.height, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||
GLES3::Utilities::get_singleton()->texture_allocated_data(emission_tex, p_image_size.width * p_image_size.height * 16, "Lightmap emission texture");
|
||||
} else {
|
||||
// Fallback to RGBA8 on devices that don't support rendering to floating point textures. This will look bad, but we have no choice.
|
||||
|
|
@ -3985,9 +4094,9 @@ TypedArray<Image> RasterizerSceneGLES3::bake_render_uv2(RID p_base, const TypedA
|
|||
{
|
||||
tex->tex_id = emission_tex;
|
||||
if (config->float_texture_supported) {
|
||||
tex->format = Image::FORMAT_RGBAF;
|
||||
tex->format = Image::FORMAT_RGBAH;
|
||||
tex->real_format = Image::FORMAT_RGBAH;
|
||||
tex->gl_type_cache = GL_FLOAT;
|
||||
tex->gl_type_cache = GL_HALF_FLOAT;
|
||||
}
|
||||
Ref<Image> img = GLES3::TextureStorage::get_singleton()->texture_2d_get(tex_rid);
|
||||
GLES3::Utilities::get_singleton()->texture_free_data(emission_tex);
|
||||
|
|
@ -4039,6 +4148,10 @@ void RasterizerSceneGLES3::decals_set_filter(RS::DecalFilter p_filter) {
|
|||
void RasterizerSceneGLES3::light_projectors_set_filter(RS::LightProjectorFilter p_filter) {
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::lightmaps_set_bicubic_filter(bool p_enable) {
|
||||
lightmap_bicubic_upscale = p_enable;
|
||||
}
|
||||
|
||||
RasterizerSceneGLES3::RasterizerSceneGLES3() {
|
||||
singleton = this;
|
||||
|
||||
|
|
@ -4052,6 +4165,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
|
|||
|
||||
positional_soft_shadow_filter_set_quality((RS::ShadowQuality)(int)GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality"));
|
||||
directional_soft_shadow_filter_set_quality((RS::ShadowQuality)(int)GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality"));
|
||||
lightmaps_set_bicubic_filter(GLOBAL_GET("rendering/lightmapping/lightmap_gi/use_bicubic_filter"));
|
||||
|
||||
{
|
||||
// Setup Lights
|
||||
|
|
@ -4113,6 +4227,9 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
|
|||
global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n";
|
||||
global_defines += "\n#define MAX_FORWARD_LIGHTS " + itos(config->max_lights_per_object) + "u\n";
|
||||
global_defines += "\n#define MAX_ROUGHNESS_LOD " + itos(sky_globals.roughness_layers - 1) + ".0\n";
|
||||
if (config->force_vertex_shading) {
|
||||
global_defines += "\n#define USE_VERTEX_LIGHTING\n";
|
||||
}
|
||||
material_storage->shaders.scene_shader.initialize(global_defines);
|
||||
scene_globals.shader_default_version = material_storage->shaders.scene_shader.version_create();
|
||||
material_storage->shaders.scene_shader.version_bind_shader(scene_globals.shader_default_version, SceneShaderGLES3::MODE_COLOR);
|
||||
|
|
|
|||
|
|
@ -98,11 +98,13 @@ enum SkyUniformLocation {
|
|||
struct RenderDataGLES3 {
|
||||
Ref<RenderSceneBuffersGLES3> render_buffers;
|
||||
bool transparent_bg = false;
|
||||
Rect2i render_region;
|
||||
|
||||
Transform3D cam_transform;
|
||||
Transform3D inv_cam_transform;
|
||||
Projection cam_projection;
|
||||
bool cam_orthogonal = false;
|
||||
bool cam_frustum = false;
|
||||
uint32_t camera_visible_layers = 0xFFFFFFFF;
|
||||
|
||||
// For billboards to cast correct shadows.
|
||||
|
|
@ -248,6 +250,10 @@ private:
|
|||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint64_t sort_key1;
|
||||
uint64_t sort_key2;
|
||||
};
|
||||
struct {
|
||||
uint64_t lod_index : 8;
|
||||
uint64_t surface_index : 8;
|
||||
|
|
@ -263,10 +269,6 @@ private:
|
|||
uint64_t depth_layer : 4;
|
||||
uint64_t priority : 8;
|
||||
};
|
||||
struct {
|
||||
uint64_t sort_key1;
|
||||
uint64_t sort_key2;
|
||||
};
|
||||
} sort;
|
||||
|
||||
RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
|
||||
|
|
@ -460,7 +462,7 @@ private:
|
|||
bool used_depth_prepass = false;
|
||||
|
||||
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
||||
GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
||||
RS::CullMode cull_mode = RS::CULL_MODE_BACK;
|
||||
|
||||
bool current_blend_enabled = false;
|
||||
bool current_depth_draw_enabled = false;
|
||||
|
|
@ -476,7 +478,7 @@ private:
|
|||
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_CULL_FACE);
|
||||
cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
||||
cull_mode = RS::CULL_MODE_BACK;
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
current_depth_draw_enabled = false;
|
||||
|
|
@ -484,16 +486,16 @@ private:
|
|||
current_depth_test_enabled = false;
|
||||
}
|
||||
|
||||
void set_gl_cull_mode(GLES3::SceneShaderData::Cull p_mode) {
|
||||
void set_gl_cull_mode(RS::CullMode p_mode) {
|
||||
if (cull_mode != p_mode) {
|
||||
if (p_mode == GLES3::SceneShaderData::CULL_DISABLED) {
|
||||
if (p_mode == RS::CULL_MODE_DISABLED) {
|
||||
glDisable(GL_CULL_FACE);
|
||||
} else {
|
||||
if (cull_mode == GLES3::SceneShaderData::CULL_DISABLED) {
|
||||
if (cull_mode == RS::CULL_MODE_DISABLED) {
|
||||
// Last time was disabled, so enable and set proper face.
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
glCullFace(p_mode == GLES3::SceneShaderData::CULL_FRONT ? GL_FRONT : GL_BACK);
|
||||
glCullFace(p_mode == RS::CULL_MODE_FRONT ? GL_FRONT : GL_BACK);
|
||||
}
|
||||
cull_mode = p_mode;
|
||||
}
|
||||
|
|
@ -680,6 +682,8 @@ protected:
|
|||
bool glow_bicubic_upscale = false;
|
||||
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
|
||||
|
||||
bool lightmap_bicubic_upscale = false;
|
||||
|
||||
/* Sky */
|
||||
|
||||
struct SkyGlobals {
|
||||
|
|
@ -765,6 +769,11 @@ public:
|
|||
|
||||
uint32_t geometry_instance_get_pair_mask() override;
|
||||
|
||||
/* PIPELINES */
|
||||
|
||||
virtual void mesh_generate_pipelines(RID p_mesh, bool p_background_compilation) override {}
|
||||
virtual uint32_t get_pipeline_compilations(RS::PipelineSource p_source) override { return 0; }
|
||||
|
||||
/* SDFGI UPDATE */
|
||||
|
||||
void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
|
||||
|
|
@ -863,6 +872,7 @@ public:
|
|||
|
||||
void decals_set_filter(RS::DecalFilter p_filter) override;
|
||||
void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
|
||||
virtual void lightmaps_set_bicubic_filter(bool p_enable) override;
|
||||
|
||||
RasterizerSceneGLES3();
|
||||
~RasterizerSceneGLES3();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "core/io/compression.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/file_access.h"
|
||||
|
||||
|
|
@ -168,6 +167,10 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant
|
|||
builder.append("#version 300 es\n");
|
||||
}
|
||||
|
||||
if (GLES3::Config::get_singleton()->polyfill_half2float) {
|
||||
builder.append("#define USE_HALF2FLOAT\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < specialization_count; i++) {
|
||||
if (p_specialization & (uint64_t(1) << uint64_t(i))) {
|
||||
builder.append("#define " + String(specializations[i].name) + "\n");
|
||||
|
|
@ -189,6 +192,14 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant
|
|||
}
|
||||
builder.append("\n"); //make sure defines begin at newline
|
||||
|
||||
// Optional support for external textures.
|
||||
if (GLES3::Config::get_singleton()->external_texture_supported) {
|
||||
builder.append("#extension GL_OES_EGL_image_external : enable\n");
|
||||
builder.append("#extension GL_OES_EGL_image_external_essl3 : enable\n");
|
||||
} else {
|
||||
builder.append("#define samplerExternalOES sampler2D\n");
|
||||
}
|
||||
|
||||
// Insert multiview extension loading, because it needs to appear before
|
||||
// any non-preprocessor code (like the "precision highp..." lines below).
|
||||
builder.append("#ifdef USE_MULTIVIEW\n");
|
||||
|
|
@ -698,7 +709,8 @@ void ShaderGLES3::_clear_version(Version *p_version) {
|
|||
|
||||
void ShaderGLES3::_initialize_version(Version *p_version) {
|
||||
ERR_FAIL_COND(p_version->variants.size() > 0);
|
||||
if (shader_cache_dir_valid && _load_from_cache(p_version)) {
|
||||
bool use_cache = shader_cache_dir_valid && !(feedback_count > 0 && GLES3::Config::get_singleton()->disable_transform_feedback_shader_cache);
|
||||
if (use_cache && _load_from_cache(p_version)) {
|
||||
return;
|
||||
}
|
||||
p_version->variants.reserve(variant_count);
|
||||
|
|
@ -709,7 +721,7 @@ void ShaderGLES3::_initialize_version(Version *p_version) {
|
|||
_compile_specialization(spec, i, p_version, specialization_default_mask);
|
||||
p_version->variants[i].insert(specialization_default_mask, spec);
|
||||
}
|
||||
if (shader_cache_dir_valid) {
|
||||
if (use_cache) {
|
||||
_save_to_cache(p_version);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,17 +36,13 @@
|
|||
#include "core/string/string_builder.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rb_map.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "platform_gl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class ShaderGLES3 {
|
||||
public:
|
||||
struct TextureUniformData {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
@ -16,6 +17,7 @@ if "GLES3_GLSL" in env["BUILDERS"]:
|
|||
|
||||
# as we have a few, not yet, converted files we name the ones we want to include:
|
||||
env.GLES3_GLSL("canvas.glsl")
|
||||
env.GLES3_GLSL("feed.glsl")
|
||||
env.GLES3_GLSL("scene.glsl")
|
||||
env.GLES3_GLSL("sky.glsl")
|
||||
env.GLES3_GLSL("canvas_occlusion.glsl")
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_quad =
|
||||
mode_ninepatch = #define USE_NINEPATCH
|
||||
mode_primitive = #define USE_PRIMITIVE
|
||||
mode_attributes = #define USE_ATTRIBUTES
|
||||
mode_instanced = #define USE_ATTRIBUTES \n#define USE_INSTANCING
|
||||
mode_default =
|
||||
|
||||
#[specializations]
|
||||
|
||||
DISABLE_LIGHTING = true
|
||||
USE_RGBA_SHADOWS = false
|
||||
SINGLE_INSTANCE = false
|
||||
USE_NINEPATCH = false
|
||||
USE_PRIMITIVE = false
|
||||
USE_ATTRIBUTES = false
|
||||
USE_INSTANCING = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
|
|
@ -84,7 +83,7 @@ layout(location = 15) in highp uvec4 attrib_H;
|
|||
#endif
|
||||
|
||||
#define read_draw_data_flags attrib_G.z
|
||||
#define read_draw_data_specular_shininess attrib_G.w
|
||||
#define read_draw_data_instance_offset attrib_G.w
|
||||
#define read_draw_data_lights attrib_H
|
||||
|
||||
// Varyings so the per-instance info can be used in the fragment shader
|
||||
|
|
@ -111,6 +110,9 @@ layout(std140) uniform MaterialUniforms{ //ubo:4
|
|||
|
||||
};
|
||||
#endif
|
||||
|
||||
uniform mediump uint batch_flags;
|
||||
|
||||
/* clang-format on */
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
|
||||
|
|
@ -140,7 +142,7 @@ void main() {
|
|||
#endif // !USE_ATTRIBUTES
|
||||
#endif // USE_PRIMITIVE
|
||||
|
||||
varying_F = uvec2(read_draw_data_flags, read_draw_data_specular_shininess);
|
||||
varying_F = uvec2(read_draw_data_flags, read_draw_data_instance_offset);
|
||||
varying_G = read_draw_data_lights;
|
||||
|
||||
vec4 instance_custom = vec4(0.0);
|
||||
|
|
@ -180,13 +182,13 @@ void main() {
|
|||
vec2 uv = uv_attrib;
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
if (bool(read_draw_data_flags & FLAGS_INSTANCING_HAS_COLORS)) {
|
||||
if (bool(batch_flags & BATCH_FLAGS_INSTANCING_HAS_COLORS)) {
|
||||
vec4 instance_color;
|
||||
instance_color.xy = unpackHalf2x16(uint(instance_color_custom_data.x));
|
||||
instance_color.zw = unpackHalf2x16(uint(instance_color_custom_data.y));
|
||||
color *= instance_color;
|
||||
}
|
||||
if (bool(read_draw_data_flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
|
||||
if (bool(batch_flags & BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
|
||||
instance_custom.xy = unpackHalf2x16(instance_color_custom_data.z);
|
||||
instance_custom.zw = unpackHalf2x16(instance_color_custom_data.w);
|
||||
}
|
||||
|
|
@ -206,20 +208,21 @@ void main() {
|
|||
// no crash or freeze on all Adreno 3xx with 'if / else if' and slightly faster!
|
||||
int vertex_id = gl_VertexID % 6;
|
||||
vec2 vertex_base;
|
||||
if (vertex_id == 0)
|
||||
if (vertex_id == 0) {
|
||||
vertex_base = vec2(0.0, 0.0);
|
||||
else if (vertex_id == 1)
|
||||
} else if (vertex_id == 1) {
|
||||
vertex_base = vec2(0.0, 1.0);
|
||||
else if (vertex_id == 2)
|
||||
} else if (vertex_id == 2) {
|
||||
vertex_base = vec2(1.0, 1.0);
|
||||
else if (vertex_id == 3)
|
||||
} else if (vertex_id == 3) {
|
||||
vertex_base = vec2(1.0, 0.0);
|
||||
else if (vertex_id == 4)
|
||||
} else if (vertex_id == 4) {
|
||||
vertex_base = vec2(0.0, 0.0);
|
||||
else if (vertex_id == 5)
|
||||
} else if (vertex_id == 5) {
|
||||
vertex_base = vec2(1.0, 1.0);
|
||||
}
|
||||
|
||||
vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
|
||||
vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & INSTANCE_FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
|
||||
vec4 color = read_draw_data_modulation;
|
||||
vec2 vertex = read_draw_data_dst_rect.xy + abs(read_draw_data_dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(read_draw_data_src_rect.zw, vec2(0.0, 0.0)));
|
||||
|
||||
|
|
@ -262,6 +265,8 @@ void main() {
|
|||
|
||||
color_interp = color;
|
||||
|
||||
vertex = (canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
|
||||
|
||||
if (use_pixel_snap) {
|
||||
vertex = floor(vertex + 0.5);
|
||||
// precision issue on some hardware creates artifacts within texture
|
||||
|
|
@ -269,8 +274,6 @@ void main() {
|
|||
uv += 1e-5;
|
||||
}
|
||||
|
||||
vertex = (canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
|
||||
|
||||
vertex_interp = vertex;
|
||||
uv_interp = uv;
|
||||
|
||||
|
|
@ -323,7 +326,7 @@ flat in vec4 varying_E;
|
|||
flat in uvec2 varying_F;
|
||||
flat in uvec4 varying_G;
|
||||
#define read_draw_data_flags varying_F.x
|
||||
#define read_draw_data_specular_shininess varying_F.y
|
||||
#define read_draw_data_instance_offset varying_F.y
|
||||
#define read_draw_data_lights varying_G
|
||||
|
||||
#ifndef DISABLE_LIGHTING
|
||||
|
|
@ -337,6 +340,9 @@ uniform sampler2D specular_texture; //texunit:-7
|
|||
|
||||
uniform sampler2D color_texture; //texunit:0
|
||||
|
||||
uniform mediump uint batch_flags;
|
||||
uniform highp uint specular_shininess_in;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
/* clang-format off */
|
||||
|
|
@ -520,7 +526,7 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo
|
|||
} else if (pixel >= draw_size - margin_end) {
|
||||
return (tex_size - (draw_size - pixel)) * tex_pixel_size;
|
||||
} else {
|
||||
if (!bool(read_draw_data_flags & FLAGS_NINEPACH_DRAW_CENTER)) {
|
||||
if (!bool(read_draw_data_flags & INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER)) {
|
||||
draw_center--;
|
||||
}
|
||||
|
||||
|
|
@ -568,8 +574,8 @@ void main() {
|
|||
|
||||
int draw_center = 2;
|
||||
uv = vec2(
|
||||
map_ninepatch_axis(pixel_size_interp.x, abs(read_draw_data_dst_rect_z), read_draw_data_color_texture_pixel_size.x, read_draw_data_ninepatch_margins.x, read_draw_data_ninepatch_margins.z, int(read_draw_data_flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center),
|
||||
map_ninepatch_axis(pixel_size_interp.y, abs(read_draw_data_dst_rect_w), read_draw_data_color_texture_pixel_size.y, read_draw_data_ninepatch_margins.y, read_draw_data_ninepatch_margins.w, int(read_draw_data_flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center));
|
||||
map_ninepatch_axis(pixel_size_interp.x, abs(read_draw_data_dst_rect_z), read_draw_data_color_texture_pixel_size.x, read_draw_data_ninepatch_margins.x, read_draw_data_ninepatch_margins.z, int(read_draw_data_flags >> INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center),
|
||||
map_ninepatch_axis(pixel_size_interp.y, abs(read_draw_data_dst_rect_w), read_draw_data_color_texture_pixel_size.y, read_draw_data_ninepatch_margins.y, read_draw_data_ninepatch_margins.w, int(read_draw_data_flags >> INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center));
|
||||
|
||||
if (draw_center == 0) {
|
||||
color.a = 0.0;
|
||||
|
|
@ -578,14 +584,15 @@ void main() {
|
|||
uv = uv * read_draw_data_src_rect.zw + read_draw_data_src_rect.xy; //apply region if needed
|
||||
|
||||
#endif
|
||||
if (bool(read_draw_data_flags & FLAGS_CLIP_RECT_UV)) {
|
||||
uv = clamp(uv, read_draw_data_src_rect.xy, read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw));
|
||||
if (bool(read_draw_data_flags & INSTANCE_FLAGS_CLIP_RECT_UV)) {
|
||||
vec2 half_texpixel = read_draw_data_color_texture_pixel_size * 0.5;
|
||||
uv = clamp(uv, read_draw_data_src_rect.xy + half_texpixel, read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) - half_texpixel);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef USE_PRIMITIVE
|
||||
if (bool(read_draw_data_flags & FLAGS_USE_MSDF)) {
|
||||
if (bool(read_draw_data_flags & INSTANCE_FLAGS_USE_MSDF)) {
|
||||
float px_range = read_draw_data_ninepatch_margins.x;
|
||||
float outline_thickness = read_draw_data_ninepatch_margins.y;
|
||||
|
||||
|
|
@ -603,7 +610,7 @@ void main() {
|
|||
float a = clamp(d * px_size + 0.5, 0.0, 1.0);
|
||||
color.a = a * color.a;
|
||||
}
|
||||
} else if (bool(read_draw_data_flags & FLAGS_USE_LCD)) {
|
||||
} else if (bool(read_draw_data_flags & INSTANCE_FLAGS_USE_LCD)) {
|
||||
vec4 lcd_sample = texture(color_texture, uv);
|
||||
if (lcd_sample.a == 1.0) {
|
||||
color.rgb = lcd_sample.rgb * color.a;
|
||||
|
|
@ -617,7 +624,7 @@ void main() {
|
|||
color *= texture(color_texture, uv);
|
||||
}
|
||||
|
||||
uint light_count = (read_draw_data_flags >> uint(FLAGS_LIGHT_COUNT_SHIFT)) & uint(0xF); //max 16 lights
|
||||
uint light_count = read_draw_data_flags & uint(0xF); // Max 16 lights.
|
||||
bool using_light = light_count > 0u || directional_light_count > 0u;
|
||||
|
||||
vec3 normal;
|
||||
|
|
@ -628,17 +635,16 @@ void main() {
|
|||
bool normal_used = false;
|
||||
#endif
|
||||
|
||||
if (normal_used || (using_light && bool(read_draw_data_flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) {
|
||||
if (normal_used || (using_light && bool(batch_flags & BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED))) {
|
||||
normal.xy = texture(normal_texture, uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0);
|
||||
if (bool(read_draw_data_flags & FLAGS_TRANSPOSE_RECT)) {
|
||||
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
if (bool(read_draw_data_flags & INSTANCE_FLAGS_TRANSPOSE_RECT)) {
|
||||
normal.xy = normal.yx;
|
||||
}
|
||||
if (bool(read_draw_data_flags & FLAGS_FLIP_H)) {
|
||||
normal.x = -normal.x;
|
||||
}
|
||||
if (bool(read_draw_data_flags & FLAGS_FLIP_V)) {
|
||||
normal.y = -normal.y;
|
||||
}
|
||||
normal.xy *= sign(read_draw_data_src_rect.zw);
|
||||
#endif
|
||||
|
||||
normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy, normal.xy)));
|
||||
normal_used = true;
|
||||
} else {
|
||||
|
|
@ -654,9 +660,9 @@ void main() {
|
|||
bool specular_shininess_used = false;
|
||||
#endif
|
||||
|
||||
if (specular_shininess_used || (using_light && normal_used && bool(read_draw_data_flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
|
||||
if (specular_shininess_used || (using_light && normal_used && bool(batch_flags & BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
|
||||
specular_shininess = texture(specular_texture, uv);
|
||||
specular_shininess *= godot_unpackUnorm4x8(read_draw_data_specular_shininess);
|
||||
specular_shininess *= godot_unpackUnorm4x8(specular_shininess_in);
|
||||
specular_shininess_used = true;
|
||||
} else {
|
||||
specular_shininess = vec4(1.0);
|
||||
|
|
@ -802,7 +808,7 @@ void main() {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
|
||||
if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(read_draw_data_flags & uint(INSTANCE_FLAGS_SHADOW_MASKED << i))) {
|
||||
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array[light_base].shadow_matrix[0], light_array[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
|
||||
vec2 pos_norm = normalize(shadow_pos);
|
||||
|
|
|
|||
|
|
@ -1,33 +1,32 @@
|
|||
|
||||
#define MAX_LIGHTS_PER_ITEM uint(16)
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
#define SDF_MAX_LENGTH 16384.0
|
||||
|
||||
//1 means enabled, 2+ means trails in use
|
||||
#define FLAGS_INSTANCING_MASK uint(0x7F)
|
||||
#define FLAGS_INSTANCING_HAS_COLORS uint(1 << 7)
|
||||
#define FLAGS_INSTANCING_HAS_CUSTOM_DATA uint(1 << 8)
|
||||
#define INSTANCE_FLAGS_LIGHT_COUNT_SHIFT 0 // 4 bits.
|
||||
|
||||
#define FLAGS_CLIP_RECT_UV uint(1 << 9)
|
||||
#define FLAGS_TRANSPOSE_RECT uint(1 << 10)
|
||||
// (1 << 11) is for FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR in RD backends, unused here.
|
||||
#define FLAGS_NINEPACH_DRAW_CENTER uint(1 << 12)
|
||||
#define INSTANCE_FLAGS_CLIP_RECT_UV uint(1 << 4)
|
||||
#define INSTANCE_FLAGS_TRANSPOSE_RECT uint(1 << 5)
|
||||
#define INSTANCE_FLAGS_USE_MSDF uint(1 << 6)
|
||||
#define INSTANCE_FLAGS_USE_LCD uint(1 << 7)
|
||||
|
||||
#define FLAGS_NINEPATCH_H_MODE_SHIFT 16
|
||||
#define FLAGS_NINEPATCH_V_MODE_SHIFT 18
|
||||
#define INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER uint(1 << 8)
|
||||
#define INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT 9
|
||||
#define INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT 11
|
||||
|
||||
#define FLAGS_LIGHT_COUNT_SHIFT 20
|
||||
#define INSTANCE_FLAGS_SHADOW_MASKED_SHIFT 13u // 16 bits.
|
||||
#define INSTANCE_FLAGS_SHADOW_MASKED uint(1 << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT)
|
||||
|
||||
#define FLAGS_DEFAULT_NORMAL_MAP_USED uint(1 << 26)
|
||||
#define FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 27)
|
||||
// 1 means enabled, 2+ means trails in use
|
||||
#define BATCH_FLAGS_INSTANCING_MASK uint(0x7F)
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT 7
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_COLORS uint(1 << BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT)
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA uint(1 << BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT)
|
||||
|
||||
#define FLAGS_USE_MSDF uint(1 << 28)
|
||||
#define FLAGS_USE_LCD uint(1 << 29)
|
||||
|
||||
#define FLAGS_FLIP_H uint(1 << 30)
|
||||
#define FLAGS_FLIP_V uint(1 << 31)
|
||||
#define BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED uint(1 << 9)
|
||||
#define BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 10)
|
||||
|
||||
layout(std140) uniform GlobalShaderUniformData { //ubo:1
|
||||
vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
39
engine/drivers/gles3/shaders/feed.glsl
Normal file
39
engine/drivers/gles3/shaders/feed.glsl
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* clang-format off */
|
||||
#[modes]
|
||||
|
||||
mode_default =
|
||||
|
||||
#[specializations]
|
||||
|
||||
USE_EXTERNAL_SAMPLER = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
|
||||
out vec2 uv_interp;
|
||||
|
||||
|
||||
void main() {
|
||||
uv_interp = vertex_attrib * 0.5 + 0.5;
|
||||
gl_Position = vec4(vertex_attrib, 1.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
in vec2 uv_interp;
|
||||
|
||||
/* clang-format on */
|
||||
#ifdef USE_EXTERNAL_SAMPLER
|
||||
uniform samplerExternalOES sourceFeed; // texunit:0
|
||||
#else
|
||||
uniform sampler2D sourceFeed; // texunit:0
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec4 color = texture(sourceFeed, uv_interp);
|
||||
|
||||
frag_color = color;
|
||||
}
|
||||
|
|
@ -342,7 +342,7 @@ void main() {
|
|||
mediump float attractor_attenuation = attractors[i].attenuation;
|
||||
amount = pow(amount, attractor_attenuation);
|
||||
dir = safe_normalize(mix(dir, attractors[i].transform[2].xyz, attractors[i].directionality));
|
||||
attractor_force -= amount * dir * attractors[i].strength;
|
||||
attractor_force -= mass * amount * dir * attractors[i].strength;
|
||||
}
|
||||
|
||||
float particle_size = particle_size;
|
||||
|
|
@ -453,14 +453,14 @@ void main() {
|
|||
|
||||
vec3 uvw_pos = vec3(local_pos_bottom / colliders[i].extents.xyz) * 0.5 + 0.5;
|
||||
|
||||
float y = 1.0 - texture(height_field_texture, uvw_pos.xz).r;
|
||||
float y = texture(height_field_texture, uvw_pos.xz).r;
|
||||
|
||||
if (y + EPSILON > uvw_pos.y) {
|
||||
//inside heightfield
|
||||
|
||||
vec3 pos1 = (vec3(uvw_pos.x, y, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
|
||||
vec3 pos2 = (vec3(uvw_pos.x + DELTA, 1.0 - texture(height_field_texture, uvw_pos.xz + vec2(DELTA, 0)).r, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
|
||||
vec3 pos3 = (vec3(uvw_pos.x, 1.0 - texture(height_field_texture, uvw_pos.xz + vec2(0, DELTA)).r, uvw_pos.z + DELTA) * 2.0 - 1.0) * colliders[i].extents.xyz;
|
||||
vec3 pos2 = (vec3(uvw_pos.x + DELTA, texture(height_field_texture, uvw_pos.xz + vec2(DELTA, 0)).r, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
|
||||
vec3 pos3 = (vec3(uvw_pos.x, texture(height_field_texture, uvw_pos.xz + vec2(0, DELTA)).r, uvw_pos.z + DELTA) * 2.0 - 1.0) * colliders[i].extents.xyz;
|
||||
|
||||
normal = normalize(cross(pos1 - pos2, pos1 - pos3));
|
||||
float local_y = (vec3(local_pos / colliders[i].extents.xyz) * 0.5 + 0.5).y;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -59,7 +59,7 @@ layout(location = 10) in highp uvec4 in_bone_attrib;
|
|||
layout(location = 11) in mediump vec4 in_weight_attrib;
|
||||
#endif
|
||||
|
||||
uniform mediump sampler2D skeleton_texture; // texunit:0
|
||||
uniform highp sampler2D skeleton_texture; // texunit:0
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
|
|
|
|||
|
|
@ -2,17 +2,15 @@
|
|||
#[modes]
|
||||
|
||||
mode_background =
|
||||
mode_half_res = #define USE_HALF_RES_PASS
|
||||
mode_quarter_res = #define USE_QUARTER_RES_PASS
|
||||
mode_cubemap = #define USE_CUBEMAP_PASS
|
||||
mode_cubemap_half_res = #define USE_CUBEMAP_PASS \n#define USE_HALF_RES_PASS
|
||||
mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PASS
|
||||
|
||||
#[specializations]
|
||||
|
||||
USE_MULTIVIEW = false
|
||||
USE_INVERTED_Y = true
|
||||
APPLY_TONEMAPPING = true
|
||||
USE_QUARTER_RES_PASS = false
|
||||
USE_HALF_RES_PASS = false
|
||||
|
||||
#[vertex]
|
||||
|
||||
|
|
@ -108,11 +106,11 @@ uniform float sky_energy_multiplier;
|
|||
uniform float luminance_multiplier;
|
||||
|
||||
uniform float fog_aerial_perspective;
|
||||
uniform vec3 fog_light_color;
|
||||
uniform vec4 fog_light_color;
|
||||
uniform float fog_sun_scatter;
|
||||
uniform bool fog_enabled;
|
||||
uniform float fog_density;
|
||||
uniform float z_far;
|
||||
uniform float fog_sky_affect;
|
||||
uniform uint directional_light_count;
|
||||
|
||||
#ifdef USE_MULTIVIEW
|
||||
|
|
@ -135,6 +133,24 @@ vec3 interleaved_gradient_noise(vec2 pos) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_FOG)
|
||||
vec4 fog_process(vec3 view, vec3 sky_color) {
|
||||
vec3 fog_color = mix(fog_light_color.rgb, sky_color, fog_aerial_perspective);
|
||||
|
||||
if (fog_sun_scatter > 0.001) {
|
||||
vec4 sun_scatter = vec4(0.0);
|
||||
float sun_total = 0.0;
|
||||
for (uint i = 0u; i < directional_light_count; i++) {
|
||||
vec3 light_color = directional_lights.data[i].color_size.xyz * directional_lights.data[i].direction_energy.w;
|
||||
float light_amount = pow(max(dot(view, directional_lights.data[i].direction_energy.xyz), 0.0), 8.0);
|
||||
fog_color += light_color * light_amount * fog_sun_scatter;
|
||||
}
|
||||
}
|
||||
|
||||
return vec4(fog_color, 1.0);
|
||||
}
|
||||
#endif // !DISABLE_FOG
|
||||
|
||||
void main() {
|
||||
vec3 cube_normal;
|
||||
#ifdef USE_MULTIVIEW
|
||||
|
|
@ -194,15 +210,28 @@ void main() {
|
|||
#endif
|
||||
|
||||
{
|
||||
|
||||
#CODE : SKY
|
||||
|
||||
}
|
||||
|
||||
color *= sky_energy_multiplier;
|
||||
|
||||
// Convert to Linear for tonemapping so color matches scene shader better
|
||||
color = srgb_to_linear(color);
|
||||
|
||||
#if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS)
|
||||
|
||||
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
|
||||
if (fog_enabled) {
|
||||
vec4 fog = fog_process(cube_normal, color.rgb);
|
||||
color.rgb = mix(color.rgb, fog.rgb, fog.a * fog_sky_affect);
|
||||
}
|
||||
|
||||
if (custom_fog.a > 0.0) {
|
||||
color.rgb = mix(color.rgb, custom_fog.rgb, custom_fog.a);
|
||||
}
|
||||
|
||||
#endif // DISABLE_FOG
|
||||
|
||||
color *= exposure;
|
||||
#ifdef APPLY_TONEMAPPING
|
||||
color = apply_tonemapping(color, white);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
|
||||
// Compatibility renames. These are exposed with the "godot_" prefix
|
||||
// to work around two distinct Adreno bugs:
|
||||
// 1. Some Adreno devices expose ES310 functions in ES300 shaders.
|
||||
// Internally, we must use the "godot_" prefix, but user shaders
|
||||
// will be mapped automatically.
|
||||
// 2. Adreno 3XX devices have poor implementations of the other packing
|
||||
// functions, so we just use our own everywhere to keep it simple.
|
||||
// functions, so we just use our own there to keep it simple.
|
||||
|
||||
#ifdef USE_HALF2FLOAT
|
||||
// Floating point pack/unpack functions are part of the GLSL ES 300 specification used by web and mobile.
|
||||
// It appears to be safe to expose these on mobile, but when running through ANGLE this appears to break.
|
||||
uint float2half(uint f) {
|
||||
uint e = f & uint(0x7f800000);
|
||||
if (e <= uint(0x38000000)) {
|
||||
|
|
@ -52,6 +53,17 @@ vec2 godot_unpackSnorm2x16(uint p) {
|
|||
return clamp((v - 32767.0) * vec2(0.00003051851), vec2(-1.0), vec2(1.0));
|
||||
}
|
||||
|
||||
#define packHalf2x16 godot_packHalf2x16
|
||||
#define unpackHalf2x16 godot_unpackHalf2x16
|
||||
#define packUnorm2x16 godot_packUnorm2x16
|
||||
#define unpackUnorm2x16 godot_unpackUnorm2x16
|
||||
#define packSnorm2x16 godot_packSnorm2x16
|
||||
#define unpackSnorm2x16 godot_unpackSnorm2x16
|
||||
|
||||
#endif // USE_HALF2FLOAT
|
||||
|
||||
// Always expose these as they are ES310 functions and not available in ES300 or GLSL 330.
|
||||
|
||||
uint godot_packUnorm4x8(vec4 v) {
|
||||
uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0));
|
||||
return uv.x | (uv.y << uint(8)) | (uv.z << uint(16)) | (uv.w << uint(24));
|
||||
|
|
@ -75,9 +87,3 @@ vec4 godot_unpackSnorm4x8(uint p) {
|
|||
#define unpackUnorm4x8 godot_unpackUnorm4x8
|
||||
#define packSnorm4x8 godot_packSnorm4x8
|
||||
#define unpackSnorm4x8 godot_unpackSnorm4x8
|
||||
#define packHalf2x16 godot_packHalf2x16
|
||||
#define unpackHalf2x16 godot_unpackHalf2x16
|
||||
#define packUnorm2x16 godot_packUnorm2x16
|
||||
#define unpackUnorm2x16 godot_unpackUnorm2x16
|
||||
#define packSnorm2x16 godot_packSnorm2x16
|
||||
#define unpackSnorm2x16 godot_unpackSnorm2x16
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@ vec3 srgb_to_linear(vec3 color) {
|
|||
|
||||
#ifdef APPLY_TONEMAPPING
|
||||
|
||||
// Based on Reinhard's extended formula, see equation 4 in https://doi.org/cjbgrt
|
||||
vec3 tonemap_reinhard(vec3 color, float p_white) {
|
||||
float white_squared = p_white * p_white;
|
||||
vec3 white_squared_color = white_squared * color;
|
||||
// Equivalent to color * (1 + color / white_squared) / (1 + color)
|
||||
return (white_squared_color + color * color) / (white_squared_color + white_squared);
|
||||
}
|
||||
|
||||
vec3 tonemap_filmic(vec3 color, float p_white) {
|
||||
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
|
||||
// also useful to scale the input to the range that the tonemapper is designed for (some require very high input values)
|
||||
|
|
@ -76,16 +84,86 @@ vec3 tonemap_aces(vec3 color, float p_white) {
|
|||
return color_tonemapped / p_white_tonemapped;
|
||||
}
|
||||
|
||||
vec3 tonemap_reinhard(vec3 color, float p_white) {
|
||||
return (p_white * color + color) / (color * p_white + p_white);
|
||||
// Polynomial approximation of EaryChow's AgX sigmoid curve.
|
||||
// x must be within the range [0.0, 1.0]
|
||||
vec3 agx_contrast_approx(vec3 x) {
|
||||
// Generated with Excel trendline
|
||||
// Input data: Generated using python sigmoid with EaryChow's configuration and 57 steps
|
||||
// Additional padding values were added to give correct intersections at 0.0 and 1.0
|
||||
// 6th order, intercept of 0.0 to remove an operation and ensure intersection at 0.0
|
||||
vec3 x2 = x * x;
|
||||
vec3 x4 = x2 * x2;
|
||||
return 0.021 * x + 4.0111 * x2 - 25.682 * x2 * x + 70.359 * x4 - 74.778 * x4 * x + 27.069 * x4 * x2;
|
||||
}
|
||||
|
||||
// This is an approximation and simplification of EaryChow's AgX implementation that is used by Blender.
|
||||
// This code is based off of the script that generates the AgX_Base_sRGB.cube LUT that Blender uses.
|
||||
// Source: https://github.com/EaryChow/AgX_LUT_Gen/blob/main/AgXBasesRGB.py
|
||||
vec3 tonemap_agx(vec3 color) {
|
||||
// Combined linear sRGB to linear Rec 2020 and Blender AgX inset matrices:
|
||||
const mat3 srgb_to_rec2020_agx_inset_matrix = mat3(
|
||||
0.54490813676363087053, 0.14044005884001287035, 0.088827411851915368603,
|
||||
0.37377945959812267119, 0.75410959864013760045, 0.17887712465043811023,
|
||||
0.081384976686407536266, 0.10543358536857773485, 0.73224999956948382528);
|
||||
|
||||
// Combined inverse AgX outset matrix and linear Rec 2020 to linear sRGB matrices.
|
||||
const mat3 agx_outset_rec2020_to_srgb_matrix = mat3(
|
||||
1.9645509602733325934, -0.29932243390911083839, -0.16436833806080403409,
|
||||
-0.85585845117807513559, 1.3264510741502356555, -0.23822464068860595117,
|
||||
-0.10886710826831608324, -0.027084020983874825605, 1.402665347143271889);
|
||||
|
||||
// LOG2_MIN = -10.0
|
||||
// LOG2_MAX = +6.5
|
||||
// MIDDLE_GRAY = 0.18
|
||||
const float min_ev = -12.4739311883324; // log2(pow(2, LOG2_MIN) * MIDDLE_GRAY)
|
||||
const float max_ev = 4.02606881166759; // log2(pow(2, LOG2_MAX) * MIDDLE_GRAY)
|
||||
|
||||
// Large negative values in one channel and large positive values in other
|
||||
// channels can result in a colour that appears darker and more saturated than
|
||||
// desired after passing it through the inset matrix. For this reason, it is
|
||||
// best to prevent negative input values.
|
||||
// This is done before the Rec. 2020 transform to allow the Rec. 2020
|
||||
// transform to be combined with the AgX inset matrix. This results in a loss
|
||||
// of color information that could be correctly interpreted within the
|
||||
// Rec. 2020 color space as positive RGB values, but it is less common for Godot
|
||||
// to provide this function with negative sRGB values and therefore not worth
|
||||
// the performance cost of an additional matrix multiplication.
|
||||
// A value of 2e-10 intentionally introduces insignificant error to prevent
|
||||
// log2(0.0) after the inset matrix is applied; color will be >= 1e-10 after
|
||||
// the matrix transform.
|
||||
color = max(color, 2e-10);
|
||||
|
||||
// Do AGX in rec2020 to match Blender and then apply inset matrix.
|
||||
color = srgb_to_rec2020_agx_inset_matrix * color;
|
||||
|
||||
// Log2 space encoding.
|
||||
// Must be clamped because agx_contrast_approx may not work
|
||||
// well with values outside of the range [0.0, 1.0]
|
||||
color = clamp(log2(color), min_ev, max_ev);
|
||||
color = (color - min_ev) / (max_ev - min_ev);
|
||||
|
||||
// Apply sigmoid function approximation.
|
||||
color = agx_contrast_approx(color);
|
||||
|
||||
// Convert back to linear before applying outset matrix.
|
||||
color = pow(color, vec3(2.4));
|
||||
|
||||
// Apply outset to make the result more chroma-laden and then go back to linear sRGB.
|
||||
color = agx_outset_rec2020_to_srgb_matrix * color;
|
||||
|
||||
// Blender's lusRGB.compensate_low_side is too complex for this shader, so
|
||||
// simply return the color, even if it has negative components. These negative
|
||||
// components may be useful for subsequent color adjustments.
|
||||
return color;
|
||||
}
|
||||
|
||||
#define TONEMAPPER_LINEAR 0
|
||||
#define TONEMAPPER_REINHARD 1
|
||||
#define TONEMAPPER_FILMIC 2
|
||||
#define TONEMAPPER_ACES 3
|
||||
#define TONEMAPPER_AGX 4
|
||||
|
||||
vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR, always outputs clamped [0;1] color
|
||||
vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR
|
||||
// Ensure color values passed to tonemappers are positive.
|
||||
// They can be negative in the case of negative lights, which leads to undesired behavior.
|
||||
if (tonemapper == TONEMAPPER_LINEAR) {
|
||||
|
|
@ -94,8 +172,10 @@ vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR, always
|
|||
return tonemap_reinhard(max(vec3(0.0f), color), p_white);
|
||||
} else if (tonemapper == TONEMAPPER_FILMIC) {
|
||||
return tonemap_filmic(max(vec3(0.0f), color), p_white);
|
||||
} else { // TONEMAPPER_ACES
|
||||
} else if (tonemapper == TONEMAPPER_ACES) {
|
||||
return tonemap_aces(max(vec3(0.0f), color), p_white);
|
||||
} else { // TONEMAPPER_AGX
|
||||
return tonemap_agx(color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "../rasterizer_gles3.h"
|
||||
#include "texture_storage.h"
|
||||
|
||||
#ifdef WEB_ENABLED
|
||||
#include <emscripten/html5_webgl.h>
|
||||
|
|
@ -80,16 +79,19 @@ Config::Config() {
|
|||
|
||||
bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc");
|
||||
astc_supported = extensions.has("GL_KHR_texture_compression_astc") || extensions.has("GL_OES_texture_compression_astc") || extensions.has("GL_KHR_texture_compression_astc_ldr") || extensions.has("GL_KHR_texture_compression_astc_hdr");
|
||||
astc_hdr_supported = extensions.has("GL_KHR_texture_compression_astc_ldr");
|
||||
astc_hdr_supported = extensions.has("GL_KHR_texture_compression_astc_hdr");
|
||||
astc_layered_supported = extensions.has("GL_KHR_texture_compression_astc_sliced_3d");
|
||||
|
||||
if (RasterizerGLES3::is_gles_over_gl()) {
|
||||
float_texture_supported = true;
|
||||
float_texture_linear_supported = true;
|
||||
etc2_supported = false;
|
||||
s3tc_supported = true;
|
||||
rgtc_supported = true; //RGTC - core since OpenGL version 3.0
|
||||
srgb_framebuffer_supported = true;
|
||||
} else {
|
||||
float_texture_supported = extensions.has("GL_EXT_color_buffer_float");
|
||||
float_texture_linear_supported = extensions.has("GL_OES_texture_float_linear");
|
||||
etc2_supported = true;
|
||||
#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED)
|
||||
// Some Android devices report support for S3TC but we don't expect that and don't export the textures.
|
||||
|
|
@ -100,6 +102,7 @@ Config::Config() {
|
|||
s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc");
|
||||
#endif
|
||||
rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc");
|
||||
srgb_framebuffer_supported = extensions.has("GL_EXT_sRGB_write_control");
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
|
||||
|
|
@ -107,6 +110,11 @@ Config::Config() {
|
|||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
|
||||
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
|
||||
glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
|
||||
GLint max_vertex_output;
|
||||
glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &max_vertex_output);
|
||||
GLint max_fragment_input;
|
||||
glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &max_fragment_input);
|
||||
max_shader_varyings = (uint32_t)MIN(max_vertex_output, max_fragment_input) / 4;
|
||||
|
||||
// sanity clamp buffer size to 16K..1MB
|
||||
max_uniform_buffer_size = CLAMP(max_uniform_buffer_size, 16384, 1048576);
|
||||
|
|
@ -121,7 +129,7 @@ Config::Config() {
|
|||
#ifdef WEB_ENABLED
|
||||
msaa_supported = (msaa_max_samples > 0);
|
||||
#else
|
||||
msaa_supported = extensions.has("GL_EXT_framebuffer_multisample");
|
||||
msaa_supported = true;
|
||||
#endif
|
||||
#ifndef IOS_ENABLED
|
||||
#ifdef WEB_ENABLED
|
||||
|
|
@ -138,6 +146,7 @@ Config::Config() {
|
|||
// These are GLES only
|
||||
rt_msaa_supported = extensions.has("GL_EXT_multisampled_render_to_texture");
|
||||
rt_msaa_multiview_supported = extensions.has("GL_OVR_multiview_multisampled_render_to_texture");
|
||||
external_texture_supported = extensions.has("GL_OES_EGL_image_external_essl3");
|
||||
|
||||
if (multiview_supported) {
|
||||
eglFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)eglGetProcAddress("glFramebufferTextureMultiviewOVR");
|
||||
|
|
@ -166,9 +175,16 @@ Config::Config() {
|
|||
rt_msaa_multiview_supported = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (external_texture_supported) {
|
||||
eglEGLImageTargetTexture2DOES = (PFNEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
||||
if (eglEGLImageTargetTexture2DOES == nullptr) {
|
||||
external_texture_supported = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
|
||||
force_vertex_shading = GLOBAL_GET("rendering/shading/overrides/force_vertex_shading");
|
||||
use_nearest_mip_filter = GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter");
|
||||
|
||||
use_depth_prepass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));
|
||||
|
|
@ -218,7 +234,16 @@ Config::Config() {
|
|||
//https://github.com/godotengine/godot/issues/92662#issuecomment-2161199477
|
||||
//disable_particles_workaround = false;
|
||||
}
|
||||
} else if (rendering_device_name == "PowerVR Rogue GE8320") {
|
||||
disable_transform_feedback_shader_cache = true;
|
||||
}
|
||||
|
||||
if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3_angle") {
|
||||
polyfill_half2float = false;
|
||||
}
|
||||
#ifdef WEB_ENABLED
|
||||
polyfill_half2float = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
Config::~Config() {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
#include "core/config/project_settings.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/templates/hash_set.h"
|
||||
#include "core/templates/vector.h"
|
||||
|
||||
#include "platform_gl.h"
|
||||
|
||||
|
|
@ -45,6 +44,7 @@ typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint,
|
|||
typedef void (*PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean);
|
||||
typedef void (*PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
|
||||
typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei);
|
||||
typedef void (*PFNEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum, void *);
|
||||
#endif
|
||||
|
||||
namespace GLES3 {
|
||||
|
|
@ -62,6 +62,7 @@ public:
|
|||
GLint max_texture_size = 0;
|
||||
GLint max_viewport_size[2] = { 0, 0 };
|
||||
GLint64 max_uniform_buffer_size = 0;
|
||||
uint32_t max_shader_varyings = 0;
|
||||
|
||||
int64_t max_renderable_elements = 0;
|
||||
int64_t max_renderable_lights = 0;
|
||||
|
|
@ -72,6 +73,7 @@ public:
|
|||
HashSet<String> extensions;
|
||||
|
||||
bool float_texture_supported = false;
|
||||
bool float_texture_linear_supported = false;
|
||||
bool s3tc_supported = false;
|
||||
bool rgtc_supported = false;
|
||||
bool bptc_supported = false;
|
||||
|
|
@ -79,6 +81,7 @@ public:
|
|||
bool astc_supported = false;
|
||||
bool astc_hdr_supported = false;
|
||||
bool astc_layered_supported = false;
|
||||
bool srgb_framebuffer_supported = false;
|
||||
|
||||
bool force_vertex_shading = false;
|
||||
|
||||
|
|
@ -91,19 +94,27 @@ public:
|
|||
bool rt_msaa_supported = false;
|
||||
bool rt_msaa_multiview_supported = false;
|
||||
bool multiview_supported = false;
|
||||
bool external_texture_supported = false;
|
||||
|
||||
// Adreno 3XX compatibility
|
||||
bool disable_particles_workaround = false; // set to 'true' to disable 'GPUParticles'
|
||||
// Adreno 3XX compatibility.
|
||||
bool disable_particles_workaround = false; // Set to 'true' to disable 'GPUParticles'.
|
||||
bool flip_xy_workaround = false;
|
||||
|
||||
// PowerVR GE 8320 workaround.
|
||||
bool disable_transform_feedback_shader_cache = false;
|
||||
|
||||
// ANGLE shader workaround.
|
||||
bool polyfill_half2float = true;
|
||||
|
||||
#ifdef ANDROID_ENABLED
|
||||
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr;
|
||||
PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr;
|
||||
PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC eglFramebufferTexture2DMultisampleEXT = nullptr;
|
||||
PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC eglFramebufferTextureMultisampleMultiviewOVR = nullptr;
|
||||
PFNEGLIMAGETARGETTEXTURE2DOESPROC eglEGLImageTargetTexture2DOES = nullptr;
|
||||
#endif
|
||||
|
||||
static Config *get_singleton() { return singleton; };
|
||||
static Config *get_singleton() { return singleton; }
|
||||
|
||||
Config();
|
||||
~Config();
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#include "light_storage.h"
|
||||
#include "../rasterizer_gles3.h"
|
||||
#include "../rasterizer_scene_gles3.h"
|
||||
#include "config.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "texture_storage.h"
|
||||
|
||||
|
|
@ -213,6 +212,23 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
|
|||
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
|
||||
}
|
||||
|
||||
void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {
|
||||
Light *light = light_owner.get_or_null(p_light);
|
||||
ERR_FAIL_NULL(light);
|
||||
|
||||
light->shadow_caster_mask = p_caster_mask;
|
||||
|
||||
light->version++;
|
||||
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
|
||||
}
|
||||
|
||||
uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {
|
||||
Light *light = light_owner.get_or_null(p_light);
|
||||
ERR_FAIL_NULL_V(light, 0);
|
||||
|
||||
return light->shadow_caster_mask;
|
||||
}
|
||||
|
||||
void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
|
||||
Light *light = light_owner.get_or_null(p_light);
|
||||
ERR_FAIL_NULL(light);
|
||||
|
|
@ -454,6 +470,13 @@ void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity
|
|||
reflection_probe->intensity = p_intensity;
|
||||
}
|
||||
|
||||
void LightStorage::reflection_probe_set_blend_distance(RID p_probe, float p_blend_distance) {
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
|
||||
ERR_FAIL_NULL(reflection_probe);
|
||||
|
||||
reflection_probe->blend_distance = p_blend_distance;
|
||||
}
|
||||
|
||||
void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
|
||||
ERR_FAIL_NULL(reflection_probe);
|
||||
|
|
@ -1046,6 +1069,9 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use
|
|||
lightmap->light_texture = p_light;
|
||||
lightmap->uses_spherical_harmonics = p_uses_spherical_haromics;
|
||||
|
||||
Vector3i light_texture_size = GLES3::TextureStorage::get_singleton()->texture_get_size(lightmap->light_texture);
|
||||
lightmap->light_texture_size = Vector2i(light_texture_size.x, light_texture_size.y);
|
||||
|
||||
GLuint tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lightmap->light_texture);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
|
@ -1184,6 +1210,33 @@ float LightStorage::lightmap_get_probe_capture_update_speed() const {
|
|||
return lightmap_probe_capture_update_speed;
|
||||
}
|
||||
|
||||
void LightStorage::lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) {
|
||||
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
|
||||
ERR_FAIL_NULL(lightmap);
|
||||
lightmap->shadow_texture = p_shadow;
|
||||
|
||||
GLuint tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lightmap->shadow_texture);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||
}
|
||||
|
||||
RS::ShadowmaskMode LightStorage::lightmap_get_shadowmask_mode(RID p_lightmap) {
|
||||
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
|
||||
ERR_FAIL_NULL_V(lightmap, RS::SHADOWMASK_MODE_NONE);
|
||||
|
||||
return lightmap->shadowmask_mode;
|
||||
}
|
||||
|
||||
void LightStorage::lightmap_set_shadowmask_mode(RID p_lightmap, RS::ShadowmaskMode p_mode) {
|
||||
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
|
||||
ERR_FAIL_NULL(lightmap);
|
||||
lightmap->shadowmask_mode = p_mode;
|
||||
}
|
||||
|
||||
/* LIGHTMAP INSTANCE */
|
||||
|
||||
RID LightStorage::lightmap_instance_create(RID p_lightmap) {
|
||||
|
|
@ -1385,7 +1438,7 @@ bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_instance,
|
|||
old_shadow = old_key & SHADOW_INDEX_MASK;
|
||||
|
||||
// Only re-allocate if a better option is available, and enough time has passed.
|
||||
should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec);
|
||||
should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (tick - shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick > shadow_atlas_realloc_tolerance_msec);
|
||||
should_redraw = shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].version != p_light_version;
|
||||
|
||||
if (!should_realloc) {
|
||||
|
|
@ -1518,6 +1571,11 @@ bool LightStorage::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_i
|
|||
uint64_t min_pass = 0; // Pass of the existing one, try to use the least recently used one (LRU fashion).
|
||||
|
||||
for (int j = 0; j < sc; j++) {
|
||||
if (sarr[j].owner_is_omni != is_omni) {
|
||||
// Existing light instance type doesn't match new light instance type skip.
|
||||
continue;
|
||||
}
|
||||
|
||||
LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);
|
||||
if (!sli) {
|
||||
// Found a released light instance.
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@
|
|||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/templates/self_list.h"
|
||||
#include "drivers/gles3/storage/texture_storage.h"
|
||||
#include "servers/rendering/renderer_compositor.h"
|
||||
#include "servers/rendering/storage/light_storage.h"
|
||||
#include "servers/rendering/storage/utilities.h"
|
||||
|
||||
|
|
@ -59,6 +57,7 @@ struct Light {
|
|||
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
|
||||
uint32_t max_sdfgi_cascade = 2;
|
||||
uint32_t cull_mask = 0xFFFFFFFF;
|
||||
uint32_t shadow_caster_mask = 0xFFFFFFFF;
|
||||
bool distance_fade = false;
|
||||
real_t distance_fade_begin = 40.0;
|
||||
real_t distance_fade_shadow = 50.0;
|
||||
|
|
@ -117,6 +116,7 @@ struct ReflectionProbe {
|
|||
RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
|
||||
int resolution = 256;
|
||||
float intensity = 1.0;
|
||||
float blend_distance = 1.0;
|
||||
RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
|
||||
Color ambient_color;
|
||||
float ambient_color_energy = 1.0;
|
||||
|
|
@ -176,11 +176,14 @@ struct ReflectionProbeInstance {
|
|||
|
||||
struct Lightmap {
|
||||
RID light_texture;
|
||||
RID shadow_texture;
|
||||
bool uses_spherical_harmonics = false;
|
||||
bool interior = false;
|
||||
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
|
||||
float baked_exposure = 1.0;
|
||||
Vector2i light_texture_size;
|
||||
int32_t array_index = -1; //unassigned
|
||||
RS::ShadowmaskMode shadowmask_mode = RS::SHADOWMASK_MODE_NONE;
|
||||
PackedVector3Array points;
|
||||
PackedColorArray point_sh;
|
||||
PackedInt32Array tetrahedra;
|
||||
|
|
@ -202,7 +205,7 @@ struct LightmapInstance {
|
|||
|
||||
class LightStorage : public RendererLightStorage {
|
||||
public:
|
||||
enum ShadowAtlastQuadrant {
|
||||
enum ShadowAtlastQuadrant : uint32_t {
|
||||
QUADRANT_SHIFT = 27,
|
||||
OMNI_LIGHT_FLAG = 1 << 26,
|
||||
SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1,
|
||||
|
|
@ -229,8 +232,6 @@ private:
|
|||
mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
|
||||
|
||||
/* LIGHTMAP */
|
||||
|
||||
Vector<RID> lightmap_textures;
|
||||
float lightmap_probe_capture_update_speed = 4;
|
||||
|
||||
mutable RID_Owner<Lightmap, true> lightmap_owner;
|
||||
|
|
@ -304,8 +305,8 @@ public:
|
|||
|
||||
/* Light API */
|
||||
|
||||
Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); };
|
||||
bool owns_light(RID p_rid) { return light_owner.owns(p_rid); };
|
||||
Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); }
|
||||
bool owns_light(RID p_rid) { return light_owner.owns(p_rid); }
|
||||
|
||||
void _light_initialize(RID p_rid, RS::LightType p_type);
|
||||
|
||||
|
|
@ -326,6 +327,8 @@ public:
|
|||
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
|
||||
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
|
||||
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
|
||||
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override;
|
||||
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override;
|
||||
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
|
||||
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
|
||||
|
||||
|
|
@ -430,8 +433,8 @@ public:
|
|||
|
||||
/* LIGHT INSTANCE API */
|
||||
|
||||
LightInstance *get_light_instance(RID p_rid) { return light_instance_owner.get_or_null(p_rid); };
|
||||
bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); };
|
||||
LightInstance *get_light_instance(RID p_rid) { return light_instance_owner.get_or_null(p_rid); }
|
||||
bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); }
|
||||
|
||||
virtual RID light_instance_create(RID p_light) override;
|
||||
virtual void light_instance_free(RID p_light_instance) override;
|
||||
|
|
@ -629,8 +632,8 @@ public:
|
|||
|
||||
/* PROBE API */
|
||||
|
||||
ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); };
|
||||
bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); };
|
||||
ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); }
|
||||
bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }
|
||||
|
||||
virtual RID reflection_probe_allocate() override;
|
||||
virtual void reflection_probe_initialize(RID p_rid) override;
|
||||
|
|
@ -638,6 +641,7 @@ public:
|
|||
|
||||
virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
|
||||
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
|
||||
virtual void reflection_probe_set_blend_distance(RID p_probe, float p_blend_distance) override;
|
||||
virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
|
||||
virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
|
||||
virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
|
||||
|
|
@ -711,8 +715,8 @@ public:
|
|||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
|
||||
Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
|
||||
bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
|
||||
Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); }
|
||||
bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }
|
||||
|
||||
virtual RID lightmap_allocate() override;
|
||||
virtual void lightmap_initialize(RID p_rid) override;
|
||||
|
|
@ -733,23 +737,27 @@ public:
|
|||
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
|
||||
virtual float lightmap_get_probe_capture_update_speed() const override;
|
||||
|
||||
virtual void lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) override;
|
||||
virtual RS::ShadowmaskMode lightmap_get_shadowmask_mode(RID p_lightmap) override;
|
||||
virtual void lightmap_set_shadowmask_mode(RID p_lightmap, RS::ShadowmaskMode p_mode) override;
|
||||
|
||||
/* LIGHTMAP INSTANCE */
|
||||
|
||||
LightmapInstance *get_lightmap_instance(RID p_rid) { return lightmap_instance_owner.get_or_null(p_rid); };
|
||||
bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); };
|
||||
LightmapInstance *get_lightmap_instance(RID p_rid) { return lightmap_instance_owner.get_or_null(p_rid); }
|
||||
bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); }
|
||||
|
||||
virtual RID lightmap_instance_create(RID p_lightmap) override;
|
||||
virtual void lightmap_instance_free(RID p_lightmap) override;
|
||||
virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
|
||||
|
||||
/* SHADOW ATLAS API */
|
||||
bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); };
|
||||
bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); }
|
||||
|
||||
virtual RID shadow_atlas_create() override;
|
||||
virtual void shadow_atlas_free(RID p_atlas) override;
|
||||
virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override;
|
||||
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
|
||||
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override;
|
||||
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override;
|
||||
|
||||
_FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_instance) {
|
||||
ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
|
||||
|
|
@ -875,7 +883,7 @@ public:
|
|||
virtual void shadow_atlas_update(RID p_atlas) override;
|
||||
|
||||
virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override;
|
||||
virtual int get_directional_light_shadow_size(RID p_light_intance) override;
|
||||
virtual int get_directional_light_shadow_size(RID p_light_instance) override;
|
||||
virtual void set_directional_shadow_count(int p_count) override;
|
||||
|
||||
Rect2i get_directional_shadow_rect();
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_
|
|||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
|
||||
_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::Scalar> &value, uint8_t *data) {
|
||||
switch (type) {
|
||||
case ShaderLanguage::TYPE_BOOL: {
|
||||
uint32_t *gui = (uint32_t *)data;
|
||||
|
|
@ -572,7 +572,10 @@ void ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_t
|
|||
Variant ShaderData::get_default_parameter(const StringName &p_parameter) const {
|
||||
if (uniforms.has(p_parameter)) {
|
||||
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
|
||||
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
|
||||
Vector<ShaderLanguage::Scalar> default_value = uniform.default_value;
|
||||
if (default_value.is_empty()) {
|
||||
return ShaderLanguage::get_default_datatype_value(uniform.type, uniform.array_size, uniform.hint);
|
||||
}
|
||||
return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
|
||||
}
|
||||
return Variant();
|
||||
|
|
@ -586,11 +589,7 @@ void ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const
|
|||
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
|
||||
continue;
|
||||
}
|
||||
if (E.value.texture_order >= 0) {
|
||||
filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.texture_order + 100000));
|
||||
} else {
|
||||
filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.order));
|
||||
}
|
||||
filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.prop_order));
|
||||
}
|
||||
int uniform_count = filtered_uniforms.size();
|
||||
sorter.sort(filtered_uniforms.ptr(), uniform_count);
|
||||
|
|
@ -640,7 +639,7 @@ bool ShaderData::is_parameter_texture(const StringName &p_param) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
return uniforms[p_param].texture_order >= 0;
|
||||
return uniforms[p_param].is_texture();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -679,6 +678,7 @@ static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = {
|
|||
GL_TEXTURE_3D, // TYPE_USAMPLER3D,
|
||||
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE,
|
||||
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY,
|
||||
_GL_TEXTURE_EXTERNAL_OES, // TYPE_SAMPLEREXT
|
||||
GL_TEXTURE_2D, // TYPE_STRUCT
|
||||
};
|
||||
|
||||
|
|
@ -719,7 +719,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
|
|||
bool uses_global_buffer = false;
|
||||
|
||||
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
|
||||
if (E.value.order < 0) {
|
||||
if (E.value.is_texture()) {
|
||||
continue; // texture, does not go here
|
||||
}
|
||||
|
||||
|
|
@ -948,7 +948,10 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
|
|||
}
|
||||
} break;
|
||||
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
|
||||
ERR_PRINT_ONCE("Type: SamplerCubeArray not supported in GL Compatibility rendering backend, please use another type.");
|
||||
ERR_PRINT_ONCE("Type: SamplerCubeArray is not supported in the Compatibility renderer, please use another type.");
|
||||
} break;
|
||||
case ShaderLanguage::TYPE_SAMPLEREXT: {
|
||||
gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_EXT);
|
||||
} break;
|
||||
|
||||
case ShaderLanguage::TYPE_ISAMPLER3D:
|
||||
|
|
@ -1193,6 +1196,7 @@ MaterialStorage::MaterialStorage() {
|
|||
actions.render_mode_defines["world_vertex_coords"] = "#define USE_WORLD_VERTEX_COORDS\n";
|
||||
|
||||
actions.global_buffer_array_variable = "global_shader_uniforms";
|
||||
actions.instance_uniform_index_variable = "read_draw_data_instance_offset";
|
||||
|
||||
shaders.compiler_canvas.initialize(actions);
|
||||
}
|
||||
|
|
@ -1237,6 +1241,8 @@ MaterialStorage::MaterialStorage() {
|
|||
actions.renames["PI"] = _MKSTR(Math_PI);
|
||||
actions.renames["TAU"] = _MKSTR(Math_TAU);
|
||||
actions.renames["E"] = _MKSTR(Math_E);
|
||||
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
|
||||
actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
|
||||
actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size";
|
||||
|
||||
actions.renames["FRAGCOORD"] = "gl_FragCoord";
|
||||
|
|
@ -1276,7 +1282,6 @@ MaterialStorage::MaterialStorage() {
|
|||
actions.renames["CUSTOM1"] = "custom1_attrib";
|
||||
actions.renames["CUSTOM2"] = "custom2_attrib";
|
||||
actions.renames["CUSTOM3"] = "custom3_attrib";
|
||||
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
|
||||
actions.renames["LIGHT_VERTEX"] = "light_vertex";
|
||||
|
||||
actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
|
||||
|
|
@ -1367,6 +1372,10 @@ MaterialStorage::MaterialStorage() {
|
|||
actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
|
||||
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
|
||||
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
|
||||
if (!GLES3::Config::get_singleton()->force_vertex_shading) {
|
||||
// If forcing vertex shading, this will be defined already.
|
||||
actions.render_mode_defines["vertex_lighting"] = "#define USE_VERTEX_LIGHTING\n";
|
||||
}
|
||||
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
|
||||
|
||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||
|
|
@ -1374,6 +1383,7 @@ MaterialStorage::MaterialStorage() {
|
|||
|
||||
actions.check_multiview_samplers = RasterizerGLES3::get_singleton()->is_xr_enabled();
|
||||
actions.global_buffer_array_variable = "global_shader_uniforms";
|
||||
actions.instance_uniform_index_variable = "instance_offset";
|
||||
|
||||
shaders.compiler_scene.initialize(actions);
|
||||
}
|
||||
|
|
@ -1385,7 +1395,7 @@ MaterialStorage::MaterialStorage() {
|
|||
|
||||
actions.renames["COLOR"] = "out_color";
|
||||
actions.renames["VELOCITY"] = "out_velocity_flags.xyz";
|
||||
//actions.renames["MASS"] = "mass"; ?
|
||||
actions.renames["MASS"] = "mass";
|
||||
actions.renames["ACTIVE"] = "particle_active";
|
||||
actions.renames["RESTART"] = "restart";
|
||||
actions.renames["CUSTOM"] = "out_custom";
|
||||
|
|
@ -1952,6 +1962,7 @@ void MaterialStorage::global_shader_parameters_load_settings(bool p_load_texture
|
|||
"sampler2DArray",
|
||||
"sampler3D",
|
||||
"samplerCube",
|
||||
"samplerExternalOES"
|
||||
};
|
||||
|
||||
RS::GlobalShaderParameterType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
|
||||
|
|
@ -2498,6 +2509,19 @@ bool MaterialStorage::material_casts_shadows(RID p_material) {
|
|||
return true; //by default everything casts shadows
|
||||
}
|
||||
|
||||
RS::CullMode MaterialStorage::material_get_cull_mode(RID p_material) const {
|
||||
const GLES3::Material *material = material_owner.get_or_null(p_material);
|
||||
ERR_FAIL_NULL_V(material, RS::CULL_MODE_DISABLED);
|
||||
ERR_FAIL_NULL_V(material->shader, RS::CULL_MODE_DISABLED);
|
||||
if (material->shader->data) {
|
||||
SceneShaderData *data = dynamic_cast<SceneShaderData *>(material->shader->data);
|
||||
if (data) {
|
||||
return (RS::CullMode)data->cull_mode;
|
||||
}
|
||||
}
|
||||
return RS::CULL_MODE_DISABLED;
|
||||
}
|
||||
|
||||
void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
|
||||
GLES3::Material *material = material_owner.get_or_null(p_material);
|
||||
ERR_FAIL_NULL(material);
|
||||
|
|
@ -2664,7 +2688,11 @@ static void bind_uniforms_generic(const Vector<RID> &p_textures, const Vector<Sh
|
|||
const ShaderCompiler::GeneratedCode::Texture &texture_uniform = texture_uniforms[texture_uniform_index];
|
||||
if (texture) {
|
||||
glActiveTexture(GL_TEXTURE0 + texture_offset + ti);
|
||||
glBindTexture(target_from_type[texture_uniform.type], texture->tex_id);
|
||||
GLenum target = target_from_type[texture_uniform.type];
|
||||
if (target == _GL_TEXTURE_EXTERNAL_OES && !GLES3::Config::get_singleton()->external_texture_supported) {
|
||||
target = GL_TEXTURE_2D;
|
||||
}
|
||||
glBindTexture(target, texture->tex_id);
|
||||
if (texture->render_target) {
|
||||
texture->render_target->used_in_frame = true;
|
||||
}
|
||||
|
|
@ -2896,7 +2924,7 @@ void SceneShaderData::set_code(const String &p_code) {
|
|||
int blend_modei = BLEND_MODE_MIX;
|
||||
int depth_testi = DEPTH_TEST_ENABLED;
|
||||
int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF;
|
||||
int cull_modei = CULL_BACK;
|
||||
int cull_modei = RS::CULL_MODE_BACK;
|
||||
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
||||
|
||||
ShaderCompiler::IdentifierActions actions;
|
||||
|
|
@ -2919,9 +2947,9 @@ void SceneShaderData::set_code(const String &p_code) {
|
|||
|
||||
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
|
||||
|
||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
|
||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
|
||||
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
|
||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_DISABLED);
|
||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_FRONT);
|
||||
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_BACK);
|
||||
|
||||
actions.render_mode_flags["unshaded"] = &unshaded;
|
||||
actions.render_mode_flags["wireframe"] = &wireframe;
|
||||
|
|
@ -2979,7 +3007,7 @@ void SceneShaderData::set_code(const String &p_code) {
|
|||
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
|
||||
depth_draw = DepthDraw(depth_drawi);
|
||||
depth_test = DepthTest(depth_testi);
|
||||
cull_mode = Cull(cull_modei);
|
||||
cull_mode = RS::CullMode(cull_modei);
|
||||
|
||||
vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL; // We can always read vertices and normals.
|
||||
vertex_input_mask |= uses_tangent << RS::ARRAY_TANGENT;
|
||||
|
|
@ -3002,19 +3030,19 @@ void SceneShaderData::set_code(const String &p_code) {
|
|||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (uses_particle_trails) {
|
||||
WARN_PRINT_ONCE_ED("Particle trails are only available when using the Forward+ or Mobile rendering backends.");
|
||||
WARN_PRINT_ONCE_ED("Particle trails are only available when using the Forward+ or Mobile renderers.");
|
||||
}
|
||||
|
||||
if (uses_sss) {
|
||||
WARN_PRINT_ONCE_ED("Sub-surface scattering is only available when using the Forward+ rendering backend.");
|
||||
WARN_PRINT_ONCE_ED("Subsurface scattering is only available when using the Forward+ renderer.");
|
||||
}
|
||||
|
||||
if (uses_transmittance) {
|
||||
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ rendering backend.");
|
||||
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ renderer.");
|
||||
}
|
||||
|
||||
if (uses_normal_texture) {
|
||||
WARN_PRINT_ONCE_ED("Reading from the normal-roughness texture is only available when using the Forward+ or Mobile rendering backends.");
|
||||
WARN_PRINT_ONCE_ED("Reading from the normal-roughness texture is only available when using the Forward+ or Mobile renderers.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -33,10 +33,8 @@
|
|||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/templates/self_list.h"
|
||||
#include "servers/rendering/renderer_compositor.h"
|
||||
#include "servers/rendering/shader_compiler.h"
|
||||
#include "servers/rendering/shader_language.h"
|
||||
#include "servers/rendering/storage/material_storage.h"
|
||||
|
|
@ -263,12 +261,6 @@ struct SceneShaderData : public ShaderData {
|
|||
DEPTH_TEST_ENABLED
|
||||
};
|
||||
|
||||
enum Cull {
|
||||
CULL_DISABLED,
|
||||
CULL_FRONT,
|
||||
CULL_BACK
|
||||
};
|
||||
|
||||
enum AlphaAntiAliasing {
|
||||
ALPHA_ANTIALIASING_OFF,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
|
||||
|
|
@ -292,7 +284,7 @@ struct SceneShaderData : public ShaderData {
|
|||
AlphaAntiAliasing alpha_antialiasing_mode;
|
||||
DepthDraw depth_draw;
|
||||
DepthTest depth_test;
|
||||
Cull cull_mode;
|
||||
RS::CullMode cull_mode;
|
||||
|
||||
bool uses_point_size;
|
||||
bool uses_alpha;
|
||||
|
|
@ -576,8 +568,8 @@ public:
|
|||
|
||||
/* SHADER API */
|
||||
|
||||
Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
|
||||
bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
|
||||
Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }
|
||||
bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }
|
||||
|
||||
void _shader_make_dirty(Shader *p_shader);
|
||||
|
||||
|
|
@ -598,8 +590,8 @@ public:
|
|||
|
||||
/* MATERIAL API */
|
||||
|
||||
Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
|
||||
bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
|
||||
Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }
|
||||
bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }
|
||||
|
||||
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
|
||||
void _update_queued_materials();
|
||||
|
|
@ -618,6 +610,7 @@ public:
|
|||
|
||||
virtual bool material_is_animated(RID p_material) override;
|
||||
virtual bool material_casts_shadows(RID p_material) override;
|
||||
virtual RS::CullMode material_get_cull_mode(RID p_material) const override;
|
||||
|
||||
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include "mesh_storage.h"
|
||||
#include "config.h"
|
||||
#include "material_storage.h"
|
||||
#include "texture_storage.h"
|
||||
#include "utilities.h"
|
||||
|
||||
|
|
@ -301,7 +300,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
Vector<uint8_t> ir = new_surface.index_data;
|
||||
wr = wf_indices.ptrw();
|
||||
|
||||
if (new_surface.vertex_count < (1 << 16)) {
|
||||
if (new_surface.vertex_count <= 65536) {
|
||||
// Read 16 bit indices.
|
||||
const uint16_t *src_idx = (const uint16_t *)ir.ptr();
|
||||
for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) {
|
||||
|
|
@ -448,6 +447,72 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|||
mesh->material_cache.clear();
|
||||
}
|
||||
|
||||
void MeshStorage::_mesh_surface_clear(Mesh *mesh, int p_surface) {
|
||||
Mesh::Surface &s = *mesh->surfaces[p_surface];
|
||||
|
||||
if (s.vertex_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.vertex_buffer);
|
||||
s.vertex_buffer = 0;
|
||||
}
|
||||
|
||||
if (s.version_count != 0) {
|
||||
for (uint32_t j = 0; j < s.version_count; j++) {
|
||||
glDeleteVertexArrays(1, &s.versions[j].vertex_array);
|
||||
s.versions[j].vertex_array = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s.attribute_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.attribute_buffer);
|
||||
s.attribute_buffer = 0;
|
||||
}
|
||||
|
||||
if (s.skin_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.skin_buffer);
|
||||
s.skin_buffer = 0;
|
||||
}
|
||||
|
||||
if (s.index_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.index_buffer);
|
||||
s.index_buffer = 0;
|
||||
}
|
||||
|
||||
if (s.versions) {
|
||||
memfree(s.versions); // reallocs, so free with memfree.
|
||||
}
|
||||
|
||||
if (s.wireframe) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.wireframe->index_buffer);
|
||||
memdelete(s.wireframe);
|
||||
}
|
||||
|
||||
if (s.lod_count) {
|
||||
for (uint32_t j = 0; j < s.lod_count; j++) {
|
||||
if (s.lods[j].index_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.lods[j].index_buffer);
|
||||
s.lods[j].index_buffer = 0;
|
||||
}
|
||||
}
|
||||
memdelete_arr(s.lods);
|
||||
}
|
||||
|
||||
if (mesh->blend_shape_count) {
|
||||
for (uint32_t j = 0; j < mesh->blend_shape_count; j++) {
|
||||
if (s.blend_shapes[j].vertex_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.blend_shapes[j].vertex_buffer);
|
||||
s.blend_shapes[j].vertex_buffer = 0;
|
||||
}
|
||||
if (s.blend_shapes[j].vertex_array != 0) {
|
||||
glDeleteVertexArrays(1, &s.blend_shapes[j].vertex_array);
|
||||
s.blend_shapes[j].vertex_array = 0;
|
||||
}
|
||||
}
|
||||
memdelete_arr(s.blend_shapes);
|
||||
}
|
||||
|
||||
memdelete(mesh->surfaces[p_surface]);
|
||||
}
|
||||
|
||||
int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const {
|
||||
const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
|
||||
ERR_FAIL_NULL_V(mesh, -1);
|
||||
|
|
@ -743,6 +808,7 @@ String MeshStorage::mesh_get_path(RID p_mesh) const {
|
|||
}
|
||||
|
||||
void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
|
||||
ERR_FAIL_COND_MSG(p_mesh == p_shadow_mesh, "Cannot set a mesh as its own shadow mesh.");
|
||||
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
|
||||
ERR_FAIL_NULL(mesh);
|
||||
|
||||
|
|
@ -771,69 +837,7 @@ void MeshStorage::mesh_clear(RID p_mesh) {
|
|||
}
|
||||
|
||||
for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
||||
Mesh::Surface &s = *mesh->surfaces[i];
|
||||
|
||||
if (s.vertex_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.vertex_buffer);
|
||||
s.vertex_buffer = 0;
|
||||
}
|
||||
|
||||
if (s.version_count != 0) {
|
||||
for (uint32_t j = 0; j < s.version_count; j++) {
|
||||
glDeleteVertexArrays(1, &s.versions[j].vertex_array);
|
||||
s.versions[j].vertex_array = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s.attribute_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.attribute_buffer);
|
||||
s.attribute_buffer = 0;
|
||||
}
|
||||
|
||||
if (s.skin_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.skin_buffer);
|
||||
s.skin_buffer = 0;
|
||||
}
|
||||
|
||||
if (s.index_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.index_buffer);
|
||||
s.index_buffer = 0;
|
||||
}
|
||||
|
||||
if (s.versions) {
|
||||
memfree(s.versions); //reallocs, so free with memfree.
|
||||
}
|
||||
|
||||
if (s.wireframe) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.wireframe->index_buffer);
|
||||
memdelete(s.wireframe);
|
||||
}
|
||||
|
||||
if (s.lod_count) {
|
||||
for (uint32_t j = 0; j < s.lod_count; j++) {
|
||||
if (s.lods[j].index_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.lods[j].index_buffer);
|
||||
s.lods[j].index_buffer = 0;
|
||||
}
|
||||
}
|
||||
memdelete_arr(s.lods);
|
||||
}
|
||||
|
||||
if (mesh->blend_shape_count) {
|
||||
for (uint32_t j = 0; j < mesh->blend_shape_count; j++) {
|
||||
if (s.blend_shapes[j].vertex_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(s.blend_shapes[j].vertex_buffer);
|
||||
s.blend_shapes[j].vertex_buffer = 0;
|
||||
}
|
||||
if (s.blend_shapes[j].vertex_array != 0) {
|
||||
glDeleteVertexArrays(1, &s.blend_shapes[j].vertex_array);
|
||||
s.blend_shapes[j].vertex_array = 0;
|
||||
}
|
||||
}
|
||||
memdelete_arr(s.blend_shapes);
|
||||
}
|
||||
|
||||
memdelete(mesh->surfaces[i]);
|
||||
_mesh_surface_clear(mesh, i);
|
||||
}
|
||||
if (mesh->surfaces) {
|
||||
memfree(mesh->surfaces);
|
||||
|
|
@ -843,6 +847,7 @@ void MeshStorage::mesh_clear(RID p_mesh) {
|
|||
mesh->surface_count = 0;
|
||||
mesh->material_cache.clear();
|
||||
mesh->has_bone_weights = false;
|
||||
mesh->aabb = AABB();
|
||||
mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
|
||||
|
||||
for (Mesh *E : mesh->shadow_owners) {
|
||||
|
|
@ -1032,6 +1037,56 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
|
|||
v.input_mask = p_input_mask;
|
||||
}
|
||||
|
||||
void MeshStorage::mesh_surface_remove(RID p_mesh, int p_surface) {
|
||||
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
|
||||
ERR_FAIL_NULL(mesh);
|
||||
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
|
||||
|
||||
// Clear instance data before mesh data.
|
||||
for (MeshInstance *mi : mesh->instances) {
|
||||
_mesh_instance_remove_surface(mi, p_surface);
|
||||
}
|
||||
|
||||
_mesh_surface_clear(mesh, p_surface);
|
||||
|
||||
if ((uint32_t)p_surface < mesh->surface_count - 1) {
|
||||
memmove(mesh->surfaces + p_surface, mesh->surfaces + p_surface + 1, sizeof(Mesh::Surface *) * (mesh->surface_count - (p_surface + 1)));
|
||||
}
|
||||
mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count - 1));
|
||||
--mesh->surface_count;
|
||||
|
||||
mesh->material_cache.clear();
|
||||
|
||||
mesh->skeleton_aabb_version = 0;
|
||||
|
||||
if (mesh->has_bone_weights) {
|
||||
mesh->has_bone_weights = false;
|
||||
for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
||||
if (mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) {
|
||||
mesh->has_bone_weights = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh->surface_count == 0) {
|
||||
mesh->aabb = AABB();
|
||||
} else {
|
||||
mesh->aabb = mesh->surfaces[0]->aabb;
|
||||
for (uint32_t i = 1; i < mesh->surface_count; i++) {
|
||||
mesh->aabb.merge_with(mesh->surfaces[i]->aabb);
|
||||
}
|
||||
}
|
||||
|
||||
mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
|
||||
|
||||
for (Mesh *E : mesh->shadow_owners) {
|
||||
Mesh *shadow_owner = E;
|
||||
shadow_owner->shadow_mesh = RID();
|
||||
shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
|
||||
}
|
||||
}
|
||||
|
||||
/* MESH INSTANCE API */
|
||||
|
||||
RID MeshStorage::mesh_instance_create(RID p_base) {
|
||||
|
|
@ -1082,30 +1137,10 @@ void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int
|
|||
}
|
||||
|
||||
void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
|
||||
for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
|
||||
if (mi->surfaces[i].version_count != 0) {
|
||||
for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) {
|
||||
glDeleteVertexArrays(1, &mi->surfaces[i].versions[j].vertex_array);
|
||||
mi->surfaces[i].versions[j].vertex_array = 0;
|
||||
}
|
||||
memfree(mi->surfaces[i].versions);
|
||||
}
|
||||
|
||||
if (mi->surfaces[i].vertex_buffers[0] != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffers[0]);
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffers[1]);
|
||||
mi->surfaces[i].vertex_buffers[0] = 0;
|
||||
mi->surfaces[i].vertex_buffers[1] = 0;
|
||||
}
|
||||
|
||||
if (mi->surfaces[i].vertex_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffer);
|
||||
mi->surfaces[i].vertex_buffer = 0;
|
||||
}
|
||||
while (mi->surfaces.size()) {
|
||||
_mesh_instance_remove_surface(mi, mi->surfaces.size() - 1);
|
||||
}
|
||||
mi->surfaces.clear();
|
||||
mi->blend_weights.clear();
|
||||
mi->skeleton_version = 0;
|
||||
mi->dirty = false;
|
||||
}
|
||||
|
||||
void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) {
|
||||
|
|
@ -1158,6 +1193,39 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
|
|||
mi->dirty = true;
|
||||
}
|
||||
|
||||
void MeshStorage::_mesh_instance_remove_surface(MeshInstance *mi, int p_surface) {
|
||||
MeshInstance::Surface &surface = mi->surfaces[p_surface];
|
||||
|
||||
if (surface.version_count != 0) {
|
||||
for (uint32_t j = 0; j < surface.version_count; j++) {
|
||||
glDeleteVertexArrays(1, &surface.versions[j].vertex_array);
|
||||
surface.versions[j].vertex_array = 0;
|
||||
}
|
||||
memfree(surface.versions);
|
||||
}
|
||||
|
||||
if (surface.vertex_buffers[0] != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(surface.vertex_buffers[0]);
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(surface.vertex_buffers[1]);
|
||||
surface.vertex_buffers[0] = 0;
|
||||
surface.vertex_buffers[1] = 0;
|
||||
}
|
||||
|
||||
if (surface.vertex_buffer != 0) {
|
||||
GLES3::Utilities::get_singleton()->buffer_free_data(surface.vertex_buffer);
|
||||
surface.vertex_buffer = 0;
|
||||
}
|
||||
|
||||
mi->surfaces.remove_at(p_surface);
|
||||
|
||||
if (mi->surfaces.is_empty()) {
|
||||
mi->blend_weights.clear();
|
||||
mi->weights_dirty = false;
|
||||
mi->skeleton_version = 0;
|
||||
}
|
||||
mi->dirty = true;
|
||||
}
|
||||
|
||||
void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
|
||||
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
|
||||
|
||||
|
|
@ -1258,7 +1326,7 @@ void MeshStorage::update_mesh_instances() {
|
|||
|
||||
// Precompute base weight if using blend shapes.
|
||||
float base_weight = 1.0;
|
||||
if (mi->mesh->blend_shape_count && mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED) {
|
||||
if (mi->surfaces.size() && mi->mesh->blend_shape_count && mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED) {
|
||||
for (uint32_t i = 0; i < mi->mesh->blend_shape_count; i++) {
|
||||
base_weight -= mi->blend_weights[i];
|
||||
}
|
||||
|
|
@ -1432,15 +1500,17 @@ void MeshStorage::update_mesh_instances() {
|
|||
|
||||
/* MULTIMESH API */
|
||||
|
||||
RID MeshStorage::multimesh_allocate() {
|
||||
RID MeshStorage::_multimesh_allocate() {
|
||||
return multimesh_owner.allocate_rid();
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_initialize(RID p_rid) {
|
||||
void MeshStorage::_multimesh_initialize(RID p_rid) {
|
||||
multimesh_owner.initialize_rid(p_rid, MultiMesh());
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_free(RID p_rid) {
|
||||
void MeshStorage::_multimesh_free(RID p_rid) {
|
||||
// Remove from interpolator.
|
||||
_interpolation_data.notify_free_multimesh(p_rid);
|
||||
_update_dirty_multimeshes();
|
||||
multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
|
||||
|
|
@ -1448,7 +1518,7 @@ void MeshStorage::multimesh_free(RID p_rid) {
|
|||
multimesh_owner.free(p_rid);
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
|
||||
void MeshStorage::_multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data, bool p_use_indirect) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
|
||||
|
|
@ -1495,13 +1565,13 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
|
|||
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH);
|
||||
}
|
||||
|
||||
int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
|
||||
int MeshStorage::_multimesh_get_instance_count(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, 0);
|
||||
return multimesh->instances;
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
|
||||
void MeshStorage::_multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
if (multimesh->mesh == p_mesh || p_mesh.is_null()) {
|
||||
|
|
@ -1651,7 +1721,7 @@ void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p
|
|||
multimesh->aabb = aabb;
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
|
||||
void MeshStorage::_multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
ERR_FAIL_INDEX(p_index, multimesh->instances);
|
||||
|
|
@ -1681,7 +1751,7 @@ void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index,
|
|||
_multimesh_mark_dirty(multimesh, p_index, true);
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
|
||||
void MeshStorage::_multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
ERR_FAIL_INDEX(p_index, multimesh->instances);
|
||||
|
|
@ -1707,7 +1777,7 @@ void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_ind
|
|||
_multimesh_mark_dirty(multimesh, p_index, true);
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
|
||||
void MeshStorage::_multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
ERR_FAIL_INDEX(p_index, multimesh->instances);
|
||||
|
|
@ -1727,7 +1797,7 @@ void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, con
|
|||
_multimesh_mark_dirty(multimesh, p_index, false);
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
|
||||
void MeshStorage::_multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
ERR_FAIL_INDEX(p_index, multimesh->instances);
|
||||
|
|
@ -1746,39 +1816,39 @@ void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_inde
|
|||
_multimesh_mark_dirty(multimesh, p_index, false);
|
||||
}
|
||||
|
||||
RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const {
|
||||
RID MeshStorage::_multimesh_get_mesh(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, RID());
|
||||
|
||||
return multimesh->mesh;
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) {
|
||||
void MeshStorage::_multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
multimesh->custom_aabb = p_aabb;
|
||||
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
|
||||
}
|
||||
|
||||
AABB MeshStorage::multimesh_get_custom_aabb(RID p_multimesh) const {
|
||||
AABB MeshStorage::_multimesh_get_custom_aabb(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, AABB());
|
||||
return multimesh->custom_aabb;
|
||||
}
|
||||
|
||||
AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const {
|
||||
AABB MeshStorage::_multimesh_get_aabb(RID p_multimesh) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, AABB());
|
||||
if (multimesh->custom_aabb != AABB()) {
|
||||
return multimesh->custom_aabb;
|
||||
}
|
||||
if (multimesh->aabb_dirty) {
|
||||
const_cast<MeshStorage *>(this)->_update_dirty_multimeshes();
|
||||
_update_dirty_multimeshes();
|
||||
}
|
||||
return multimesh->aabb;
|
||||
}
|
||||
|
||||
Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
|
||||
Transform3D MeshStorage::_multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, Transform3D());
|
||||
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
|
||||
|
|
@ -1809,7 +1879,7 @@ Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p
|
|||
return t;
|
||||
}
|
||||
|
||||
Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
|
||||
Transform2D MeshStorage::_multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, Transform2D());
|
||||
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
|
||||
|
|
@ -1834,7 +1904,7 @@ Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, in
|
|||
return t;
|
||||
}
|
||||
|
||||
Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
|
||||
Color MeshStorage::_multimesh_instance_get_color(RID p_multimesh, int p_index) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, Color());
|
||||
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
|
||||
|
|
@ -1858,7 +1928,7 @@ Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) co
|
|||
return c;
|
||||
}
|
||||
|
||||
Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
|
||||
Color MeshStorage::_multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, Color());
|
||||
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
|
||||
|
|
@ -1882,7 +1952,7 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind
|
|||
return c;
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
|
||||
void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
|
||||
|
|
@ -1971,7 +2041,15 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
|
|||
}
|
||||
}
|
||||
|
||||
Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
|
||||
RID MeshStorage::_multimesh_get_command_buffer_rd_rid(RID p_multimesh) const {
|
||||
ERR_FAIL_V_MSG(RID(), "GLES3 does not implement indirect multimeshes.");
|
||||
}
|
||||
|
||||
RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const {
|
||||
ERR_FAIL_V_MSG(RID(), "GLES3 does not contain a Rid for the multimesh buffer.");
|
||||
}
|
||||
|
||||
Vector<float> MeshStorage::_multimesh_get_buffer(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, Vector<float>());
|
||||
Vector<float> ret;
|
||||
|
|
@ -2043,7 +2121,7 @@ Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
|
|||
}
|
||||
}
|
||||
|
||||
void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
|
||||
void MeshStorage::_multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL(multimesh);
|
||||
ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
|
||||
|
|
@ -2065,12 +2143,19 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible
|
|||
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
|
||||
}
|
||||
|
||||
int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
|
||||
int MeshStorage::_multimesh_get_visible_instances(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V(multimesh, 0);
|
||||
return multimesh->visible_instances;
|
||||
}
|
||||
|
||||
MeshStorage::MultiMeshInterpolator *MeshStorage::_multimesh_get_interpolator(RID p_multimesh) const {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
|
||||
ERR_FAIL_NULL_V_MSG(multimesh, nullptr, "Multimesh not found: " + itos(p_multimesh.get_id()));
|
||||
|
||||
return &multimesh->interpolator;
|
||||
}
|
||||
|
||||
void MeshStorage::_update_dirty_multimeshes() {
|
||||
while (multimesh_dirty_list) {
|
||||
MultiMesh *multimesh = multimesh_dirty_list;
|
||||
|
|
@ -2191,7 +2276,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_
|
|||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
GLES3::Utilities::get_singleton()->texture_allocated_data(skeleton->transforms_texture, skeleton->data.size() * sizeof(float), "Skeleton transforms texture");
|
||||
|
||||
memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
|
||||
memset(skeleton->data.ptr(), 0, skeleton->data.size() * sizeof(float));
|
||||
|
||||
_skeleton_make_dirty(skeleton);
|
||||
}
|
||||
|
|
@ -2222,7 +2307,7 @@ void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const
|
|||
ERR_FAIL_INDEX(p_bone, skeleton->size);
|
||||
ERR_FAIL_COND(skeleton->use_2d);
|
||||
|
||||
float *dataptr = skeleton->data.ptrw() + p_bone * 12;
|
||||
float *dataptr = skeleton->data.ptr() + p_bone * 12;
|
||||
|
||||
dataptr[0] = p_transform.basis.rows[0][0];
|
||||
dataptr[1] = p_transform.basis.rows[0][1];
|
||||
|
|
@ -2274,7 +2359,7 @@ void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, con
|
|||
ERR_FAIL_INDEX(p_bone, skeleton->size);
|
||||
ERR_FAIL_COND(!skeleton->use_2d);
|
||||
|
||||
float *dataptr = skeleton->data.ptrw() + p_bone * 8;
|
||||
float *dataptr = skeleton->data.ptr() + p_bone * 8;
|
||||
|
||||
dataptr[0] = p_transform.columns[0][0];
|
||||
dataptr[1] = p_transform.columns[1][0];
|
||||
|
|
|
|||
|
|
@ -205,6 +205,8 @@ struct MultiMesh {
|
|||
bool dirty = false;
|
||||
MultiMesh *dirty_list = nullptr;
|
||||
|
||||
RendererMeshStorage::MultiMeshInterpolator interpolator;
|
||||
|
||||
Dependency dependency;
|
||||
};
|
||||
|
||||
|
|
@ -212,7 +214,7 @@ struct Skeleton {
|
|||
bool use_2d = false;
|
||||
int size = 0;
|
||||
int height = 0;
|
||||
Vector<float> data;
|
||||
LocalVector<float> data;
|
||||
|
||||
bool dirty = false;
|
||||
Skeleton *dirty_list = nullptr;
|
||||
|
|
@ -239,6 +241,7 @@ private:
|
|||
mutable RID_Owner<Mesh, true> mesh_owner;
|
||||
|
||||
void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, MeshInstance::Surface *mis = nullptr);
|
||||
void _mesh_surface_clear(Mesh *mesh, int p_surface);
|
||||
|
||||
/* Mesh Instance API */
|
||||
|
||||
|
|
@ -246,6 +249,7 @@ private:
|
|||
|
||||
void _mesh_instance_clear(MeshInstance *mi);
|
||||
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
|
||||
void _mesh_instance_remove_surface(MeshInstance *mi, int p_surface);
|
||||
void _blend_shape_bind_mesh_instance_buffer(MeshInstance *p_mi, uint32_t p_surface);
|
||||
SelfList<MeshInstance>::List dirty_mesh_instance_weights;
|
||||
SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
|
||||
|
|
@ -278,8 +282,8 @@ public:
|
|||
|
||||
/* MESH API */
|
||||
|
||||
Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); };
|
||||
bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
|
||||
Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); }
|
||||
bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }
|
||||
|
||||
virtual RID mesh_allocate() override;
|
||||
virtual void mesh_initialize(RID p_rid) override;
|
||||
|
|
@ -313,7 +317,9 @@ public:
|
|||
virtual String mesh_get_path(RID p_mesh) const override;
|
||||
|
||||
virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;
|
||||
|
||||
virtual void mesh_clear(RID p_mesh) override;
|
||||
virtual void mesh_surface_remove(RID p_mesh, int p_surface) override;
|
||||
|
||||
_FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
|
||||
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
|
||||
|
|
@ -441,8 +447,8 @@ public:
|
|||
|
||||
/* MESH INSTANCE API */
|
||||
|
||||
MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
|
||||
bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
|
||||
MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); }
|
||||
bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); }
|
||||
|
||||
virtual RID mesh_instance_create(RID p_base) override;
|
||||
virtual void mesh_instance_free(RID p_rid) override;
|
||||
|
|
@ -490,35 +496,39 @@ public:
|
|||
|
||||
/* MULTIMESH API */
|
||||
|
||||
MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
|
||||
bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
|
||||
MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); }
|
||||
bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }
|
||||
|
||||
virtual RID multimesh_allocate() override;
|
||||
virtual void multimesh_initialize(RID p_rid) override;
|
||||
virtual void multimesh_free(RID p_rid) override;
|
||||
virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
|
||||
virtual int multimesh_get_instance_count(RID p_multimesh) const override;
|
||||
virtual RID _multimesh_allocate() override;
|
||||
virtual void _multimesh_initialize(RID p_rid) override;
|
||||
virtual void _multimesh_free(RID p_rid) override;
|
||||
virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) override;
|
||||
virtual int _multimesh_get_instance_count(RID p_multimesh) const override;
|
||||
|
||||
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
|
||||
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
|
||||
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
|
||||
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
|
||||
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
|
||||
virtual void _multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
|
||||
virtual void _multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
|
||||
virtual void _multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
|
||||
virtual void _multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
|
||||
virtual void _multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
|
||||
|
||||
virtual RID multimesh_get_mesh(RID p_multimesh) const override;
|
||||
virtual void multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) override;
|
||||
virtual AABB multimesh_get_custom_aabb(RID p_multimesh) const override;
|
||||
virtual AABB multimesh_get_aabb(RID p_multimesh) const override;
|
||||
virtual RID _multimesh_get_mesh(RID p_multimesh) const override;
|
||||
virtual void _multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) override;
|
||||
virtual AABB _multimesh_get_custom_aabb(RID p_multimesh) const override;
|
||||
virtual AABB _multimesh_get_aabb(RID p_multimesh) override;
|
||||
|
||||
virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
|
||||
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
|
||||
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
|
||||
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
|
||||
virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
|
||||
virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override;
|
||||
virtual Transform3D _multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
|
||||
virtual Transform2D _multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
|
||||
virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
|
||||
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
|
||||
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
|
||||
virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const override;
|
||||
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override;
|
||||
virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const override;
|
||||
|
||||
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
|
||||
virtual int multimesh_get_visible_instances(RID p_multimesh) const override;
|
||||
virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
|
||||
virtual int _multimesh_get_visible_instances(RID p_multimesh) const override;
|
||||
|
||||
virtual MultiMeshInterpolator *_multimesh_get_interpolator(RID p_multimesh) const override;
|
||||
|
||||
void _update_dirty_multimeshes();
|
||||
|
||||
|
|
@ -567,8 +577,8 @@ public:
|
|||
|
||||
/* SKELETON API */
|
||||
|
||||
Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
|
||||
bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
|
||||
Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); }
|
||||
bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); }
|
||||
|
||||
virtual RID skeleton_allocate() override;
|
||||
virtual void skeleton_initialize(RID p_rid) override;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#include "texture_storage.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include "servers/rendering/rendering_server_default.h"
|
||||
#include "servers/rendering/rendering_server_globals.h"
|
||||
|
||||
using namespace GLES3;
|
||||
|
||||
|
|
@ -223,6 +223,19 @@ void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_
|
|||
ERR_FAIL_NULL(particles);
|
||||
particles->pre_process_time = p_time;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_request_process_time(RID p_particles, real_t p_request_process_time) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
particles->request_process_time = p_request_process_time;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_seed(RID p_particles, uint32_t p_seed) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
particles->random_seed = p_seed;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL(particles);
|
||||
|
|
@ -287,13 +300,13 @@ void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_en
|
|||
|
||||
void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
|
||||
if (p_enable) {
|
||||
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support particle trails.");
|
||||
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support particle trails.");
|
||||
}
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
|
||||
if (p_bind_poses.size() != 0) {
|
||||
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support particle trails.");
|
||||
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support particle trails.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -357,12 +370,12 @@ void ParticlesStorage::particles_restart(RID p_particles) {
|
|||
|
||||
void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
|
||||
if (p_subemitter_particles.is_valid()) {
|
||||
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support particle sub-emitters.");
|
||||
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support particle sub-emitters.");
|
||||
}
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
|
||||
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support manually emitting particles.");
|
||||
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support manually emitting particles.");
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_request_process(RID p_particles) {
|
||||
|
|
@ -507,7 +520,6 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
|
|||
|
||||
if (p_particles->clear) {
|
||||
p_particles->cycle_number = 0;
|
||||
p_particles->random_seed = Math::rand();
|
||||
} else if (new_phase < p_particles->phase) {
|
||||
if (p_particles->one_shot) {
|
||||
p_particles->emitting = false;
|
||||
|
|
@ -645,7 +657,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
|
|||
attr.extents[2] = extents.z;
|
||||
} break;
|
||||
case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
|
||||
WARN_PRINT_ONCE_ED("Vector field particle attractors are not available in the GL Compatibility rendering backend.");
|
||||
WARN_PRINT_ONCE_ED("Vector field particle attractors are not available in the Compatibility renderer.");
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
|
|
@ -678,7 +690,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
|
|||
col.extents[2] = extents.z;
|
||||
} break;
|
||||
case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
|
||||
WARN_PRINT_ONCE_ED("SDF Particle Colliders are not available in the GL Compatibility rendering backend.");
|
||||
WARN_PRINT_ONCE_ED("SDF Particle Colliders are not available in the Compatibility renderer.");
|
||||
} break;
|
||||
case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
|
||||
if (collision_heightmap_texture != 0) { //already taken
|
||||
|
|
@ -1136,6 +1148,24 @@ void ParticlesStorage::update_particles() {
|
|||
}
|
||||
}
|
||||
|
||||
if (particles->request_process_time > 0.0) {
|
||||
double frame_time;
|
||||
if (fixed_fps > 0) {
|
||||
frame_time = 1.0 / fixed_fps;
|
||||
} else {
|
||||
frame_time = 1.0 / 30.0;
|
||||
}
|
||||
float tmp_scale = particles->speed_scale;
|
||||
particles->speed_scale = 1.0;
|
||||
double todo = particles->request_process_time;
|
||||
while (todo >= 0) {
|
||||
_particles_process(particles, frame_time);
|
||||
todo -= frame_time;
|
||||
}
|
||||
particles->speed_scale = tmp_scale;
|
||||
particles->request_process_time = 0.0;
|
||||
}
|
||||
|
||||
// Copy particles to instance buffer and pack Color/Custom.
|
||||
// We don't have camera information here, so don't copy here if we need camera information for view depth or align mode.
|
||||
if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
|
||||
|
|
@ -1341,7 +1371,7 @@ void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_parti
|
|||
}
|
||||
|
||||
void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
|
||||
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support SDF collisions in 3D particle shaders");
|
||||
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support SDF collisions in 3D particle shaders");
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
|
||||
|
|
@ -1402,6 +1432,18 @@ bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collis
|
|||
return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
|
||||
}
|
||||
|
||||
uint32_t ParticlesStorage::particles_collision_get_height_field_mask(RID p_particles_collision) const {
|
||||
const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
|
||||
ERR_FAIL_NULL_V(particles_collision, false);
|
||||
return particles_collision->heightfield_mask;
|
||||
}
|
||||
|
||||
void ParticlesStorage::particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) {
|
||||
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
|
||||
ERR_FAIL_NULL(particles_collision);
|
||||
particles_collision->heightfield_mask = p_heightfield_mask;
|
||||
}
|
||||
|
||||
Dependency *ParticlesStorage::particles_collision_get_dependency(RID p_particles_collision) const {
|
||||
ParticlesCollision *pc = particles_collision_owner.get_or_null(p_particles_collision);
|
||||
ERR_FAIL_NULL_V(pc, nullptr);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/templates/self_list.h"
|
||||
#include "drivers/gles3/shaders/particles_copy.glsl.gen.h"
|
||||
|
|
@ -158,6 +157,7 @@ private:
|
|||
int amount = 0;
|
||||
double lifetime = 1.0;
|
||||
double pre_process_time = 0.0;
|
||||
real_t request_process_time = 0.0;
|
||||
real_t explosiveness = 0.0;
|
||||
real_t randomness = 0.0;
|
||||
bool restart_request = false;
|
||||
|
|
@ -247,6 +247,7 @@ private:
|
|||
|
||||
Particles() :
|
||||
update_list(this) {
|
||||
random_seed = Math::rand();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -286,6 +287,7 @@ private:
|
|||
GLuint heightfield_texture = 0;
|
||||
GLuint heightfield_fb = 0;
|
||||
Size2i heightfield_fb_size;
|
||||
uint32_t heightfield_mask = (1 << 20) - 1;
|
||||
|
||||
RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
|
||||
|
||||
|
|
@ -326,6 +328,7 @@ public:
|
|||
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
|
||||
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
|
||||
virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
|
||||
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) override;
|
||||
virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
|
||||
|
|
@ -341,6 +344,7 @@ public:
|
|||
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
|
||||
|
||||
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
|
||||
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) override;
|
||||
|
||||
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
|
||||
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
|
||||
|
|
@ -396,7 +400,7 @@ public:
|
|||
|
||||
_FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
|
||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||
ERR_FAIL_NULL_V(particles, 0);
|
||||
ERR_FAIL_NULL_V(particles, false);
|
||||
|
||||
return particles->has_collision_cache;
|
||||
}
|
||||
|
|
@ -431,6 +435,8 @@ public:
|
|||
Vector3 particles_collision_get_extents(RID p_particles_collision) const;
|
||||
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
|
||||
GLuint particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
|
||||
virtual uint32_t particles_collision_get_height_field_mask(RID p_particles_collision) const override;
|
||||
virtual void particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) override;
|
||||
|
||||
_FORCE_INLINE_ Size2i particles_collision_get_heightfield_size(RID p_particles_collision) const {
|
||||
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
|||
scaling_3d_mode = p_config->get_scaling_3d_mode();
|
||||
//fsr_sharpness = p_config->get_fsr_sharpness();
|
||||
//texture_mipmap_bias = p_config->get_texture_mipmap_bias();
|
||||
//anisotropic_filtering_level = p_config->get_anisotropic_filtering_level();
|
||||
render_target = p_config->get_render_target();
|
||||
msaa3d.mode = p_config->get_msaa_3d();
|
||||
//screen_space_aa = p_config->get_screen_space_aa();
|
||||
|
|
|
|||
|
|
@ -103,9 +103,10 @@ public:
|
|||
virtual void configure(const RenderSceneBuffersConfiguration *p_config) override;
|
||||
void configure_for_probe(Size2i p_size);
|
||||
|
||||
virtual void set_fsr_sharpness(float p_fsr_sharpness) override{};
|
||||
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override{};
|
||||
virtual void set_use_debanding(bool p_use_debanding) override{};
|
||||
virtual void set_anisotropic_filtering_level(RS::ViewportAnisotropicFiltering p_anisotropic_filtering_level) override {}
|
||||
virtual void set_fsr_sharpness(float p_fsr_sharpness) override {}
|
||||
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override {}
|
||||
virtual void set_use_debanding(bool p_use_debanding) override {}
|
||||
void set_apply_color_adjustments_in_post(bool p_apply_in_post);
|
||||
|
||||
void free_render_buffer_data();
|
||||
|
|
|
|||
|
|
@ -152,6 +152,11 @@ TextureStorage::TextureStorage() {
|
|||
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_ANISO], image);
|
||||
}
|
||||
|
||||
{
|
||||
default_gl_textures[DEFAULT_GL_TEXTURE_EXT] = texture_allocate();
|
||||
texture_external_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_EXT], 1, 1, 0);
|
||||
}
|
||||
|
||||
{
|
||||
unsigned char pixel_data[4 * 4 * 4];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
|
|
@ -225,6 +230,32 @@ TextureStorage::TextureStorage() {
|
|||
sdf_shader.shader_version = sdf_shader.shader.version_create();
|
||||
}
|
||||
|
||||
// Initialize texture placeholder data for the `texture_*_placeholder_initialize()` methods.
|
||||
|
||||
constexpr int placeholder_size = 4;
|
||||
texture_2d_placeholder = Image::create_empty(placeholder_size, placeholder_size, false, Image::FORMAT_RGBA8);
|
||||
// Draw a magenta/black checkerboard pattern.
|
||||
for (int i = 0; i < placeholder_size * placeholder_size; i++) {
|
||||
const int x = i % placeholder_size;
|
||||
const int y = i / placeholder_size;
|
||||
texture_2d_placeholder->set_pixel(x, y, (x + y) % 2 == 0 ? Color(1, 0, 1) : Color(0, 0, 0));
|
||||
}
|
||||
|
||||
texture_2d_array_placeholder.push_back(texture_2d_placeholder);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
cubemap_placeholder.push_back(texture_2d_placeholder);
|
||||
}
|
||||
|
||||
Ref<Image> texture_2d_placeholder_rotated;
|
||||
texture_2d_placeholder_rotated.instantiate();
|
||||
texture_2d_placeholder_rotated->copy_from(texture_2d_placeholder);
|
||||
texture_2d_placeholder_rotated->rotate_90(CLOCKWISE);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// Alternate checkerboard pattern on odd layers (by using a copy that is rotated 90 degrees).
|
||||
texture_3d_placeholder.push_back(i % 2 == 0 ? texture_2d_placeholder : texture_2d_placeholder_rotated);
|
||||
}
|
||||
|
||||
#ifdef GL_API_ENABLED
|
||||
if (RasterizerGLES3::is_gles_over_gl()) {
|
||||
glEnable(GL_PROGRAM_POINT_SIZE);
|
||||
|
|
@ -246,11 +277,6 @@ TextureStorage::~TextureStorage() {
|
|||
sdf_shader.shader.version_free(sdf_shader.shader_version);
|
||||
}
|
||||
|
||||
//TODO, move back to storage
|
||||
bool TextureStorage::can_create_resources_async() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Canvas Texture API */
|
||||
|
||||
RID TextureStorage::canvas_texture_allocate() {
|
||||
|
|
@ -308,15 +334,8 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS:
|
|||
|
||||
/* Texture API */
|
||||
|
||||
Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const {
|
||||
static inline Error _get_gl_uncompressed_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type) {
|
||||
Config *config = Config::get_singleton();
|
||||
r_gl_format = 0;
|
||||
Ref<Image> image = p_image;
|
||||
r_compressed = false;
|
||||
r_real_format = p_format;
|
||||
|
||||
bool need_decompress = false;
|
||||
bool decompress_ra_to_rg = false;
|
||||
|
||||
switch (p_format) {
|
||||
case Image::FORMAT_L8: {
|
||||
|
|
@ -345,55 +364,95 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_internal_format = GL_R8;
|
||||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_RG8: {
|
||||
r_gl_internal_format = GL_RG8;
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_RGB8: {
|
||||
r_gl_internal_format = GL_RGB8;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_RGBA8: {
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_internal_format = GL_RGBA8;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_RGBA4444: {
|
||||
r_gl_internal_format = GL_RGBA4;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_RGB565: {
|
||||
r_gl_internal_format = GL_RGB565;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
} break;
|
||||
case Image::FORMAT_RF: {
|
||||
r_gl_internal_format = GL_R32F;
|
||||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_FLOAT;
|
||||
|
||||
if (config->float_texture_linear_supported) {
|
||||
r_gl_internal_format = GL_R32F;
|
||||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_FLOAT;
|
||||
} else {
|
||||
ERR_PRINT("R32 float texture not supported, converting to R16.");
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RH);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RH;
|
||||
r_gl_internal_format = GL_R16F;
|
||||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGF: {
|
||||
r_gl_internal_format = GL_RG32F;
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_FLOAT;
|
||||
|
||||
if (config->float_texture_linear_supported) {
|
||||
r_gl_internal_format = GL_RG32F;
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_FLOAT;
|
||||
} else {
|
||||
ERR_PRINT("RG32 float texture not supported, converting to RG16.");
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGH);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGH;
|
||||
r_gl_internal_format = GL_RG16F;
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGBF: {
|
||||
r_gl_internal_format = GL_RGB32F;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_FLOAT;
|
||||
|
||||
if (config->float_texture_linear_supported) {
|
||||
r_gl_internal_format = GL_RGB32F;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_FLOAT;
|
||||
} else {
|
||||
ERR_PRINT("RGB32 float texture not supported, converting to RGB16.");
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGBH);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGBH;
|
||||
r_gl_internal_format = GL_RGB16F;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGBAF: {
|
||||
r_gl_internal_format = GL_RGBA32F;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_FLOAT;
|
||||
|
||||
if (config->float_texture_linear_supported) {
|
||||
r_gl_internal_format = GL_RGBA32F;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_FLOAT;
|
||||
} else {
|
||||
ERR_PRINT("RGBA32 float texture not supported, converting to RGBA16.");
|
||||
if (p_image.is_valid()) {
|
||||
p_image->convert(Image::FORMAT_RGBAH);
|
||||
}
|
||||
r_real_format = Image::FORMAT_RGBAH;
|
||||
r_gl_internal_format = GL_RGBA16F;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RH: {
|
||||
r_gl_internal_format = GL_R16F;
|
||||
|
|
@ -404,26 +463,48 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_internal_format = GL_RG16F;
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_RGBH: {
|
||||
r_gl_internal_format = GL_RGB16F;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_RGBAH: {
|
||||
r_gl_internal_format = GL_RGBA16F;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_HALF_FLOAT;
|
||||
|
||||
} break;
|
||||
case Image::FORMAT_RGBE9995: {
|
||||
r_gl_internal_format = GL_RGB9_E5;
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV;
|
||||
|
||||
} break;
|
||||
default: {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const {
|
||||
Config *config = Config::get_singleton();
|
||||
r_gl_format = 0;
|
||||
Ref<Image> image = p_image;
|
||||
r_compressed = false;
|
||||
r_real_format = p_format;
|
||||
|
||||
if (!Image::is_format_compressed(p_format)) {
|
||||
Error err = _get_gl_uncompressed_format(p_image, p_format, r_real_format, r_gl_format, r_gl_internal_format, r_gl_type);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, Ref<Image>(), vformat("The image format %d is not supported by the Compatibility renderer.", p_format));
|
||||
return p_image;
|
||||
}
|
||||
|
||||
// For compressed images, some formats may not be supported by the current device and will require decompression.
|
||||
bool need_decompress = false;
|
||||
bool decompress_ra_to_rg = false;
|
||||
|
||||
switch (p_format) {
|
||||
case Image::FORMAT_DXT1: {
|
||||
if (config->s3tc_supported) {
|
||||
r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
|
|
@ -510,7 +591,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -521,7 +601,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RED;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -532,7 +611,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -543,7 +621,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RG;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -555,7 +632,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RGB;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -566,7 +642,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -577,7 +652,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -616,7 +690,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -627,7 +700,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -638,7 +710,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
|
|
@ -649,56 +720,31 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
|||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
ERR_FAIL_V_MSG(Ref<Image>(), "The image format " + itos(p_format) + " is not supported by the GL Compatibility rendering backend.");
|
||||
ERR_FAIL_V_MSG(Ref<Image>(), vformat("The image format %d is not supported by the Compatibility renderer.", p_format));
|
||||
}
|
||||
}
|
||||
|
||||
if (need_decompress || p_force_decompress) {
|
||||
if (!image.is_null()) {
|
||||
if (image.is_valid()) {
|
||||
image = image->duplicate();
|
||||
image->decompress();
|
||||
ERR_FAIL_COND_V(image->is_compressed(), image);
|
||||
|
||||
if (decompress_ra_to_rg) {
|
||||
image->convert_ra_rgba8_to_rg();
|
||||
image->convert(Image::FORMAT_RG8);
|
||||
}
|
||||
switch (image->get_format()) {
|
||||
case Image::FORMAT_RG8: {
|
||||
r_gl_format = GL_RG;
|
||||
r_gl_internal_format = GL_RG8;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_real_format = Image::FORMAT_RG8;
|
||||
r_compressed = false;
|
||||
} break;
|
||||
case Image::FORMAT_RGB8: {
|
||||
r_gl_format = GL_RGB;
|
||||
r_gl_internal_format = GL_RGB;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_real_format = Image::FORMAT_RGB8;
|
||||
r_compressed = false;
|
||||
} break;
|
||||
case Image::FORMAT_RGBA8: {
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_internal_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_real_format = Image::FORMAT_RGBA8;
|
||||
r_compressed = false;
|
||||
} break;
|
||||
default: {
|
||||
image->convert(Image::FORMAT_RGBA8);
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_internal_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_real_format = Image::FORMAT_RGBA8;
|
||||
r_compressed = false;
|
||||
} break;
|
||||
}
|
||||
|
||||
Error err = _get_gl_uncompressed_format(image, image->get_format(), r_real_format, r_gl_format, r_gl_internal_format, r_gl_type);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, Ref<Image>(), vformat("The image format %d is not supported by the Compatibility renderer.", image->get_format()));
|
||||
|
||||
r_real_format = image->get_format();
|
||||
r_compressed = false;
|
||||
}
|
||||
|
||||
return image;
|
||||
|
|
@ -729,7 +775,7 @@ void TextureStorage::texture_free(RID p_texture) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
must_free_data = t->tex_id != 0 && !t->is_external;
|
||||
must_free_data = t->tex_id != 0 && !t->is_from_native_handle;
|
||||
}
|
||||
if (must_free_data) {
|
||||
GLES3::Utilities::get_singleton()->texture_free_data(t->tex_id);
|
||||
|
|
@ -769,11 +815,53 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
|
|||
texture_set_data(p_texture, p_image);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) {
|
||||
Texture texture;
|
||||
texture.active = true;
|
||||
texture.alloc_width = texture.width = p_width;
|
||||
texture.alloc_height = texture.height = p_height;
|
||||
texture.real_format = texture.format = Image::FORMAT_RGB8;
|
||||
texture.type = Texture::TYPE_2D;
|
||||
|
||||
if (GLES3::Config::get_singleton()->external_texture_supported) {
|
||||
texture.target = _GL_TEXTURE_EXTERNAL_OES;
|
||||
} else {
|
||||
texture.target = GL_TEXTURE_2D;
|
||||
}
|
||||
|
||||
glGenTextures(1, &texture.tex_id);
|
||||
glBindTexture(texture.target, texture.tex_id);
|
||||
|
||||
#ifdef ANDROID_ENABLED
|
||||
if (texture.target == _GL_TEXTURE_EXTERNAL_OES) {
|
||||
if (p_external_buffer) {
|
||||
GLES3::Config::get_singleton()->eglEGLImageTargetTexture2DOES(_GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<void *>(p_external_buffer));
|
||||
}
|
||||
texture.total_data_size = 0;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// If external textures aren't supported, allocate an empty 1x1 texture.
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
texture.total_data_size = 3;
|
||||
}
|
||||
|
||||
glTexParameteri(texture.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(texture.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(texture.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(texture.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, texture.total_data_size, "Texture External");
|
||||
texture_owner.initialize_rid(p_texture, texture);
|
||||
|
||||
glBindTexture(texture.target, 0);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
|
||||
ERR_FAIL_COND(p_layers.is_empty());
|
||||
|
||||
ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6);
|
||||
ERR_FAIL_COND_MSG(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY, "Cubemap Arrays are not supported in the GL Compatibility backend.");
|
||||
ERR_FAIL_COND_MSG(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY, "Cubemap Arrays are not supported in the Compatibility renderer.");
|
||||
|
||||
const Ref<Image> &image = p_layers[0];
|
||||
{
|
||||
|
|
@ -874,26 +962,28 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
|
|||
texture_owner.initialize_rid(p_texture, proxy_tex);
|
||||
}
|
||||
|
||||
RID TextureStorage::texture_create_external(GLES3::Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
|
||||
RID TextureStorage::texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
|
||||
Texture texture;
|
||||
texture.active = true;
|
||||
texture.is_external = true;
|
||||
texture.type = p_type;
|
||||
texture.is_from_native_handle = true;
|
||||
|
||||
switch (p_type) {
|
||||
case Texture::TYPE_2D: {
|
||||
case RS::TEXTURE_TYPE_2D: {
|
||||
texture.type = Texture::TYPE_2D;
|
||||
texture.target = GL_TEXTURE_2D;
|
||||
} break;
|
||||
case Texture::TYPE_3D: {
|
||||
case RS::TEXTURE_TYPE_3D: {
|
||||
texture.type = Texture::TYPE_3D;
|
||||
texture.target = GL_TEXTURE_3D;
|
||||
} break;
|
||||
case Texture::TYPE_LAYERED: {
|
||||
case RS::TEXTURE_TYPE_LAYERED: {
|
||||
texture.type = Texture::TYPE_LAYERED;
|
||||
texture.target = GL_TEXTURE_2D_ARRAY;
|
||||
} break;
|
||||
}
|
||||
|
||||
texture.real_format = texture.format = p_format;
|
||||
texture.tex_id = p_image;
|
||||
texture.tex_id = p_native_handle;
|
||||
texture.alloc_width = texture.width = p_width;
|
||||
texture.alloc_height = texture.height = p_height;
|
||||
texture.depth = p_depth;
|
||||
|
|
@ -928,6 +1018,22 @@ void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &
|
|||
GLES3::Utilities::get_singleton()->texture_resize_data(tex->tex_id, tex->total_data_size);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) {
|
||||
Texture *tex = texture_owner.get_or_null(p_texture);
|
||||
ERR_FAIL_NULL(tex);
|
||||
|
||||
tex->alloc_width = tex->width = p_width;
|
||||
tex->alloc_height = tex->height = p_height;
|
||||
|
||||
#ifdef ANDROID_ENABLED
|
||||
if (tex->target == _GL_TEXTURE_EXTERNAL_OES && p_external_buffer) {
|
||||
glBindTexture(_GL_TEXTURE_EXTERNAL_OES, tex->tex_id);
|
||||
GLES3::Config::get_singleton()->eglEGLImageTargetTexture2DOES(_GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<void *>(p_external_buffer));
|
||||
glBindTexture(_GL_TEXTURE_EXTERNAL_OES, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
|
||||
Texture *tex = texture_owner.get_or_null(p_texture);
|
||||
ERR_FAIL_NULL(tex);
|
||||
|
|
@ -954,46 +1060,19 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
|
|||
}
|
||||
|
||||
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
|
||||
//this could be better optimized to reuse an existing image , done this way
|
||||
//for now to get it working
|
||||
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(1, 0, 1, 1));
|
||||
|
||||
texture_2d_initialize(p_texture, image);
|
||||
texture_2d_initialize(p_texture, texture_2d_placeholder);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) {
|
||||
//this could be better optimized to reuse an existing image , done this way
|
||||
//for now to get it working
|
||||
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(1, 0, 1, 1));
|
||||
|
||||
Vector<Ref<Image>> images;
|
||||
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
|
||||
if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
|
||||
images.push_back(image);
|
||||
texture_2d_layered_initialize(p_texture, texture_2d_array_placeholder, p_layered_type);
|
||||
} else {
|
||||
//cube
|
||||
for (int i = 0; i < 6; i++) {
|
||||
images.push_back(image);
|
||||
}
|
||||
texture_2d_layered_initialize(p_texture, cubemap_placeholder, p_layered_type);
|
||||
}
|
||||
|
||||
texture_2d_layered_initialize(p_texture, images, p_layered_type);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
|
||||
//this could be better optimized to reuse an existing image , done this way
|
||||
//for now to get it working
|
||||
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(1, 0, 1, 1));
|
||||
|
||||
Vector<Ref<Image>> images;
|
||||
//cube
|
||||
for (int i = 0; i < 4; i++) {
|
||||
images.push_back(image);
|
||||
}
|
||||
|
||||
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
|
||||
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, texture_3d_placeholder);
|
||||
}
|
||||
|
||||
Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
||||
|
|
@ -1013,7 +1092,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
|||
// It also allows for reading compressed textures, mipmaps, and more formats.
|
||||
Vector<uint8_t> data;
|
||||
|
||||
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->real_format, texture->mipmaps > 1);
|
||||
int64_t data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->real_format, texture->mipmaps > 1);
|
||||
|
||||
data.resize(data_size * 2); // Add some memory at the end, just in case for buggy drivers.
|
||||
uint8_t *w = data.ptrw();
|
||||
|
|
@ -1025,7 +1104,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
|||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
for (int i = 0; i < texture->mipmaps; i++) {
|
||||
int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, texture->real_format, i);
|
||||
int64_t ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, texture->real_format, i);
|
||||
|
||||
if (texture->compressed) {
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
|
|
@ -1039,9 +1118,13 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
|||
data.resize(data_size);
|
||||
|
||||
ERR_FAIL_COND_V(data.is_empty(), Ref<Image>());
|
||||
image = Image::create_from_data(texture->width, texture->height, texture->mipmaps > 1, texture->real_format, data);
|
||||
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
|
||||
if (texture->format != texture->real_format) {
|
||||
image = Image::create_from_data(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, texture->real_format, data);
|
||||
if (image->is_empty()) {
|
||||
const String &path_str = texture->path.is_empty() ? "with no path" : vformat("with path '%s'", texture->path);
|
||||
ERR_FAIL_V_MSG(Ref<Image>(), vformat("Texture %s has no data.", path_str));
|
||||
}
|
||||
|
||||
if (texture->format != texture->real_format && !Image::is_format_compressed(texture->real_format)) {
|
||||
image->convert(texture->format);
|
||||
}
|
||||
}
|
||||
|
|
@ -1051,7 +1134,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
|||
Vector<uint8_t> data;
|
||||
|
||||
// On web and mobile we always read an RGBA8 image with no mipmaps.
|
||||
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
|
||||
int64_t data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
|
||||
|
||||
data.resize(data_size * 2); // Add some memory at the end, just in case for buggy drivers.
|
||||
uint8_t *w = data.ptrw();
|
||||
|
|
@ -1095,10 +1178,13 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
|||
data.resize(data_size);
|
||||
|
||||
ERR_FAIL_COND_V(data.is_empty(), Ref<Image>());
|
||||
image = Image::create_from_data(texture->width, texture->height, false, Image::FORMAT_RGBA8, data);
|
||||
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
|
||||
image = Image::create_from_data(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data);
|
||||
if (image->is_empty()) {
|
||||
const String &path_str = texture->path.is_empty() ? "with no path" : vformat("with path '%s'", texture->path);
|
||||
ERR_FAIL_V_MSG(Ref<Image>(), vformat("Texture %s has no data.", path_str));
|
||||
}
|
||||
|
||||
if (texture->format != Image::FORMAT_RGBA8) {
|
||||
if (texture->format != Image::FORMAT_RGBA8 && !Image::is_format_compressed(texture->format)) {
|
||||
image->convert(texture->format);
|
||||
}
|
||||
|
||||
|
|
@ -1123,7 +1209,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons
|
|||
|
||||
Vector<uint8_t> data;
|
||||
|
||||
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
|
||||
int64_t data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
|
||||
|
||||
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
|
||||
uint8_t *w = data.ptrw();
|
||||
|
|
@ -1168,9 +1254,12 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons
|
|||
|
||||
ERR_FAIL_COND_V(data.is_empty(), Ref<Image>());
|
||||
Ref<Image> image = Image::create_from_data(texture->width, texture->height, false, Image::FORMAT_RGBA8, data);
|
||||
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
|
||||
if (image->is_empty()) {
|
||||
const String &path_str = texture->path.is_empty() ? "with no path" : vformat("with path '%s'", texture->path);
|
||||
ERR_FAIL_V_MSG(Ref<Image>(), vformat("Texture %s has no data.", path_str));
|
||||
}
|
||||
|
||||
if (texture->format != Image::FORMAT_RGBA8) {
|
||||
if (texture->format != Image::FORMAT_RGBA8 && !Image::is_format_compressed(texture->format)) {
|
||||
image->convert(texture->format);
|
||||
}
|
||||
|
||||
|
|
@ -1192,7 +1281,7 @@ Vector<Ref<Image>> TextureStorage::_texture_3d_read_framebuffer(GLES3::Texture *
|
|||
int depth = p_texture->depth;
|
||||
|
||||
for (int mipmap_level = 0; mipmap_level < p_texture->mipmaps; mipmap_level++) {
|
||||
int data_size = Image::get_image_data_size(width, height, Image::FORMAT_RGBA8, false);
|
||||
int64_t data_size = Image::get_image_data_size(width, height, Image::FORMAT_RGBA8, false);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
@ -1211,7 +1300,7 @@ Vector<Ref<Image>> TextureStorage::_texture_3d_read_framebuffer(GLES3::Texture *
|
|||
Ref<Image> img = Image::create_from_data(width, height, false, Image::FORMAT_RGBA8, data);
|
||||
ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>());
|
||||
|
||||
if (p_texture->format != Image::FORMAT_RGBA8) {
|
||||
if (p_texture->format != Image::FORMAT_RGBA8 && !Image::is_format_compressed(p_texture->format)) {
|
||||
img->convert(p_texture->format);
|
||||
}
|
||||
|
||||
|
|
@ -1389,8 +1478,22 @@ void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
|
|||
tinfo.format = t->format;
|
||||
tinfo.width = t->alloc_width;
|
||||
tinfo.height = t->alloc_height;
|
||||
tinfo.depth = t->depth;
|
||||
tinfo.bytes = t->total_data_size;
|
||||
|
||||
switch (t->type) {
|
||||
case Texture::TYPE_3D:
|
||||
tinfo.depth = t->depth;
|
||||
break;
|
||||
|
||||
case Texture::TYPE_LAYERED:
|
||||
tinfo.depth = t->layers;
|
||||
break;
|
||||
|
||||
default:
|
||||
tinfo.depth = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
r_info->push_back(tinfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -1452,8 +1555,17 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
|
|||
GLenum internal_format;
|
||||
bool compressed = false;
|
||||
|
||||
bool needs_decompress = texture->resize_to_po2;
|
||||
|
||||
// Support for RGTC-compressed Texture Arrays isn't mandated by GLES3/WebGL.
|
||||
if (!RasterizerGLES3::is_gles_over_gl() && texture->target == GL_TEXTURE_2D_ARRAY) {
|
||||
if (p_image->get_format() == Image::FORMAT_RGTC_R || p_image->get_format() == Image::FORMAT_RGTC_RG) {
|
||||
needs_decompress = true;
|
||||
}
|
||||
}
|
||||
|
||||
Image::Format real_format;
|
||||
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, texture->resize_to_po2);
|
||||
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, needs_decompress);
|
||||
ERR_FAIL_COND(img.is_null());
|
||||
if (texture->resize_to_po2) {
|
||||
if (p_image->is_compressed()) {
|
||||
|
|
@ -1497,11 +1609,9 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
|
|||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
if (texture->target == GL_TEXTURE_2D_ARRAY) {
|
||||
if (p_initialize) {
|
||||
glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, w, h, texture->layers, 0,
|
||||
size * texture->layers, &read[ofs]);
|
||||
} else {
|
||||
glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 1, internal_format, size, &read[ofs]);
|
||||
glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, w, h, texture->layers, 0, size * texture->layers, nullptr);
|
||||
}
|
||||
glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 1, internal_format, size, &read[ofs]);
|
||||
} else {
|
||||
glCompressedTexImage2D(blit_target, i, internal_format, w, h, 0, size, &read[ofs]);
|
||||
}
|
||||
|
|
@ -1523,7 +1633,11 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
|
|||
h = MAX(1, h >> 1);
|
||||
}
|
||||
|
||||
texture->total_data_size = tsize;
|
||||
if (texture->target == GL_TEXTURE_CUBE_MAP || texture->target == GL_TEXTURE_2D_ARRAY) {
|
||||
texture->total_data_size = tsize * texture->layers;
|
||||
} else {
|
||||
texture->total_data_size = tsize;
|
||||
}
|
||||
|
||||
texture->stored_cube_sides |= (1 << p_layer);
|
||||
|
||||
|
|
@ -1548,7 +1662,7 @@ void TextureStorage::_texture_set_3d_data(RID p_texture, const Vector<Ref<Image>
|
|||
Ref<Image> img = _get_gl_image_and_format(p_data[0], p_data[0]->get_format(), real_format, format, internal_format, type, compressed, texture->resize_to_po2);
|
||||
ERR_FAIL_COND(img.is_null());
|
||||
|
||||
ERR_FAIL_COND_MSG(compressed, "Compressed 3D textures are not supported in the GL Compatibility backend.");
|
||||
ERR_FAIL_COND_MSG(compressed, "Compressed 3D textures are not supported in the Compatibility renderer.");
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(texture->target, texture->tex_id);
|
||||
|
|
@ -1680,6 +1794,14 @@ uint32_t TextureStorage::texture_get_texid(RID p_texture) const {
|
|||
return texture->tex_id;
|
||||
}
|
||||
|
||||
Vector3i TextureStorage::texture_get_size(RID p_texture) const {
|
||||
Texture *texture = texture_owner.get_or_null(p_texture);
|
||||
|
||||
ERR_FAIL_NULL_V(texture, Vector3i(0, 0, 0));
|
||||
|
||||
return Vector3i(texture->width, texture->height, texture->depth);
|
||||
}
|
||||
|
||||
uint32_t TextureStorage::texture_get_width(RID p_texture) const {
|
||||
Texture *texture = texture_owner.get_or_null(p_texture);
|
||||
|
||||
|
|
@ -2369,7 +2491,7 @@ Point2i TextureStorage::render_target_get_position(RID p_render_target) const {
|
|||
ERR_FAIL_NULL_V(rt, Point2i());
|
||||
|
||||
return rt->position;
|
||||
};
|
||||
}
|
||||
|
||||
void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
|
|
@ -2398,7 +2520,7 @@ Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
|
|||
return rt->size;
|
||||
}
|
||||
|
||||
void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) {
|
||||
void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL(rt);
|
||||
ERR_FAIL_COND(rt->direct_to_screen);
|
||||
|
|
@ -2475,6 +2597,20 @@ RID TextureStorage::render_target_get_override_velocity(RID p_render_target) con
|
|||
return rt->overridden.velocity;
|
||||
}
|
||||
|
||||
void TextureStorage::render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL(rt);
|
||||
|
||||
rt->render_region = p_render_region;
|
||||
}
|
||||
|
||||
Rect2i TextureStorage::render_target_get_render_region(RID p_render_target) const {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL_V(rt, Rect2i());
|
||||
|
||||
return rt->render_region;
|
||||
}
|
||||
|
||||
RID TextureStorage::render_target_get_texture(RID p_render_target) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL_V(rt, RID());
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "platform_gl.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "servers/rendering/renderer_compositor.h"
|
||||
|
|
@ -126,6 +127,7 @@ enum DefaultGLTexture {
|
|||
DEFAULT_GL_TEXTURE_3D_BLACK,
|
||||
DEFAULT_GL_TEXTURE_2D_ARRAY_WHITE,
|
||||
DEFAULT_GL_TEXTURE_2D_UINT,
|
||||
DEFAULT_GL_TEXTURE_EXT,
|
||||
DEFAULT_GL_TEXTURE_MAX
|
||||
};
|
||||
|
||||
|
|
@ -146,7 +148,7 @@ struct Texture {
|
|||
RID self;
|
||||
|
||||
bool is_proxy = false;
|
||||
bool is_external = false;
|
||||
bool is_from_native_handle = false;
|
||||
bool is_render_target = false;
|
||||
|
||||
RID proxy_to;
|
||||
|
|
@ -209,7 +211,7 @@ struct Texture {
|
|||
void copy_from(const Texture &o) {
|
||||
proxy_to = o.proxy_to;
|
||||
is_proxy = o.is_proxy;
|
||||
is_external = o.is_external;
|
||||
is_from_native_handle = o.is_from_native_handle;
|
||||
width = o.width;
|
||||
height = o.height;
|
||||
alloc_width = o.alloc_width;
|
||||
|
|
@ -370,6 +372,8 @@ struct RenderTarget {
|
|||
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
bool reattach_textures = false;
|
||||
|
||||
Rect2i render_region;
|
||||
|
||||
struct RTOverridden {
|
||||
bool is_overridden = false;
|
||||
RID color;
|
||||
|
|
@ -476,8 +480,8 @@ public:
|
|||
|
||||
/* Canvas Texture API */
|
||||
|
||||
CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
|
||||
bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
|
||||
CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }
|
||||
bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }
|
||||
|
||||
virtual RID canvas_texture_allocate() override;
|
||||
virtual void canvas_texture_initialize(RID p_rid) override;
|
||||
|
|
@ -497,29 +501,34 @@ public:
|
|||
return texture_owner.get_or_null(texture->proxy_to);
|
||||
}
|
||||
return texture;
|
||||
};
|
||||
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
|
||||
}
|
||||
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }
|
||||
|
||||
void texture_2d_initialize_from_texture(RID p_texture, Texture &p_tex) {
|
||||
texture_owner.initialize_rid(p_texture, p_tex);
|
||||
}
|
||||
|
||||
virtual bool can_create_resources_async() const override;
|
||||
|
||||
virtual RID texture_allocate() override;
|
||||
virtual void texture_free(RID p_rid) override;
|
||||
|
||||
virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
|
||||
virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
|
||||
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
|
||||
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
|
||||
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
|
||||
|
||||
RID texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY);
|
||||
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
|
||||
|
||||
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
|
||||
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
|
||||
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
|
||||
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
|
||||
|
||||
Ref<Image> texture_2d_placeholder;
|
||||
Vector<Ref<Image>> texture_2d_array_placeholder;
|
||||
Vector<Ref<Image>> cubemap_placeholder;
|
||||
Vector<Ref<Image>> texture_3d_placeholder;
|
||||
|
||||
//these two APIs can be used together or in combination with the others.
|
||||
virtual void texture_2d_placeholder_initialize(RID p_texture) override;
|
||||
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
|
||||
|
|
@ -553,6 +562,7 @@ public:
|
|||
void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
|
||||
virtual Image::Format texture_get_format(RID p_texture) const override;
|
||||
uint32_t texture_get_texid(RID p_texture) const;
|
||||
Vector3i texture_get_size(RID p_texture) const;
|
||||
uint32_t texture_get_width(RID p_texture) const;
|
||||
uint32_t texture_get_height(RID p_texture) const;
|
||||
uint32_t texture_get_depth(RID p_texture) const;
|
||||
|
|
@ -581,7 +591,7 @@ public:
|
|||
|
||||
virtual RID decal_allocate() override;
|
||||
virtual void decal_initialize(RID p_rid) override;
|
||||
virtual void decal_free(RID p_rid) override{};
|
||||
virtual void decal_free(RID p_rid) override {}
|
||||
|
||||
virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override;
|
||||
virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
|
||||
|
|
@ -610,8 +620,8 @@ public:
|
|||
|
||||
static GLuint system_fbo;
|
||||
|
||||
RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
|
||||
bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
|
||||
RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); }
|
||||
bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); }
|
||||
|
||||
void check_backbuffer(RenderTarget *rt, const bool uses_screen_texture, const bool uses_depth_texture);
|
||||
|
||||
|
|
@ -677,13 +687,20 @@ public:
|
|||
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
|
||||
virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
|
||||
|
||||
virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override;
|
||||
virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override;
|
||||
virtual RID render_target_get_override_color(RID p_render_target) const override;
|
||||
virtual RID render_target_get_override_depth(RID p_render_target) const override;
|
||||
virtual RID render_target_get_override_velocity(RID p_render_target) const override;
|
||||
virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); }
|
||||
|
||||
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) override;
|
||||
virtual Rect2i render_target_get_render_region(RID p_render_target) const override;
|
||||
|
||||
virtual RID render_target_get_texture(RID p_render_target) override;
|
||||
|
||||
virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {}
|
||||
virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(); }
|
||||
|
||||
void bind_framebuffer(GLuint framebuffer) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,6 @@
|
|||
#include "particles_storage.h"
|
||||
#include "texture_storage.h"
|
||||
|
||||
#include "servers/rendering/rendering_server_globals.h"
|
||||
|
||||
using namespace GLES3;
|
||||
|
||||
Utilities *Utilities::singleton = nullptr;
|
||||
|
|
@ -467,4 +465,16 @@ Size2i Utilities::get_maximum_viewport_size() const {
|
|||
return Size2i(config->max_viewport_size[0], config->max_viewport_size[1]);
|
||||
}
|
||||
|
||||
uint32_t Utilities::get_maximum_shader_varyings() const {
|
||||
Config *config = Config::get_singleton();
|
||||
ERR_FAIL_NULL_V(config, 31);
|
||||
return config->max_shader_varyings;
|
||||
}
|
||||
|
||||
uint64_t Utilities::get_maximum_uniform_buffer_size() const {
|
||||
Config *config = Config::get_singleton();
|
||||
ERR_FAIL_NULL_V(config, 65536);
|
||||
return uint64_t(config->max_uniform_buffer_size);
|
||||
}
|
||||
|
||||
#endif // GLES3_ENABLED
|
||||
|
|
|
|||
|
|
@ -165,8 +165,8 @@ public:
|
|||
|
||||
/* VISIBILITY NOTIFIER */
|
||||
|
||||
VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); };
|
||||
bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); };
|
||||
VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }
|
||||
bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }
|
||||
|
||||
virtual RID visibility_notifier_allocate() override;
|
||||
virtual void visibility_notifier_initialize(RID p_notifier) override;
|
||||
|
|
@ -226,6 +226,8 @@ public:
|
|||
virtual String get_video_adapter_api_version() const override;
|
||||
|
||||
virtual Size2i get_maximum_viewport_size() const override;
|
||||
virtual uint32_t get_maximum_shader_varyings() const override;
|
||||
virtual uint64_t get_maximum_uniform_buffer_size() const override;
|
||||
};
|
||||
|
||||
} // namespace GLES3
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue