diff --git a/SConstruct b/SConstruct
index f96cd93fdf..6713b75fc2 100644
--- a/SConstruct
+++ b/SConstruct
@@ -497,8 +497,7 @@ if selected_platform in platform_list:
if not env['verbose']:
methods.no_verbose(sys, env)
- if (not env["platform"] == "server"): # FIXME: detect GLES3
- env.Append(BUILDERS = { 'GLES3_GLSL' : env.Builder(action=run_in_subprocess(gles_builders.build_gles3_headers), suffix='glsl.gen.h', src_suffix='.glsl')})
+ if (not env["platform"] == "server"):
env.Append(BUILDERS = { 'GLES2_GLSL' : env.Builder(action=run_in_subprocess(gles_builders.build_gles2_headers), suffix='glsl.gen.h', src_suffix='.glsl')})
env.Append(BUILDERS = { 'RD_GLSL' : env.Builder(action=run_in_subprocess(gles_builders.build_rd_headers), suffix='glsl.gen.h', src_suffix='.glsl')})
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 1dc48a95a0..5b25300dbd 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -1410,7 +1410,7 @@ void _OS::_bind_methods() {
ADD_PROPERTY_DEFAULT("window_size", Vector2());
BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES2);
- BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES3);
+ BIND_ENUM_CONSTANT(VIDEO_DRIVER_VULKAN);
BIND_ENUM_CONSTANT(DAY_SUNDAY);
BIND_ENUM_CONSTANT(DAY_MONDAY);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 015bcd965e..22cb4a3828 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -104,7 +104,6 @@ protected:
public:
enum VideoDriver {
- VIDEO_DRIVER_GLES3,
VIDEO_DRIVER_GLES2,
VIDEO_DRIVER_VULKAN,
};
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index f0730a0f58..46a96020d0 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -534,7 +534,7 @@
Set [code]ALBEDO[/code] to the per-vertex color specified in the mesh.
- Vertex color is in sRGB space and needs to be converted to linear. Only applies in the GLES3 renderer.
+ Vertex color is in sRGB space and needs to be converted to linear. Only applies in the Vulkan renderer.
Uses point size to alter the size of primitive points. Also changes the albedo texture lookup to use [code]POINT_COORD[/code] instead of [code]UV[/code].
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 5529251b5a..7335ff5a2e 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -295,9 +295,6 @@
-
- Gray color.
-
Alice blue color.
@@ -448,6 +445,9 @@
Goldenrod color.
+
+ Gray color.
+
Green color.
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 1847954b67..5fd0da7452 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -619,7 +619,7 @@
-
+
@@ -672,7 +672,7 @@
-
+
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index e0f73df1bf..b3b77b0b26 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -973,11 +973,11 @@
-
+
The GLES2 rendering backend. It uses OpenGL ES 2.0 on mobile devices, OpenGL 2.1 on desktop platforms and WebGL 1.0 on the web.
-
- The GLES3 rendering backend. It uses OpenGL ES 3.0 on mobile devices, OpenGL 3.3 on desktop platforms and WebGL 2.0 on the web.
+
+ The Vulkan rendering backend.
Sunday.
diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml
index e992f25836..a7bf947011 100644
--- a/doc/classes/Performance.xml
+++ b/doc/classes/Performance.xml
@@ -89,7 +89,7 @@
The amount of vertex memory used.
- Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0.
+ Unimplemented in the GLES2 rendering backend, always returns 0.
Number of active [RigidBody2D] nodes in the game.
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 517c68221e..53b6aa798f 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -972,7 +972,7 @@
Some NVIDIA GPU drivers have a bug which produces flickering issues for the [code]draw_rect[/code] method, especially as used in [TileMap]. Refer to [url=https://github.com/godotengine/godot/issues/9913]GitHub issue 9913[/url] for details.
- If [code]true[/code], this option enables a "safe" code path for such NVIDIA GPUs at the cost of performance. This option only impacts the GLES2 rendering backend (so the bug stays if you use GLES3), and only desktop platforms.
+ If [code]true[/code], this option enables a "safe" code path for such NVIDIA GPUs at the cost of performance. This option only impacts the GLES2 rendering backend, and only desktop platforms. It is not necessary when using the Vulkan backend.
If [code]true[/code], forces snapping of polygons to pixels in 2D rendering. May help in some pixel art styles.
@@ -990,12 +990,8 @@
Lower-end override for [member rendering/quality/directional_shadow/size] on mobile devices, due to performance concerns or driver support.
- The video driver to use ("GLES2" or "GLES3").
- [b]Note:[/b] The backend in use can be overridden at runtime via the [code]--video-driver[/code] command line argument, or by the [member rendering/quality/driver/fallback_to_gles2] option if the target system does not support GLES3 and falls back to GLES2. In such cases, this property is not updated, so use [method OS.get_current_video_driver] to query it at run-time.
-
-
- If [code]true[/code], allows falling back to the GLES2 driver if the GLES3 driver is not supported.
- [b]Note:[/b] The two video drivers are not drop-in replacements for each other, so a game designed for GLES3 might not work properly when falling back to GLES2. In particular, some features of the GLES3 backend are not available in GLES2. Enabling this setting also means that both ETC and ETC2 VRAM-compressed textures will be exported on Android and iOS, increasing the data pack's size.
+ The video driver to use ("GLES2" or "Vulkan").
+ [b]Note:[/b] The backend in use can be overridden at runtime via the [code]--video-driver[/code] command line argument. In such cases, this property is not updated, so use [method OS.get_current_video_driver] to query it at run-time.
@@ -1101,13 +1097,13 @@
Thread model for rendering. Rendering on a thread can vastly improve performance, but synchronizing to the main thread can cause a bit more jitter.
- If [code]true[/code], the texture importer will import VRAM-compressed textures using the BPTC algorithm. This texture compression algorithm is only supported on desktop platforms, and only when using the GLES3 renderer.
+ If [code]true[/code], the texture importer will import VRAM-compressed textures using the BPTC algorithm. This texture compression algorithm is only supported on desktop platforms, and only when using the Vulkan renderer.
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression algorithm. This algorithm doesn't support alpha channels in textures.
- If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm. This texture compression algorithm is only supported when using the GLES3 renderer.
+ If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm. This texture compression algorithm is only supported when using the Vulkan renderer.
If [code]true[/code], the texture importer will import VRAM-compressed textures using the PowerVR Texture Compression algorithm. This texture compression algorithm is only supported on iOS.
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index f6b24c2391..9de10d12a8 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -3706,7 +3706,7 @@
The amount of draw calls in frame.
- Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0.
+ Unimplemented in the GLES2 rendering backend, always returns 0.
The amount of video memory used, i.e. texture and vertex memory combined.
diff --git a/drivers/SCsub b/drivers/SCsub
index 48befd213c..932014b540 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -24,7 +24,6 @@ SConscript('winmidi/SCsub')
# Graphics drivers
if (env["platform"] != "server"):
-# SConscript('gles3/SCsub')
# SConscript('gles2/SCsub')
SConscript('vulkan/SCsub')
SConscript('gl_context/SCsub')
diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h
index 65e84a1fbe..174cdd8e2e 100644
--- a/drivers/gles2/rasterizer_scene_gles2.h
+++ b/drivers/gles2/rasterizer_scene_gles2.h
@@ -38,19 +38,6 @@
#include "shaders/effect_blur.glsl.gen.h"
#include "shaders/scene.glsl.gen.h"
#include "shaders/tonemap.glsl.gen.h"
-/*
-
-
-#include "drivers/gles3/shaders/exposure.glsl.gen.h"
-#include "drivers/gles3/shaders/resolve.glsl.gen.h"
-#include "drivers/gles3/shaders/scene.glsl.gen.h"
-#include "drivers/gles3/shaders/screen_space_reflection.glsl.gen.h"
-#include "drivers/gles3/shaders/ssao.glsl.gen.h"
-#include "drivers/gles3/shaders/ssao_blur.glsl.gen.h"
-#include "drivers/gles3/shaders/ssao_minify.glsl.gen.h"
-#include "drivers/gles3/shaders/subsurf_scattering.glsl.gen.h"
-
-*/
class RasterizerSceneGLES2 : public RasterizerScene {
public:
@@ -109,103 +96,6 @@ public:
Color default_ambient;
Color default_bg;
- // ResolveShaderGLES3 resolve_shader;
- // ScreenSpaceReflectionShaderGLES3 ssr_shader;
- // EffectBlurShaderGLES3 effect_blur_shader;
- // SubsurfScatteringShaderGLES3 sss_shader;
- // SsaoMinifyShaderGLES3 ssao_minify_shader;
- // SsaoShaderGLES3 ssao_shader;
- // SsaoBlurShaderGLES3 ssao_blur_shader;
- // ExposureShaderGLES3 exposure_shader;
-
- /*
- struct SceneDataUBO {
- //this is a std140 compatible struct. Please read the OpenGL 3.3 Specificaiton spec before doing any changes
- float projection_matrix[16];
- float inv_projection_matrix[16];
- float camera_inverse_matrix[16];
- float camera_matrix[16];
- float ambient_light_color[4];
- float bg_color[4];
- float fog_color_enabled[4];
- float fog_sun_color_amount[4];
-
- float ambient_energy;
- float bg_energy;
- float z_offset;
- float z_slope_scale;
- float shadow_dual_paraboloid_render_zfar;
- float shadow_dual_paraboloid_render_side;
- float viewport_size[2];
- float screen_pixel_size[2];
- float shadow_atlas_pixel_size[2];
- float shadow_directional_pixel_size[2];
-
- float time;
- float z_far;
- float reflection_multiplier;
- float subsurface_scatter_width;
- float ambient_occlusion_affect_light;
-
- uint32_t fog_depth_enabled;
- float fog_depth_begin;
- float fog_depth_curve;
- uint32_t fog_transmit_enabled;
- float fog_transmit_curve;
- uint32_t fog_height_enabled;
- float fog_height_min;
- float fog_height_max;
- float fog_height_curve;
- // make sure this struct is padded to be a multiple of 16 bytes for webgl
-
- } ubo_data;
-
- GLuint scene_ubo;
-
- struct EnvironmentRadianceUBO {
-
- float transform[16];
- float ambient_contribution;
- uint8_t padding[12];
-
- } env_radiance_data;
-
- GLuint env_radiance_ubo;
-
- GLuint sky_array;
-
- GLuint directional_ubo;
-
- GLuint spot_array_ubo;
- GLuint omni_array_ubo;
- GLuint reflection_array_ubo;
-
- GLuint immediate_buffer;
- GLuint immediate_array;
-
- uint32_t ubo_light_size;
- uint8_t *spot_array_tmp;
- uint8_t *omni_array_tmp;
- uint8_t *reflection_array_tmp;
-
- int max_ubo_lights;
- int max_forward_lights_per_object;
- int max_ubo_reflections;
- int max_skeleton_bones;
-
- bool used_contact_shadows;
-
- int spot_light_count;
- int omni_light_count;
- int directional_light_count;
- int reflection_probe_count;
-
- bool used_sss;
- bool using_contact_shadows;
-
- VS::ViewportDebugDraw debug_draw;
- */
-
bool cull_front;
bool cull_disabled;
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 15cfac9f03..e39ef5e7bd 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -99,4 +99,4 @@ public:
ShaderCompilerGLES2();
};
-#endif // SHADERCOMPILERGLES3_H
+#endif // SHADERCOMPILERGLES2_H
diff --git a/drivers/gles3/SCsub b/drivers/gles3/SCsub
deleted file mode 100644
index 2471dd3739..0000000000
--- a/drivers/gles3/SCsub
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-
-Import('env')
-
-env.add_source_files(env.drivers_sources,"*.cpp")
-
-SConscript("shaders/SCsub")
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
deleted file mode 100644
index 0117d2b89b..0000000000
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ /dev/null
@@ -1,2266 +0,0 @@
-/*************************************************************************/
-/* rasterizer_canvas_gles3.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#include "rasterizer_canvas_gles3.h"
-
-#include "core/os/os.h"
-#include "core/project_settings.h"
-#include "rasterizer_scene_gles3.h"
-#include "servers/visual/visual_server_raster.h"
-
-#ifndef GLES_OVER_GL
-#define glClearDepth glClearDepthf
-#endif
-
-static _FORCE_INLINE_ void store_transform2d(const Transform2D &p_mtx, float *p_array) {
-
- p_array[0] = p_mtx.elements[0][0];
- p_array[1] = p_mtx.elements[0][1];
- p_array[2] = 0;
- p_array[3] = 0;
- p_array[4] = p_mtx.elements[1][0];
- p_array[5] = p_mtx.elements[1][1];
- p_array[6] = 0;
- p_array[7] = 0;
- p_array[8] = 0;
- p_array[9] = 0;
- p_array[10] = 1;
- p_array[11] = 0;
- p_array[12] = p_mtx.elements[2][0];
- p_array[13] = p_mtx.elements[2][1];
- p_array[14] = 0;
- p_array[15] = 1;
-}
-
-static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.elements[0][0];
- p_array[1] = p_mtx.basis.elements[1][0];
- p_array[2] = p_mtx.basis.elements[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.basis.elements[0][1];
- p_array[5] = p_mtx.basis.elements[1][1];
- p_array[6] = p_mtx.basis.elements[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.basis.elements[0][2];
- p_array[9] = p_mtx.basis.elements[1][2];
- p_array[10] = p_mtx.basis.elements[2][2];
- p_array[11] = 0;
- p_array[12] = p_mtx.origin.x;
- p_array[13] = p_mtx.origin.y;
- p_array[14] = p_mtx.origin.z;
- p_array[15] = 1;
-}
-
-static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
-
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
- }
- }
-}
-
-RID RasterizerCanvasGLES3::light_internal_create() {
-
- LightInternal *li = memnew(LightInternal);
-
- glGenBuffers(1, &li->ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, li->ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInternal::UBOData), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- return light_internal_owner.make_rid(li);
-}
-
-void RasterizerCanvasGLES3::light_internal_update(RID p_rid, Light *p_light) {
-
- LightInternal *li = light_internal_owner.getornull(p_rid);
- ERR_FAIL_COND(!li);
-
- store_transform2d(p_light->light_shader_xform, li->ubo_data.light_matrix);
- store_transform2d(p_light->xform_cache.affine_inverse(), li->ubo_data.local_matrix);
- store_camera(p_light->shadow_matrix_cache, li->ubo_data.shadow_matrix);
-
- for (int i = 0; i < 4; i++) {
-
- li->ubo_data.color[i] = p_light->color[i] * p_light->energy;
- li->ubo_data.shadow_color[i] = p_light->shadow_color[i];
- }
-
- li->ubo_data.light_pos[0] = p_light->light_shader_pos.x;
- li->ubo_data.light_pos[1] = p_light->light_shader_pos.y;
- li->ubo_data.shadowpixel_size = (1.0 / p_light->shadow_buffer_size) * (1.0 + p_light->shadow_smooth);
- li->ubo_data.light_outside_alpha = p_light->mode == VS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0;
- li->ubo_data.light_height = p_light->height;
- if (p_light->radius_cache == 0)
- li->ubo_data.shadow_gradient = 0;
- else
- li->ubo_data.shadow_gradient = p_light->shadow_gradient_length / (p_light->radius_cache * 1.1);
-
- li->ubo_data.shadow_distance_mult = (p_light->radius_cache * 1.1);
-
- glBindBuffer(GL_UNIFORM_BUFFER, li->ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(LightInternal::UBOData), &li->ubo_data, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-}
-
-void RasterizerCanvasGLES3::light_internal_free(RID p_rid) {
-
- LightInternal *li = light_internal_owner.getornull(p_rid);
- ERR_FAIL_COND(!li);
-
- glDeleteBuffers(1, &li->ubo);
- light_internal_owner.free(p_rid);
- memdelete(li);
-}
-
-void RasterizerCanvasGLES3::canvas_begin() {
-
- if (storage->frame.current_rt && storage->frame.clear_request) {
- // a clear request may be pending, so do it
- bool transparent = storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT];
-
- glClearColor(storage->frame.clear_request_color.r,
- storage->frame.clear_request_color.g,
- storage->frame.clear_request_color.b,
- transparent ? storage->frame.clear_request_color.a : 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
- storage->frame.clear_request = false;
- glColorMask(1, 1, 1, transparent ? 1 : 0);
- }
-
- reset_canvas();
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_TEXTURE_RECT, true);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false);
-
- state.canvas_shader.set_custom_shader(0);
- state.canvas_shader.bind();
- state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, Color(1, 1, 1, 1));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, Transform2D());
- state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, Transform2D());
- if (storage->frame.current_rt) {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
- } else {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0));
- }
-
- //state.canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,state.vp);
- //state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Transform());
- //state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Transform());
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_item_ubo);
- glBindVertexArray(data.canvas_quad_array);
- state.using_texture_rect = true;
- state.using_ninepatch = false;
- state.using_skeleton = false;
-}
-
-void RasterizerCanvasGLES3::canvas_end() {
-
- glBindVertexArray(0);
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
- glColorMask(1, 1, 1, 1);
-
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
-
- state.using_texture_rect = false;
- state.using_ninepatch = false;
-}
-
-RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force) {
-
- RasterizerStorageGLES3::Texture *tex_return = NULL;
-
- if (p_texture == state.current_tex && !p_force) {
- tex_return = state.current_tex_ptr;
- } else if (p_texture.is_valid()) {
-
- RasterizerStorageGLES3::Texture *texture = storage->texture_owner.getornull(p_texture);
-
- if (!texture) {
- state.current_tex = RID();
- state.current_tex_ptr = NULL;
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
-
- } else {
-
- if (texture->redraw_if_visible) { //check before proxy, because this is usually used with proxies
- VisualServerRaster::redraw_request();
- }
-
- texture = texture->get_ptr();
-
- if (texture->render_target)
- texture->render_target->used_in_frame = true;
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture->tex_id);
- state.current_tex = p_texture;
- state.current_tex_ptr = texture;
-
- tex_return = texture;
- }
-
- } else {
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
- state.current_tex = RID();
- state.current_tex_ptr = NULL;
- }
-
- if (p_normal_map == state.current_normal && !p_force) {
- //do none
- state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, state.current_normal.is_valid());
-
- } else if (p_normal_map.is_valid()) {
-
- RasterizerStorageGLES3::Texture *normal_map = storage->texture_owner.getornull(p_normal_map);
-
- if (!normal_map) {
- state.current_normal = RID();
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, false);
-
- } else {
-
- if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies
- VisualServerRaster::redraw_request();
- }
-
- normal_map = normal_map->get_ptr();
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
- state.current_normal = p_normal_map;
- state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, true);
- }
-
- } else {
-
- state.current_normal = RID();
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, false);
- }
-
- return tex_return;
-}
-
-void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepatch) {
-
- if (state.using_texture_rect == p_enable && state.using_ninepatch == p_ninepatch)
- return;
-
- if (p_enable) {
- glBindVertexArray(data.canvas_quad_array);
-
- } else {
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, p_ninepatch && p_enable);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_TEXTURE_RECT, p_enable);
- state.canvas_shader.bind();
- state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix);
- if (state.using_skeleton) {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse);
- }
- if (storage->frame.current_rt) {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
- } else {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0));
- }
- state.using_texture_rect = p_enable;
- state.using_ninepatch = p_ninepatch;
-}
-
-void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights) {
-
- glBindVertexArray(data.polygon_buffer_pointer_array);
- glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
-
-#ifndef GLES_OVER_GL
- // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
- glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
-#endif
-
- uint32_t buffer_ofs = 0;
-
- //vertex
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices);
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Vector2) * p_vertex_count;
- //color
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
-#endif
-
- if (p_singlecolor) {
- glDisableVertexAttribArray(VS::ARRAY_COLOR);
- Color m = *p_colors;
- glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
- } else if (!p_colors) {
- glDisableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
- } else {
-
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
- glEnableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Color) * p_vertex_count;
- }
-
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
-#endif
-
- if (p_uvs) {
-
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Vector2) * p_vertex_count;
-
- } else {
- glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
- }
-
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
-#endif
-
- if (p_bones && p_weights) {
-
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones);
- glEnableVertexAttribArray(VS::ARRAY_BONES);
- //glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs);
- glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(int) * 4 * p_vertex_count;
-
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights);
- glEnableVertexAttribArray(VS::ARRAY_WEIGHTS);
- glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, false, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(float) * 4 * p_vertex_count;
-
- } else if (state.using_skeleton) {
- glVertexAttribI4ui(VS::ARRAY_BONES, 0, 0, 0, 0);
- glVertexAttrib4f(VS::ARRAY_WEIGHTS, 0, 0, 0, 0);
- }
-
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
-#endif
-
- //bind the indices buffer.
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
-#ifndef GLES_OVER_GL
- // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW);
-#endif
- glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices);
-
- //draw the triangles.
- glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0);
-
- storage->frame.canvas_draw_commands++;
-
- if (p_bones && p_weights) {
- //not used so often, so disable when used
- glDisableVertexAttribArray(VS::ARRAY_BONES);
- glDisableVertexAttribArray(VS::ARRAY_WEIGHTS);
- }
-
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
-
-void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) {
-
- glBindVertexArray(data.polygon_buffer_pointer_array);
- glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
-
-#ifndef GLES_OVER_GL
- // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
- glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
-#endif
-
- uint32_t buffer_ofs = 0;
-
- //vertex
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices);
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Vector2) * p_vertex_count;
- //color
-
- if (p_singlecolor) {
- glDisableVertexAttribArray(VS::ARRAY_COLOR);
- Color m = *p_colors;
- glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
- } else if (!p_colors) {
- glDisableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
- } else {
-
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
- glEnableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Color) * p_vertex_count;
- }
-
- if (p_uvs) {
-
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Vector2) * p_vertex_count;
-
- } else {
- glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
- }
-
- glDrawArrays(p_primitive, 0, p_vertex_count);
-
- storage->frame.canvas_draw_commands++;
-
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
-
-void RasterizerCanvasGLES3::_draw_generic_indices(GLuint p_primitive, const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) {
-
- glBindVertexArray(data.polygon_buffer_pointer_array);
- glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
-
-#ifndef GLES_OVER_GL
- // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
- glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
-#endif
-
- uint32_t buffer_ofs = 0;
-
- //vertex
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices);
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Vector2) * p_vertex_count;
- //color
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
-#endif
-
- if (p_singlecolor) {
- glDisableVertexAttribArray(VS::ARRAY_COLOR);
- Color m = *p_colors;
- glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
- } else if (!p_colors) {
- glDisableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
- } else {
-
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
- glEnableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Color) * p_vertex_count;
- }
-
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
-#endif
-
- if (p_uvs) {
-
- glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
- buffer_ofs += sizeof(Vector2) * p_vertex_count;
-
- } else {
- glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
- }
-
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size);
-#endif
-
- //bind the indices buffer.
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
-#ifndef GLES_OVER_GL
- // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW);
-#endif
- glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices);
-
- //draw the triangles.
- glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0);
-
- storage->frame.canvas_draw_commands++;
-
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
-
-void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) {
-
- static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN };
-
- //#define GLES_USE_PRIMITIVE_BUFFER
-
- int version = 0;
- int color_ofs = 0;
- int uv_ofs = 0;
- int stride = 2;
-
- if (p_colors) { //color
- version |= 1;
- color_ofs = stride;
- stride += 4;
- }
-
- if (p_uvs) { //uv
- version |= 2;
- uv_ofs = stride;
- stride += 2;
- }
-
- float b[(2 + 2 + 4) * 4];
-
- for (int i = 0; i < p_points; i++) {
- b[stride * i + 0] = p_vertices[i].x;
- b[stride * i + 1] = p_vertices[i].y;
- }
-
- if (p_colors) {
-
- for (int i = 0; i < p_points; i++) {
- b[stride * i + color_ofs + 0] = p_colors[i].r;
- b[stride * i + color_ofs + 1] = p_colors[i].g;
- b[stride * i + color_ofs + 2] = p_colors[i].b;
- b[stride * i + color_ofs + 3] = p_colors[i].a;
- }
- }
-
- if (p_uvs) {
-
- for (int i = 0; i < p_points; i++) {
- b[stride * i + uv_ofs + 0] = p_uvs[i].x;
- b[stride * i + uv_ofs + 1] = p_uvs[i].y;
- }
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
-#ifndef GLES_OVER_GL
- // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
- glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW);
-#endif
- //TODO the below call may need to be replaced with: glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), &b[0]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4, &b[0]);
- glBindVertexArray(data.polygon_buffer_quad_arrays[version]);
- glDrawArrays(prim[p_points], 0, p_points);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- storage->frame.canvas_draw_commands++;
-}
-
-static const GLenum gl_primitive[] = {
- GL_POINTS,
- GL_LINES,
- GL_LINE_STRIP,
- GL_LINE_LOOP,
- GL_TRIANGLES,
- GL_TRIANGLE_STRIP,
- GL_TRIANGLE_FAN
-};
-
-void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip) {
-
- int cc = p_item->commands.size();
- Item::Command **commands = p_item->commands.ptrw();
-
- for (int i = 0; i < cc; i++) {
-
- Item::Command *c = commands[i];
-
- switch (c->type) {
- case Item::Command::TYPE_LINE: {
-
- Item::CommandLine *line = static_cast(c);
- _set_texture_rect_mode(false);
-
- _bind_canvas_texture(RID(), RID());
-
- glVertexAttrib4f(VS::ARRAY_COLOR, line->color.r, line->color.g, line->color.b, line->color.a);
-
- if (line->width <= 1) {
- Vector2 verts[2] = {
- Vector2(line->from.x, line->from.y),
- Vector2(line->to.x, line->to.y)
- };
-
-#ifdef GLES_OVER_GL
- if (line->antialiased)
- glEnable(GL_LINE_SMOOTH);
-#endif
- //glLineWidth(line->width);
- _draw_gui_primitive(2, verts, NULL, NULL);
-
-#ifdef GLES_OVER_GL
- if (line->antialiased)
- glDisable(GL_LINE_SMOOTH);
-#endif
- } else {
- //thicker line
-
- Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5;
-
- Vector2 verts[4] = {
- line->from - t,
- line->from + t,
- line->to + t,
- line->to - t,
- };
-
- //glLineWidth(line->width);
- _draw_gui_primitive(4, verts, NULL, NULL);
-#ifdef GLES_OVER_GL
- if (line->antialiased) {
- glEnable(GL_LINE_SMOOTH);
- for (int j = 0; j < 4; j++) {
- Vector2 vertsl[2] = {
- verts[j],
- verts[(j + 1) % 4],
- };
- _draw_gui_primitive(2, vertsl, NULL, NULL);
- }
- glDisable(GL_LINE_SMOOTH);
- }
-#endif
- }
-
- } break;
- case Item::Command::TYPE_POLYLINE: {
-
- Item::CommandPolyLine *pline = static_cast(c);
- _set_texture_rect_mode(false);
-
- _bind_canvas_texture(RID(), RID());
-
- if (pline->triangles.size()) {
-
- _draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1);
-#ifdef GLES_OVER_GL
- glEnable(GL_LINE_SMOOTH);
- if (pline->multiline) {
- //needs to be different
- } else {
- _draw_generic(GL_LINE_LOOP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1);
- }
- glDisable(GL_LINE_SMOOTH);
-#endif
- } else {
-
-#ifdef GLES_OVER_GL
- if (pline->antialiased)
- glEnable(GL_LINE_SMOOTH);
-#endif
-
- if (pline->multiline) {
- int todo = pline->lines.size() / 2;
- int max_per_call = data.polygon_buffer_size / (sizeof(real_t) * 4);
- int offset = 0;
-
- while (todo) {
- int to_draw = MIN(max_per_call, todo);
- _draw_generic(GL_LINES, to_draw * 2, &pline->lines.ptr()[offset], NULL, pline->line_colors.size() == 1 ? pline->line_colors.ptr() : &pline->line_colors.ptr()[offset], pline->line_colors.size() == 1);
- todo -= to_draw;
- offset += to_draw * 2;
- }
-
- } else {
-
- _draw_generic(GL_LINE_STRIP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1);
- }
-
-#ifdef GLES_OVER_GL
- if (pline->antialiased)
- glDisable(GL_LINE_SMOOTH);
-#endif
- }
-
- } break;
- case Item::Command::TYPE_RECT: {
-
- Item::CommandRect *rect = static_cast(c);
-
- _set_texture_rect_mode(true);
-
- //set color
- glVertexAttrib4f(VS::ARRAY_COLOR, rect->modulate.r, rect->modulate.g, rect->modulate.b, rect->modulate.a);
-
- RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(rect->texture, rect->normal_map);
-
- if (texture) {
-
- bool untile = false;
-
- if (rect->flags & CANVAS_RECT_TILE && !(texture->flags & VS::TEXTURE_FLAG_REPEAT)) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- untile = true;
- }
-
- Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- Rect2 src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * texpixel_size, rect->source.size * texpixel_size) : Rect2(0, 0, 1, 1);
- Rect2 dst_rect = Rect2(rect->rect.position, rect->rect.size);
-
- if (dst_rect.size.width < 0) {
- dst_rect.position.x += dst_rect.size.width;
- dst_rect.size.width *= -1;
- }
- if (dst_rect.size.height < 0) {
- dst_rect.position.y += dst_rect.size.height;
- dst_rect.size.height *= -1;
- }
-
- if (rect->flags & CANVAS_RECT_FLIP_H) {
- src_rect.size.x *= -1;
- }
-
- if (rect->flags & CANVAS_RECT_FLIP_V) {
- src_rect.size.y *= -1;
- }
-
- if (rect->flags & CANVAS_RECT_TRANSPOSE) {
- dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform
- }
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, rect->flags & CANVAS_RECT_CLIP_UV);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- if (untile) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
-
- } else {
- Rect2 dst_rect = Rect2(rect->rect.position, rect->rect.size);
-
- if (dst_rect.size.width < 0) {
- dst_rect.position.x += dst_rect.size.width;
- dst_rect.size.width *= -1;
- }
- if (dst_rect.size.height < 0) {
- dst_rect.position.y += dst_rect.size.height;
- dst_rect.size.height *= -1;
- }
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
-
- storage->frame.canvas_draw_commands++;
-
- } break;
-
- case Item::Command::TYPE_NINEPATCH: {
-
- Item::CommandNinePatch *np = static_cast(c);
-
- _set_texture_rect_mode(true, true);
-
- glVertexAttrib4f(VS::ARRAY_COLOR, np->color.r, np->color.g, np->color.b, np->color.a);
-
- RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(np->texture, np->normal_map);
-
- Size2 texpixel_size;
-
- if (!texture) {
-
- texpixel_size = Size2(1, 1);
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1));
-
- } else {
-
- if (np->source != Rect2()) {
- texpixel_size = Size2(1.0 / np->source.size.width, 1.0 / np->source.size.height);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(np->source.position.x / texture->width, np->source.position.y / texture->height, np->source.size.x / texture->width, np->source.size.y / texture->height));
- } else {
- texpixel_size = Size2(1.0 / texture->width, 1.0 / texture->height);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(0, 0, 1, 1));
- }
- }
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_REPEAT_H, int(np->axis_x));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_REPEAT_V, int(np->axis_y));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_DRAW_CENTER, np->draw_center);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::NP_MARGINS, Color(np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y));
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- storage->frame.canvas_draw_commands++;
- } break;
-
- case Item::Command::TYPE_PRIMITIVE: {
-
- Item::CommandPrimitive *primitive = static_cast(c);
- _set_texture_rect_mode(false);
-
- ERR_CONTINUE(primitive->points.size() < 1);
-
- RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(primitive->texture, primitive->normal_map);
-
- if (texture) {
- Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
- }
- if (primitive->colors.size() == 1 && primitive->points.size() > 1) {
-
- Color col = primitive->colors[0];
- glVertexAttrib4f(VS::ARRAY_COLOR, col.r, col.g, col.b, col.a);
-
- } else if (primitive->colors.empty()) {
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
- }
-
- _draw_gui_primitive(primitive->points.size(), primitive->points.ptr(), primitive->colors.ptr(), primitive->uvs.ptr());
-
- } break;
- case Item::Command::TYPE_POLYGON: {
-
- Item::CommandPolygon *polygon = static_cast(c);
- _set_texture_rect_mode(false);
-
- RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map);
-
- if (texture) {
- Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
- }
-
- _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1, polygon->bones.ptr(), polygon->weights.ptr());
-#ifdef GLES_OVER_GL
- if (polygon->antialiased) {
- glEnable(GL_LINE_SMOOTH);
- // FIXME: Removed during Vulkan rebase.
- //if (polygon->antialiasing_use_indices) {
- // _draw_generic_indices(GL_LINE_STRIP, polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
- //} else
- _draw_generic(GL_LINE_LOOP, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
-
- glDisable(GL_LINE_SMOOTH);
- }
-#endif
-
- } break;
- case Item::Command::TYPE_MESH: {
-
- Item::CommandMesh *mesh = static_cast(c);
- _set_texture_rect_mode(false);
-
- RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mesh->texture, mesh->normal_map);
-
- if (texture) {
- Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
- }
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * mesh->transform);
-
- RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh);
- if (mesh_data) {
-
- for (int j = 0; j < mesh_data->surfaces.size(); j++) {
- RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j];
- // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing
- glBindVertexArray(s->array_id);
-
- glVertexAttrib4f(VS::ARRAY_COLOR, mesh->modulate.r, mesh->modulate.g, mesh->modulate.b, mesh->modulate.a);
-
- if (s->index_array_len) {
- glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0);
- } else {
- glDrawArrays(gl_primitive[s->primitive], 0, s->array_len);
- }
-
- glBindVertexArray(0);
- }
- }
- state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform);
-
- } break;
- case Item::Command::TYPE_MULTIMESH: {
-
- Item::CommandMultiMesh *mmesh = static_cast(c);
-
- RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh);
-
- if (!multi_mesh)
- break;
-
- RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh);
-
- if (!mesh_data)
- break;
-
- RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map);
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != VS::MULTIMESH_CUSTOM_DATA_NONE);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true);
- //reset shader and force rebind
- state.using_texture_rect = true;
- _set_texture_rect_mode(false);
-
- if (texture) {
- Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
- }
-
- int amount = MIN(multi_mesh->size, multi_mesh->visible_instances);
-
- if (amount == -1) {
- amount = multi_mesh->size;
- }
-
- for (int j = 0; j < mesh_data->surfaces.size(); j++) {
- RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j];
- // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing
- glBindVertexArray(s->instancing_array_id);
-
- glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer
-
- int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4;
- glEnableVertexAttribArray(8);
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0));
- glVertexAttribDivisor(8, 1);
- glEnableVertexAttribArray(9);
- glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4));
- glVertexAttribDivisor(9, 1);
-
- int color_ofs;
-
- if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) {
- glEnableVertexAttribArray(10);
- glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4));
- glVertexAttribDivisor(10, 1);
- color_ofs = 12 * 4;
- } else {
- glDisableVertexAttribArray(10);
- glVertexAttrib4f(10, 0, 0, 1, 0);
- color_ofs = 8 * 4;
- }
-
- int custom_data_ofs = color_ofs;
-
- switch (multi_mesh->color_format) {
-
- case VS::MULTIMESH_COLOR_MAX:
- case VS::MULTIMESH_COLOR_NONE: {
- glDisableVertexAttribArray(11);
- glVertexAttrib4f(11, 1, 1, 1, 1);
- } break;
- case VS::MULTIMESH_COLOR_8BIT: {
- glEnableVertexAttribArray(11);
- glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs));
- glVertexAttribDivisor(11, 1);
- custom_data_ofs += 4;
-
- } break;
- case VS::MULTIMESH_COLOR_FLOAT: {
- glEnableVertexAttribArray(11);
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs));
- glVertexAttribDivisor(11, 1);
- custom_data_ofs += 4 * 4;
- } break;
- }
-
- switch (multi_mesh->custom_data_format) {
-
- case VS::MULTIMESH_CUSTOM_DATA_MAX:
- case VS::MULTIMESH_CUSTOM_DATA_NONE: {
- glDisableVertexAttribArray(12);
- glVertexAttrib4f(12, 1, 1, 1, 1);
- } break;
- case VS::MULTIMESH_CUSTOM_DATA_8BIT: {
- glEnableVertexAttribArray(12);
- glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs));
- glVertexAttribDivisor(12, 1);
-
- } break;
- case VS::MULTIMESH_CUSTOM_DATA_FLOAT: {
- glEnableVertexAttribArray(12);
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs));
- glVertexAttribDivisor(12, 1);
- } break;
- }
-
- if (s->index_array_len) {
- glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);
- } else {
- glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount);
- }
-
- glBindVertexArray(0);
- }
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false);
- state.using_texture_rect = true;
- _set_texture_rect_mode(false);
-
- } break;
- case Item::Command::TYPE_PARTICLES: {
-
- Item::CommandParticles *particles_cmd = static_cast(c);
-
- RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(particles_cmd->particles);
- if (!particles)
- break;
-
- if (particles->inactive && !particles->emitting)
- break;
-
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white
-
- VisualServerRaster::redraw_request();
-
- storage->particles_request_process(particles_cmd->particles);
- //enable instancing
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, true);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, true);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true);
- //reset shader and force rebind
- state.using_texture_rect = true;
- _set_texture_rect_mode(false);
-
- RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(particles_cmd->texture, particles_cmd->normal_map);
-
- if (texture) {
- Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
- } else {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0));
- }
-
- if (!particles->use_local_coords) {
-
- Transform2D inv_xf;
- inv_xf.set_axis(0, Vector2(particles->emission_transform.basis.get_axis(0).x, particles->emission_transform.basis.get_axis(0).y));
- inv_xf.set_axis(1, Vector2(particles->emission_transform.basis.get_axis(1).x, particles->emission_transform.basis.get_axis(1).y));
- inv_xf.set_origin(Vector2(particles->emission_transform.get_origin().x, particles->emission_transform.get_origin().y));
- inv_xf.affine_invert();
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf);
- }
-
- glBindVertexArray(data.particle_quad_array); //use particle quad array
- glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //bind particle buffer
-
- int stride = sizeof(float) * 4 * 6;
-
- int amount = particles->amount;
-
- if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) {
-
- glEnableVertexAttribArray(8); //xform x
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3));
- glVertexAttribDivisor(8, 1);
- glEnableVertexAttribArray(9); //xform y
- glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4));
- glVertexAttribDivisor(9, 1);
- glEnableVertexAttribArray(10); //xform z
- glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5));
- glVertexAttribDivisor(10, 1);
- glEnableVertexAttribArray(11); //color
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL);
- glVertexAttribDivisor(11, 1);
- glEnableVertexAttribArray(12); //custom
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2));
- glVertexAttribDivisor(12, 1);
-
- glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount);
- } else {
- //split
- int split = int(Math::ceil(particles->phase * particles->amount));
-
- if (amount - split > 0) {
- glEnableVertexAttribArray(8); //xform x
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3));
- glVertexAttribDivisor(8, 1);
- glEnableVertexAttribArray(9); //xform y
- glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4));
- glVertexAttribDivisor(9, 1);
- glEnableVertexAttribArray(10); //xform z
- glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5));
- glVertexAttribDivisor(10, 1);
- glEnableVertexAttribArray(11); //color
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0));
- glVertexAttribDivisor(11, 1);
- glEnableVertexAttribArray(12); //custom
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2));
- glVertexAttribDivisor(12, 1);
-
- glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount - split);
- }
-
- if (split > 0) {
- glEnableVertexAttribArray(8); //xform x
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3));
- glVertexAttribDivisor(8, 1);
- glEnableVertexAttribArray(9); //xform y
- glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4));
- glVertexAttribDivisor(9, 1);
- glEnableVertexAttribArray(10); //xform z
- glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5));
- glVertexAttribDivisor(10, 1);
- glEnableVertexAttribArray(11); //color
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL);
- glVertexAttribDivisor(11, 1);
- glEnableVertexAttribArray(12); //custom
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2));
- glVertexAttribDivisor(12, 1);
-
- glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, split);
- }
- }
-
- glBindVertexArray(0);
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false);
- state.using_texture_rect = true;
- _set_texture_rect_mode(false);
-
- } break;
- case Item::Command::TYPE_CIRCLE: {
-
- _set_texture_rect_mode(false);
-
- Item::CommandCircle *circle = static_cast(c);
- static const int numpoints = 32;
- Vector2 points[numpoints + 1];
- points[numpoints] = circle->pos;
- int indices[numpoints * 3];
-
- for (int j = 0; j < numpoints; j++) {
-
- points[j] = circle->pos + Vector2(Math::sin(j * Math_PI * 2.0 / numpoints), Math::cos(j * Math_PI * 2.0 / numpoints)) * circle->radius;
- indices[j * 3 + 0] = j;
- indices[j * 3 + 1] = (j + 1) % numpoints;
- indices[j * 3 + 2] = numpoints;
- }
-
- _bind_canvas_texture(RID(), RID());
- _draw_polygon(indices, numpoints * 3, numpoints + 1, points, NULL, &circle->color, true, NULL, NULL);
-
- //_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true);
- //canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1);
- } break;
- case Item::Command::TYPE_TRANSFORM: {
-
- Item::CommandTransform *transform = static_cast(c);
- state.extra_matrix = transform->xform;
- state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix);
-
- } break;
- case Item::Command::TYPE_CLIP_IGNORE: {
-
- Item::CommandClipIgnore *ci = static_cast(c);
- if (current_clip) {
-
- if (ci->ignore != reclip) {
- if (ci->ignore) {
-
- glDisable(GL_SCISSOR_TEST);
- reclip = true;
- } else {
-
- glEnable(GL_SCISSOR_TEST);
- //glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),
- //current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height);
- int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y);
- if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP])
- y = current_clip->final_clip_rect.position.y;
-
- glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y);
-
- reclip = false;
- }
- }
- }
-
- } break;
- }
- }
-}
-
-void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) {
-
- ERR_FAIL_COND_MSG(storage->frame.current_rt->effects.mip_maps[0].sizes.size() == 0, "Can't use screen texture copying in a render target configured without copy buffers.");
-
- glDisable(GL_BLEND);
-
- state.canvas_texscreen_used = true;
- //blur diffuse into effect mipmaps using separatable convolution
- //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
-
- Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height);
-
- Color blur_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y);
-
- if (p_rect != Rect2()) {
-
- scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_BLUR_SECTION, true);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_COPY_SECTION, true);
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
-
- storage->shaders.copy.bind();
- storage->shaders.copy.set_uniform(CopyShaderGLES3::COPY_SECTION, blur_section);
-
- scene_render->_copy_screen();
-
- for (int i = 0; i < storage->frame.current_rt->effects.mip_maps[1].sizes.size(); i++) {
-
- int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width;
- int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height;
- glViewport(0, 0, vp_w, vp_h);
- //horizontal pass
- scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, true);
- scene_render->state.effect_blur_shader.bind();
- scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
- scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo);
-
- scene_render->_copy_screen();
-
- scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, false);
-
- //vertical pass
- scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, true);
- scene_render->state.effect_blur_shader.bind();
- scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
- scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color);
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger
-
- scene_render->_copy_screen();
-
- scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, false);
- }
-
- scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_BLUR_SECTION, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_COPY_SECTION, false);
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front
- glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
-
- // back to canvas, force rebind
- state.using_texture_rect = true;
- _set_texture_rect_mode(false);
-
- _bind_canvas_texture(state.current_tex, state.current_normal, true);
-
- glEnable(GL_BLEND);
-}
-
-void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform) {
-
- Item *current_clip = NULL;
- RasterizerStorageGLES3::Shader *shader_cache = NULL;
-
- bool rebind_shader = true;
-
- glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- state.current_tex = RID();
- state.current_tex_ptr = NULL;
- state.current_normal = RID();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
-
- int last_blend_mode = -1;
-
- RID canvas_last_material;
-
- bool prev_distance_field = false;
- bool prev_use_skeleton = false;
-
- while (p_item_list) {
-
- Item *ci = p_item_list;
-
- if (prev_distance_field != ci->distance_field) {
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, ci->distance_field);
- prev_distance_field = ci->distance_field;
- rebind_shader = true;
- }
-
- if (current_clip != ci->final_clip_owner) {
-
- current_clip = ci->final_clip_owner;
-
- //setup clip
- if (current_clip) {
-
- glEnable(GL_SCISSOR_TEST);
- int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y);
- if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP])
- y = current_clip->final_clip_rect.position.y;
-
- glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y);
-
- } else {
-
- glDisable(GL_SCISSOR_TEST);
- }
- }
-
- if (ci->copy_back_buffer) {
-
- if (ci->copy_back_buffer->full) {
-
- _copy_texscreen(Rect2());
- } else {
- _copy_texscreen(ci->copy_back_buffer->rect);
- }
- }
-
- RasterizerStorageGLES3::Skeleton *skeleton = NULL;
-
- {
- //skeleton handling
- if (ci->skeleton.is_valid() && storage->skeleton_owner.owns(ci->skeleton)) {
- skeleton = storage->skeleton_owner.getornull(ci->skeleton);
- if (!skeleton->use_2d) {
- skeleton = NULL;
- } else {
- state.skeleton_transform = p_transform * skeleton->base_transform_2d;
- state.skeleton_transform_inverse = state.skeleton_transform.affine_inverse();
- }
- }
-
- bool use_skeleton = skeleton != NULL;
- if (prev_use_skeleton != use_skeleton) {
- rebind_shader = true;
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, use_skeleton);
- prev_use_skeleton = use_skeleton;
- }
-
- if (skeleton) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
- glBindTexture(GL_TEXTURE_2D, skeleton->texture);
- state.using_skeleton = true;
- } else {
- state.using_skeleton = false;
- }
- }
-
- //begin rect
- Item *material_owner = ci->material_owner ? ci->material_owner : ci;
-
- RID material = material_owner->material;
-
- if (material != canvas_last_material || rebind_shader) {
-
- RasterizerStorageGLES3::Material *material_ptr = storage->material_owner.getornull(material);
- RasterizerStorageGLES3::Shader *shader_ptr = NULL;
-
- if (material_ptr) {
-
- shader_ptr = material_ptr->shader;
-
- if (shader_ptr && shader_ptr->mode != VS::SHADER_CANVAS_ITEM) {
- shader_ptr = NULL; //do not use non canvasitem shader
- }
- }
-
- if (shader_ptr) {
-
- if (shader_ptr->canvas_item.uses_screen_texture && !state.canvas_texscreen_used) {
- //copy if not copied before
- _copy_texscreen(Rect2());
-
- // blend mode will have been enabled so make sure we disable it again later on
- last_blend_mode = last_blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1;
- }
-
- if (shader_ptr != shader_cache || rebind_shader) {
-
- if (shader_ptr->canvas_item.uses_time) {
- VisualServerRaster::redraw_request();
- }
-
- state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id);
- state.canvas_shader.bind();
- }
-
- if (material_ptr->ubo_id) {
- glBindBufferBase(GL_UNIFORM_BUFFER, 2, material_ptr->ubo_id);
- }
-
- int tc = material_ptr->textures.size();
- RID *textures = material_ptr->textures.ptrw();
- ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw();
-
- for (int i = 0; i < tc; i++) {
-
- glActiveTexture(GL_TEXTURE2 + i);
-
- RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(textures[i]);
- if (!t) {
-
- switch (texture_hints[i]) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
- glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
- glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
- } break;
- default: {
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
- } break;
- }
-
- //check hints
-
- continue;
- }
-
- if (t->redraw_if_visible) { //check before proxy, because this is usually used with proxies
- VisualServerRaster::redraw_request();
- }
-
- t = t->get_ptr();
-
- if (storage->config.srgb_decode_supported && t->using_srgb) {
- //no srgb in 2D
- glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT);
- t->using_srgb = false;
- }
-
- glBindTexture(t->target, t->tex_id);
- }
-
- } else {
- state.canvas_shader.set_custom_shader(0);
- state.canvas_shader.bind();
- }
-
- shader_cache = shader_ptr;
-
- canvas_last_material = material;
- rebind_shader = false;
- }
-
- int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
- if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) {
- blend_mode = RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
- }
- bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || (blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX && blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA));
- bool reclip = false;
-
- if (last_blend_mode != blend_mode) {
- if (last_blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) {
- // re-enable it
- glEnable(GL_BLEND);
- } else if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) {
- // disable it
- glDisable(GL_BLEND);
- }
-
- switch (blend_mode) {
-
- case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED: {
-
- // nothing to do here
-
- } break;
- case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: {
-
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
- }
-
- } break;
- case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_ADD: {
-
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
- } else {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
- }
-
- } break;
- case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_SUB: {
-
- glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
- } else {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
- }
- } break;
- case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MUL: {
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
- } else {
- glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
- }
-
- } break;
- case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA: {
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
- }
-
- } break;
- }
-
- last_blend_mode = blend_mode;
- }
-
- state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(ci->final_modulate.r * p_modulate.r, ci->final_modulate.g * p_modulate.g, ci->final_modulate.b * p_modulate.b, ci->final_modulate.a * p_modulate.a);
-
- state.final_transform = ci->final_transform;
- state.extra_matrix = Transform2D();
-
- if (state.using_skeleton) {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse);
- }
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix);
- if (storage->frame.current_rt) {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
- } else {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0));
- }
- if (unshaded || (state.canvas_item_modulate.a > 0.001 && (!shader_cache || shader_cache->canvas_item.light_mode != RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked))
- _canvas_item_render_commands(ci, current_clip, reclip);
-
- if ((blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) {
-
- Light *light = p_light;
- bool light_used = false;
- VS::CanvasLightMode mode = VS::CANVAS_LIGHT_MODE_ADD;
- state.canvas_item_modulate = ci->final_modulate; // remove the canvas modulate
-
- while (light) {
-
- if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) {
-
- //intersects this light
-
- if (!light_used || mode != light->mode) {
-
- mode = light->mode;
-
- switch (mode) {
-
- case VS::CANVAS_LIGHT_MODE_ADD: {
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-
- } break;
- case VS::CANVAS_LIGHT_MODE_SUB: {
- glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- } break;
- case VS::CANVAS_LIGHT_MODE_MIX:
- case VS::CANVAS_LIGHT_MODE_MASK: {
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- } break;
- }
- }
-
- if (!light_used) {
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, true);
- light_used = true;
- }
-
- bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask & light->item_shadow_mask;
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, has_shadow);
- if (has_shadow) {
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_NONE);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF3);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF5);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF7);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF9);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF13);
- }
-
- bool light_rebind = state.canvas_shader.bind();
-
- if (light_rebind) {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, Transform2D());
- if (storage->frame.current_rt) {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
- } else {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0));
- }
- if (state.using_skeleton) {
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse);
- }
- }
-
- LightInternal *light_internal = light_internal_owner.getornull(light->light_internal);
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 1, light_internal->ubo);
-
- if (has_shadow) {
-
- RasterizerStorageGLES3::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.getornull(light->shadow_buffer);
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
- glBindTexture(GL_TEXTURE_2D, cls->distance);
-
- /*canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_MATRIX,light->shadow_matrix_cache);
- canvas_shader.set_uniform(CanvasShaderGLES3::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult);
- canvas_shader.set_uniform(CanvasShaderGLES3::LIGHT_SHADOW_COLOR,light->shadow_color);*/
- }
-
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
- RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(light->texture);
- if (!t) {
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
- } else {
- t = t->get_ptr();
-
- glBindTexture(t->target, t->tex_id);
- }
-
- glActiveTexture(GL_TEXTURE0);
- _canvas_item_render_commands(ci, current_clip, reclip); //redraw using light
- }
-
- light = light->next_ptr;
- }
-
- if (light_used) {
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false);
-
- state.canvas_shader.bind();
-
- last_blend_mode = -1;
-
- /*
- //this is set again, so it should not be needed anyway?
- state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(
- ci->final_modulate.r * p_modulate.r,
- ci->final_modulate.g * p_modulate.g,
- ci->final_modulate.b * p_modulate.b,
- ci->final_modulate.a * p_modulate.a );
-
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,state.final_transform);
- state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Transform2D());
- state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate);
-
- glBlendEquation(GL_FUNC_ADD);
-
- if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- //@TODO RESET canvas_blend_mode
- */
- }
- }
-
- if (reclip) {
-
- glEnable(GL_SCISSOR_TEST);
- int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y);
- if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP])
- y = current_clip->final_clip_rect.position.y;
- glScissor(current_clip->final_clip_rect.position.x, y, current_clip->final_clip_rect.size.width, current_clip->final_clip_rect.size.height);
- }
-
- p_item_list = p_item_list->next;
- }
-
- if (current_clip) {
- glDisable(GL_SCISSOR_TEST);
- }
- //disable states that may have been used
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false);
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false);
-}
-
-void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {
-
- Light *light = p_lights_with_shadow;
-
- canvas_begin(); //reset
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
- int h = 10;
- int w = storage->frame.current_rt->width;
- int ofs = h;
- glDisable(GL_BLEND);
-
- while (light) {
- if (light->shadow_buffer.is_valid()) {
-
- RasterizerStorageGLES3::CanvasLightShadow *sb = storage->canvas_light_shadow_owner.getornull(light->shadow_buffer);
- if (sb) {
- glBindTexture(GL_TEXTURE_2D, sb->distance);
- draw_generic_textured_rect(Rect2(h, ofs, w - h * 2, h), Rect2(0, 0, 1, 1));
- ofs += h * 2;
- }
- }
-
- light = light->shadows_next_ptr;
- }
-
- canvas_end();
-}
-
-void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) {
-
- RasterizerStorageGLES3::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.getornull(p_buffer);
- ERR_FAIL_COND(!cls);
-
- glDisable(GL_BLEND);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_DITHER);
- glDisable(GL_CULL_FACE);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_DEPTH_TEST);
- glDepthMask(true);
-
- glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
-
- state.canvas_shadow_shader.bind();
-
- glViewport(0, 0, cls->size, cls->height);
- glClearDepth(1.0f);
- glClearColor(1, 1, 1, 1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- VS::CanvasOccluderPolygonCullMode cull = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
-
- for (int i = 0; i < 4; i++) {
-
- //make sure it remains orthogonal, makes easy to read angle later
-
- Transform light;
- light.origin[0] = p_light_xform[2][0];
- light.origin[1] = p_light_xform[2][1];
- light.basis[0][0] = p_light_xform[0][0];
- light.basis[0][1] = p_light_xform[1][0];
- light.basis[1][0] = p_light_xform[0][1];
- light.basis[1][1] = p_light_xform[1][1];
-
- //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
-
- //p_near=1;
- CameraMatrix 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::deg2rad(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(Vector3(0, 0, Math_PI * 2 * (i / 4.0))).xform(Vector3(0, 1, 0));
- projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
-
- state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::PROJECTION_MATRIX, projection);
- state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::LIGHT_MATRIX, light);
- state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::DISTANCE_NORM, 1.0 / p_far);
-
- if (i == 0)
- *p_xform_cache = projection;
-
- glViewport(0, (cls->height / 4) * i, cls->size, cls->height / 4);
-
- LightOccluderInstance *instance = p_occluders;
-
- while (instance) {
-
- RasterizerStorageGLES3::CanvasOccluder *cc = storage->canvas_occluder_owner.getornull(instance->polygon_buffer);
- if (!cc || cc->len == 0 || !(p_light_mask & instance->light_mask)) {
-
- instance = instance->next;
- continue;
- }
-
- state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES3::WORLD_MATRIX, instance->xform_cache);
-
- VS::CanvasOccluderPolygonCullMode transformed_cull_cache = instance->cull_cache;
-
- if (transformed_cull_cache != VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED &&
- (p_light_xform.basis_determinant() * instance->xform_cache.basis_determinant()) < 0) {
- transformed_cull_cache =
- transformed_cull_cache == VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE ?
- VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE :
- VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE;
- }
-
- if (cull != transformed_cull_cache) {
-
- cull = transformed_cull_cache;
- switch (cull) {
- case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: {
-
- glDisable(GL_CULL_FACE);
-
- } break;
- case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: {
-
- glEnable(GL_CULL_FACE);
- glCullFace(GL_FRONT);
- } break;
- case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: {
-
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
-
- } break;
- }
- }
-
- glBindVertexArray(cc->array_id);
- glDrawElements(GL_TRIANGLES, cc->len * 3, GL_UNSIGNED_SHORT, 0);
-
- instance = instance->next;
- }
- }
-
- glBindVertexArray(0);
-}
-void RasterizerCanvasGLES3::reset_canvas() {
-
- if (storage->frame.current_rt) {
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
- glColorMask(1, 1, 1, 1); //don't touch alpha
- }
-
- glBindVertexArray(0);
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_DITHER);
- glEnable(GL_BLEND);
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
- //glLineWidth(1.0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
- //use for reading from screen
- if (storage->frame.current_rt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING]) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
- }
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
-
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
-
- Transform canvas_transform;
-
- if (storage->frame.current_rt) {
-
- float csy = 1.0;
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) {
- csy = -1.0;
- }
- canvas_transform.translate(-(storage->frame.current_rt->width / 2.0f), -(storage->frame.current_rt->height / 2.0f), 0.0f);
- canvas_transform.scale(Vector3(2.0f / storage->frame.current_rt->width, csy * -2.0f / storage->frame.current_rt->height, 1.0f));
- } else {
- Vector2 ssize = OS::get_singleton()->get_window_size();
- canvas_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
- canvas_transform.scale(Vector3(2.0f / ssize.width, -2.0f / ssize.height, 1.0f));
- }
-
- state.vp = canvas_transform;
-
- store_transform(canvas_transform, state.canvas_item_ubo_data.projection_matrix);
- state.canvas_item_ubo_data.time = storage->frame.time[0];
-
- glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- state.canvas_texscreen_used = false;
-}
-
-void RasterizerCanvasGLES3::draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src) {
-
- state.canvas_shader.set_uniform(CanvasShaderGLES3::DST_RECT, Color(p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::SRC_RECT, Color(p_src.position.x, p_src.position.y, p_src.size.x, p_src.size.y));
- state.canvas_shader.set_uniform(CanvasShaderGLES3::CLIP_RECT_UV, false);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-}
-
-void RasterizerCanvasGLES3::draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) {
- Vector2 half_size;
- if (storage->frame.current_rt) {
- half_size = Vector2(storage->frame.current_rt->width, storage->frame.current_rt->height);
- } else {
- half_size = OS::get_singleton()->get_window_size();
- }
- half_size *= 0.5;
- Vector2 offset((p_rect.position.x - half_size.x) / half_size.x, (p_rect.position.y - half_size.y) / half_size.y);
- Vector2 scale(p_rect.size.x / half_size.x, p_rect.size.y / half_size.y);
-
- float aspect_ratio = p_rect.size.x / p_rect.size.y;
-
- // setup our lens shader
- state.lens_shader.bind();
- state.lens_shader.set_uniform(LensDistortedShaderGLES3::OFFSET, offset);
- state.lens_shader.set_uniform(LensDistortedShaderGLES3::SCALE, scale);
- state.lens_shader.set_uniform(LensDistortedShaderGLES3::K1, p_k1);
- state.lens_shader.set_uniform(LensDistortedShaderGLES3::K2, p_k2);
- state.lens_shader.set_uniform(LensDistortedShaderGLES3::EYE_CENTER, p_eye_center);
- state.lens_shader.set_uniform(LensDistortedShaderGLES3::UPSCALE, p_oversample);
- state.lens_shader.set_uniform(LensDistortedShaderGLES3::ASPECT_RATIO, aspect_ratio);
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_item_ubo);
- glBindVertexArray(data.canvas_quad_array);
-
- // and draw
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- glBindVertexArray(0);
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
-}
-
-void RasterizerCanvasGLES3::draw_window_margins(int *black_margin, RID *black_image) {
-
- Vector2 window_size = OS::get_singleton()->get_window_size();
- int window_h = window_size.height;
- int window_w = window_size.width;
-
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- glViewport(0, 0, window_size.width, window_size.height);
- canvas_begin();
-
- if (black_image[MARGIN_LEFT].is_valid()) {
- _bind_canvas_texture(black_image[MARGIN_LEFT], RID());
- Size2 sz(storage->texture_get_width(black_image[MARGIN_LEFT]), storage->texture_get_height(black_image[MARGIN_LEFT]));
- draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), Rect2(0, 0, sz.x, sz.y));
- } else if (black_margin[MARGIN_LEFT]) {
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
-
- draw_generic_textured_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), Rect2(0, 0, 1, 1));
- }
-
- if (black_image[MARGIN_RIGHT].is_valid()) {
- _bind_canvas_texture(black_image[MARGIN_RIGHT], RID());
- Size2 sz(storage->texture_get_width(black_image[MARGIN_RIGHT]), storage->texture_get_height(black_image[MARGIN_RIGHT]));
- draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h), Rect2(0, 0, sz.x, sz.y));
- } else if (black_margin[MARGIN_RIGHT]) {
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
-
- draw_generic_textured_rect(Rect2(window_w - black_margin[MARGIN_RIGHT], 0, black_margin[MARGIN_RIGHT], window_h), Rect2(0, 0, 1, 1));
- }
-
- if (black_image[MARGIN_TOP].is_valid()) {
- _bind_canvas_texture(black_image[MARGIN_TOP], RID());
-
- Size2 sz(storage->texture_get_width(black_image[MARGIN_TOP]), storage->texture_get_height(black_image[MARGIN_TOP]));
- draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[MARGIN_TOP]), Rect2(0, 0, sz.x, sz.y));
-
- } else if (black_margin[MARGIN_TOP]) {
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
-
- draw_generic_textured_rect(Rect2(0, 0, window_w, black_margin[MARGIN_TOP]), Rect2(0, 0, 1, 1));
- }
-
- if (black_image[MARGIN_BOTTOM].is_valid()) {
-
- _bind_canvas_texture(black_image[MARGIN_BOTTOM], RID());
-
- Size2 sz(storage->texture_get_width(black_image[MARGIN_BOTTOM]), storage->texture_get_height(black_image[MARGIN_BOTTOM]));
- draw_generic_textured_rect(Rect2(0, window_h - black_margin[MARGIN_BOTTOM], window_w, black_margin[MARGIN_BOTTOM]), Rect2(0, 0, sz.x, sz.y));
-
- } else if (black_margin[MARGIN_BOTTOM]) {
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
-
- draw_generic_textured_rect(Rect2(0, window_h - black_margin[MARGIN_BOTTOM], window_w, black_margin[MARGIN_BOTTOM]), Rect2(0, 0, 1, 1));
- }
-}
-
-void RasterizerCanvasGLES3::initialize() {
-
- {
- //quad buffers
-
- glGenBuffers(1, &data.canvas_quad_vertices);
- glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices);
- {
- const float qv[8] = {
- 0, 0,
- 0, 1,
- 1, 1,
- 1, 0
- };
-
- glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, qv, GL_STATIC_DRAW);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- glGenVertexArrays(1, &data.canvas_quad_array);
- glBindVertexArray(data.canvas_quad_array);
- glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
- glEnableVertexAttribArray(0);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
- }
- {
- //particle quad buffers
-
- glGenBuffers(1, &data.particle_quad_vertices);
- glBindBuffer(GL_ARRAY_BUFFER, data.particle_quad_vertices);
- {
- //quad of size 1, with pivot on the center for particles, then regular UVS. Color is general plus fetched from particle
- const float qv[16] = {
- -0.5, -0.5,
- 0.0, 0.0,
- -0.5, 0.5,
- 0.0, 1.0,
- 0.5, 0.5,
- 1.0, 1.0,
- 0.5, -0.5,
- 1.0, 0.0
- };
-
- glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- glGenVertexArrays(1, &data.particle_quad_array);
- glBindVertexArray(data.particle_quad_array);
- glBindBuffer(GL_ARRAY_BUFFER, data.particle_quad_vertices);
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8));
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
- }
- {
-
- uint32_t poly_size = GLOBAL_DEF_RST("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/canvas_polygon_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/canvas_polygon_buffer_size_kb", PROPERTY_HINT_RANGE, "0,256,1,or_greater"));
- poly_size *= 1024; //kb
- poly_size = MAX(poly_size, (2 + 2 + 4) * 4 * sizeof(float));
- glGenBuffers(1, &data.polygon_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
- glBufferData(GL_ARRAY_BUFFER, poly_size, NULL, GL_DYNAMIC_DRAW); //allocate max size
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- data.polygon_buffer_size = poly_size;
-
- //quad arrays
- for (int i = 0; i < 4; i++) {
- glGenVertexArrays(1, &data.polygon_buffer_quad_arrays[i]);
- glBindVertexArray(data.polygon_buffer_quad_arrays[i]);
- glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
-
- int uv_ofs = 0;
- int color_ofs = 0;
- int stride = 2 * 4;
-
- if (i & 1) { //color
- color_ofs = stride;
- stride += 4 * 4;
- }
-
- if (i & 2) { //uv
- uv_ofs = stride;
- stride += 2 * 4;
- }
-
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride, NULL);
-
- if (i & 1) {
- glEnableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs));
- }
-
- if (i & 2) {
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(uv_ofs));
- }
-
- glBindVertexArray(0);
- }
-
- glGenVertexArrays(1, &data.polygon_buffer_pointer_array);
-
- uint32_t index_size = GLOBAL_DEF_RST("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", 128);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", PROPERTY_HINT_RANGE, "0,256,1,or_greater"));
- index_size *= 1024; //kb
- glGenBuffers(1, &data.polygon_index_buffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, NULL, GL_DYNAMIC_DRAW); //allocate max size
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
- data.polygon_index_buffer_size = index_size;
- }
-
- store_transform(Transform(), state.canvas_item_ubo_data.projection_matrix);
-
- glGenBuffers(1, &state.canvas_item_ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- state.canvas_shader.init();
- state.canvas_shader.set_base_material_tex_index(2);
- state.canvas_shadow_shader.init();
- state.lens_shader.init();
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);
- state.canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);
-
- state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false));
-}
-
-void RasterizerCanvasGLES3::finalize() {
-
- glDeleteBuffers(1, &data.canvas_quad_vertices);
- glDeleteVertexArrays(1, &data.canvas_quad_array);
-
- glDeleteBuffers(1, &data.canvas_quad_vertices);
- glDeleteVertexArrays(1, &data.canvas_quad_array);
-
- glDeleteVertexArrays(1, &data.polygon_buffer_pointer_array);
-}
-
-RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
-}
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
deleted file mode 100644
index 8e7a3ae873..0000000000
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*************************************************************************/
-/* rasterizer_canvas_gles3.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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 RASTERIZERCANVASGLES3_H
-#define RASTERIZERCANVASGLES3_H
-
-#include "rasterizer_storage_gles3.h"
-#include "servers/visual/rasterizer.h"
-
-#include "shaders/canvas_shadow.glsl.gen.h"
-#include "shaders/lens_distorted.glsl.gen.h"
-
-class RasterizerSceneGLES3;
-
-class RasterizerCanvasGLES3 : public RasterizerCanvas {
-public:
- struct CanvasItemUBO {
-
- float projection_matrix[16];
- float time;
- uint8_t padding[12];
- };
-
- RasterizerSceneGLES3 *scene_render;
-
- struct Data {
-
- GLuint canvas_quad_vertices;
- GLuint canvas_quad_array;
-
- GLuint polygon_buffer;
- GLuint polygon_buffer_quad_arrays[4];
- GLuint polygon_buffer_pointer_array;
- GLuint polygon_index_buffer;
-
- GLuint particle_quad_vertices;
- GLuint particle_quad_array;
-
- uint32_t polygon_buffer_size;
- uint32_t polygon_index_buffer_size;
-
- } data;
-
- struct State {
- CanvasItemUBO canvas_item_ubo_data;
- GLuint canvas_item_ubo;
- bool canvas_texscreen_used;
- CanvasShaderGLES3 canvas_shader;
- CanvasShadowShaderGLES3 canvas_shadow_shader;
- LensDistortedShaderGLES3 lens_shader;
-
- bool using_texture_rect;
- bool using_ninepatch;
-
- RID current_tex;
- RID current_normal;
- RasterizerStorageGLES3::Texture *current_tex_ptr;
-
- Transform vp;
-
- Color canvas_item_modulate;
- Transform2D extra_matrix;
- Transform2D final_transform;
- bool using_skeleton;
- Transform2D skeleton_transform;
- Transform2D skeleton_transform_inverse;
-
- } state;
-
- RasterizerStorageGLES3 *storage;
-
- struct LightInternal {
-
- struct UBOData {
-
- float light_matrix[16];
- float local_matrix[16];
- float shadow_matrix[16];
- float color[4];
- float shadow_color[4];
- float light_pos[2];
- float shadowpixel_size;
- float shadow_gradient;
- float light_height;
- float light_outside_alpha;
- float shadow_distance_mult;
- uint8_t padding[4];
- } ubo_data;
-
- GLuint ubo;
- };
-
- RID_PtrOwner light_internal_owner;
-
- virtual RID light_internal_create();
- virtual void light_internal_update(RID p_rid, Light *p_light);
- virtual void light_internal_free(RID p_rid);
-
- virtual void canvas_begin();
- virtual void canvas_end();
-
- _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false);
- _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force = false);
-
- _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs);
- _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights);
- _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
- _FORCE_INLINE_ void _draw_generic_indices(GLuint p_primitive, const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
-
- _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip);
- _FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect);
-
- virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform);
- virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow);
-
- virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache);
-
- virtual void reset_canvas();
-
- void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src);
- void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
-
- void initialize();
- void finalize();
-
- virtual void draw_window_margins(int *black_margin, RID *black_image);
-
- RasterizerCanvasGLES3();
-};
-
-#endif // RASTERIZERCANVASGLES3_H
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
deleted file mode 100644
index ef6f2854bc..0000000000
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ /dev/null
@@ -1,444 +0,0 @@
-/*************************************************************************/
-/* rasterizer_gles3.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#include "rasterizer_gles3.h"
-
-#include "core/os/os.h"
-#include "core/project_settings.h"
-
-RasterizerStorage *RasterizerGLES3::get_storage() {
-
- return storage;
-}
-
-RasterizerCanvas *RasterizerGLES3::get_canvas() {
-
- return canvas;
-}
-
-RasterizerScene *RasterizerGLES3::get_scene() {
-
- return scene;
-}
-
-#define _EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
-#define _EXT_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
-#define _EXT_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
-#define _EXT_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
-#define _EXT_DEBUG_SOURCE_API_ARB 0x8246
-#define _EXT_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
-#define _EXT_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
-#define _EXT_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
-#define _EXT_DEBUG_SOURCE_APPLICATION_ARB 0x824A
-#define _EXT_DEBUG_SOURCE_OTHER_ARB 0x824B
-#define _EXT_DEBUG_TYPE_ERROR_ARB 0x824C
-#define _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
-#define _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
-#define _EXT_DEBUG_TYPE_PORTABILITY_ARB 0x824F
-#define _EXT_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
-#define _EXT_DEBUG_TYPE_OTHER_ARB 0x8251
-#define _EXT_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
-#define _EXT_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
-#define _EXT_DEBUG_LOGGED_MESSAGES_ARB 0x9145
-#define _EXT_DEBUG_SEVERITY_HIGH_ARB 0x9146
-#define _EXT_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
-#define _EXT_DEBUG_SEVERITY_LOW_ARB 0x9148
-#define _EXT_DEBUG_OUTPUT 0x92E0
-
-#if defined(MINGW_ENABLED) || defined(_MSC_VER)
-#define strcpy strcpy_s
-#endif
-
-#ifdef GLAD_ENABLED
-// Restricting to GLAD as only used in initialize() with GLAD_GL_ARB_debug_output
-static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
-
- if (type == _EXT_DEBUG_TYPE_OTHER_ARB)
- return;
-
- if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB)
- return; //these are ultimately annoying, so removing for now
-
- char debSource[256], debType[256], debSev[256];
- if (source == _EXT_DEBUG_SOURCE_API_ARB)
- strcpy(debSource, "OpenGL");
- else if (source == _EXT_DEBUG_SOURCE_WINDOW_SYSTEM_ARB)
- strcpy(debSource, "Windows");
- else if (source == _EXT_DEBUG_SOURCE_SHADER_COMPILER_ARB)
- strcpy(debSource, "Shader Compiler");
- else if (source == _EXT_DEBUG_SOURCE_THIRD_PARTY_ARB)
- strcpy(debSource, "Third Party");
- else if (source == _EXT_DEBUG_SOURCE_APPLICATION_ARB)
- strcpy(debSource, "Application");
- else if (source == _EXT_DEBUG_SOURCE_OTHER_ARB)
- strcpy(debSource, "Other");
-
- if (type == _EXT_DEBUG_TYPE_ERROR_ARB)
- strcpy(debType, "Error");
- else if (type == _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB)
- strcpy(debType, "Deprecated behavior");
- else if (type == _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB)
- strcpy(debType, "Undefined behavior");
- else if (type == _EXT_DEBUG_TYPE_PORTABILITY_ARB)
- strcpy(debType, "Portability");
- else if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB)
- strcpy(debType, "Performance");
-
- if (severity == _EXT_DEBUG_SEVERITY_HIGH_ARB)
- strcpy(debSev, "High");
- else if (severity == _EXT_DEBUG_SEVERITY_MEDIUM_ARB)
- strcpy(debSev, "Medium");
- else if (severity == _EXT_DEBUG_SEVERITY_LOW_ARB)
- strcpy(debSev, "Low");
-
- String output = String() + "GL ERROR: Source: " + debSource + "\tType: " + debType + "\tID: " + itos(id) + "\tSeverity: " + debSev + "\tMessage: " + message;
-
- ERR_PRINT(output);
-}
-#endif // GLAD_ENABLED
-
-typedef void (*DEBUGPROCARB)(GLenum source,
- GLenum type,
- GLuint id,
- GLenum severity,
- GLsizei length,
- const char *message,
- const void *userParam);
-
-typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userParam);
-
-Error RasterizerGLES3::is_viable() {
-
-#ifdef GLAD_ENABLED
- if (!gladLoadGL()) {
- ERR_PRINT("Error initializing GLAD");
- return ERR_UNAVAILABLE;
- }
-
-// GLVersion seems to be used for both GL and GL ES, so we need different version checks for them
-#ifdef OPENGL_ENABLED // OpenGL 3.3 Core Profile required
- if (GLVersion.major < 3 || (GLVersion.major == 3 && GLVersion.minor < 3)) {
-#else // OpenGL ES 3.0
- if (GLVersion.major < 3) {
-#endif
- return ERR_UNAVAILABLE;
- }
-
-#endif // GLAD_ENABLED
- return OK;
-}
-
-void RasterizerGLES3::initialize() {
-
- print_verbose("Using GLES3 video driver");
-
-#ifdef GLAD_ENABLED
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (GLAD_GL_ARB_debug_output) {
- glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
- glDebugMessageCallbackARB(_gl_debug_print, NULL);
- glEnable(_EXT_DEBUG_OUTPUT);
- } else {
- print_line("OpenGL debugging not supported!");
- }
- }
-#endif // GLAD_ENABLED
-
- /* // For debugging
- if (GLAD_GL_ARB_debug_output) {
- glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_ERROR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
- glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
- glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
- glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PORTABILITY_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
- glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PERFORMANCE_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
- glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_OTHER_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE);
- glDebugMessageInsertARB(
- GL_DEBUG_SOURCE_API_ARB,
- GL_DEBUG_TYPE_OTHER_ARB, 1,
- GL_DEBUG_SEVERITY_HIGH_ARB,5, "hello");
- }
- */
-
- print_line("OpenGL ES 3.0 Renderer: " + VisualServer::get_singleton()->get_video_adapter_name());
- storage->initialize();
- canvas->initialize();
- scene->initialize();
-}
-
-void RasterizerGLES3::begin_frame(double frame_step) {
-
- time_total += frame_step;
-
- if (frame_step == 0) {
- //to avoid hiccups
- frame_step = 0.001;
- }
-
- double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs");
- if (time_total > time_roll_over)
- time_total = 0; //roll over every day (should be customz
-
- storage->frame.time[0] = time_total;
- storage->frame.time[1] = Math::fmod(time_total, 3600);
- storage->frame.time[2] = Math::fmod(time_total, 900);
- storage->frame.time[3] = Math::fmod(time_total, 60);
- storage->frame.count++;
- storage->frame.delta = frame_step;
-
- storage->update_dirty_resources();
-
- storage->info.render_final = storage->info.render;
- storage->info.render.reset();
-
- scene->iteration();
-}
-
-void RasterizerGLES3::set_current_render_target(RID p_render_target) {
-
- if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
- //handle pending clear request, if the framebuffer was not cleared
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
-
- glClearColor(
- storage->frame.clear_request_color.r,
- storage->frame.clear_request_color.g,
- storage->frame.clear_request_color.b,
- storage->frame.clear_request_color.a);
-
- glClear(GL_COLOR_BUFFER_BIT);
- }
-
- if (p_render_target.is_valid()) {
- RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
- storage->frame.current_rt = rt;
- ERR_FAIL_COND(!rt);
- storage->frame.clear_request = false;
-
- glViewport(0, 0, rt->width, rt->height);
-
- } else {
- storage->frame.current_rt = NULL;
- storage->frame.clear_request = false;
- glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- }
-}
-
-void RasterizerGLES3::restore_render_target(bool p_3d_was_drawn) {
-
- ERR_FAIL_COND(storage->frame.current_rt == NULL);
- RasterizerStorageGLES3::RenderTarget *rt = storage->frame.current_rt;
- if (p_3d_was_drawn && rt->external.fbo != 0) {
- // our external render buffer is now leading, render 2d into that.
- glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
- } else {
- glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
- }
- glViewport(0, 0, rt->width, rt->height);
-}
-
-void RasterizerGLES3::clear_render_target(const Color &p_color) {
-
- ERR_FAIL_COND(!storage->frame.current_rt);
-
- storage->frame.clear_request = true;
- storage->frame.clear_request_color = p_color;
-}
-
-void RasterizerGLES3::set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
-
- if (p_image.is_null() || p_image->empty())
- return;
-
- begin_frame(0.0);
-
- int window_w = OS::get_singleton()->get_video_mode(0).width;
- int window_h = OS::get_singleton()->get_video_mode(0).height;
-
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- glViewport(0, 0, window_w, window_h);
- glDisable(GL_BLEND);
- glDepthMask(GL_FALSE);
- if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
- glClearColor(0.0, 0.0, 0.0, 0.0);
- } else {
- glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
- }
- glClear(GL_COLOR_BUFFER_BIT);
- canvas->canvas_begin();
-
- RID texture = storage->texture_create();
- storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0);
- storage->texture_set_data(texture, p_image);
-
- Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());
- Rect2 screenrect;
- if (p_scale) {
-
- if (window_w > window_h) {
- //scale horizontally
- screenrect.size.y = window_h;
- screenrect.size.x = imgrect.size.x * window_h / imgrect.size.y;
- screenrect.position.x = (window_w - screenrect.size.x) / 2;
-
- } else {
- //scale vertically
- screenrect.size.x = window_w;
- screenrect.size.y = imgrect.size.y * window_w / imgrect.size.x;
- screenrect.position.y = (window_h - screenrect.size.y) / 2;
- }
- } else {
-
- screenrect = imgrect;
- screenrect.position += ((Size2(window_w, window_h) - screenrect.size) / 2.0).floor();
- }
-
- RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(texture);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, t->tex_id);
- canvas->draw_generic_textured_rect(screenrect, Rect2(0, 0, 1, 1));
- glBindTexture(GL_TEXTURE_2D, 0);
- canvas->canvas_end();
-
- storage->free(texture); // free since it's only one frame that stays there
-
- end_frame(true);
-}
-
-void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen) {
-
- ERR_FAIL_COND(storage->frame.current_rt);
-
- RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND(!rt);
-
- Size2 win_size = OS::get_singleton()->get_window_size();
- if (rt->external.fbo != 0) {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo);
- } else {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
- }
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- glBlitFramebuffer(0, 0, rt->width, rt->height, p_screen_rect.position.x, win_size.height - p_screen_rect.position.y - p_screen_rect.size.height, p_screen_rect.position.x + p_screen_rect.size.width, win_size.height - p_screen_rect.position.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
-}
-
-void RasterizerGLES3::output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) {
- ERR_FAIL_COND(storage->frame.current_rt);
-
- RasterizerStorageGLES3::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND(!rt);
-
- glDisable(GL_BLEND);
-
- // render to our framebuffer
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-
- // output our texture
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, rt->color);
-
- canvas->draw_lens_distortion_rect(p_screen_rect, p_k1, p_k2, p_eye_center, p_oversample);
-
- glBindTexture(GL_TEXTURE_2D, 0);
-}
-
-void RasterizerGLES3::end_frame(bool p_swap_buffers) {
-
- if (OS::get_singleton()->is_layered_allowed()) {
- if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
-#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
- Size2 wndsize = OS::get_singleton()->get_layered_buffer_size();
- uint8_t *data = OS::get_singleton()->get_layered_buffer_data();
- if (data) {
- glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data);
- OS::get_singleton()->swap_layered_buffer();
-
- return;
- }
-#endif
- } else {
- //clear alpha
- glColorMask(false, false, false, true);
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT);
- glColorMask(true, true, true, true);
- }
- }
-
- if (p_swap_buffers)
- OS::get_singleton()->swap_buffers();
- else
- glFinish();
-}
-
-void RasterizerGLES3::finalize() {
-
- storage->finalize();
- canvas->finalize();
-}
-
-Rasterizer *RasterizerGLES3::_create_current() {
-
- return memnew(RasterizerGLES3);
-}
-
-void RasterizerGLES3::make_current() {
- _create_func = _create_current;
-}
-
-void RasterizerGLES3::register_config() {
-
- GLOBAL_DEF("rendering/quality/filters/anisotropic_filter_level", 4);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/anisotropic_filter_level", PropertyInfo(Variant::INT, "rendering/quality/filters/anisotropic_filter_level", PROPERTY_HINT_RANGE, "1,16,1"));
- GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::REAL, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"));
-}
-
-RasterizerGLES3::RasterizerGLES3() {
-
- storage = memnew(RasterizerStorageGLES3);
- canvas = memnew(RasterizerCanvasGLES3);
- scene = memnew(RasterizerSceneGLES3);
- canvas->storage = storage;
- canvas->scene_render = scene;
- storage->canvas = canvas;
- scene->storage = storage;
- storage->scene = scene;
-
- time_total = 0;
-}
-
-RasterizerGLES3::~RasterizerGLES3() {
-
- memdelete(storage);
- memdelete(canvas);
- memdelete(scene);
-}
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
deleted file mode 100644
index de7c1ab7e1..0000000000
--- a/drivers/gles3/rasterizer_gles3.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*************************************************************************/
-/* rasterizer_gles3.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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 RASTERIZERGLES3_H
-#define RASTERIZERGLES3_H
-
-#include "rasterizer_canvas_gles3.h"
-#include "rasterizer_scene_gles3.h"
-#include "rasterizer_storage_gles3.h"
-#include "servers/visual/rasterizer.h"
-
-class RasterizerGLES3 : public Rasterizer {
-
- static Rasterizer *_create_current();
-
- RasterizerStorageGLES3 *storage;
- RasterizerCanvasGLES3 *canvas;
- RasterizerSceneGLES3 *scene;
-
- double time_total;
-
-public:
- virtual RasterizerStorage *get_storage();
- virtual RasterizerCanvas *get_canvas();
- virtual RasterizerScene *get_scene();
-
- virtual void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true);
-
- virtual void initialize();
- virtual void begin_frame(double frame_step);
- virtual void set_current_render_target(RID p_render_target);
- virtual void restore_render_target(bool p_3d_was_drawn);
- virtual void clear_render_target(const Color &p_color);
- virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0);
- virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
- virtual void end_frame(bool p_swap_buffers);
- virtual void finalize();
-
- static Error is_viable();
- static void make_current();
- static void register_config();
-
- virtual bool is_low_end() const { return false; }
-
- RasterizerGLES3();
- ~RasterizerGLES3();
-};
-
-#endif // RASTERIZERGLES3_H
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
deleted file mode 100644
index ec8701af31..0000000000
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ /dev/null
@@ -1,5346 +0,0 @@
-/*************************************************************************/
-/* rasterizer_scene_gles3.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#include "rasterizer_scene_gles3.h"
-
-#include "core/math/math_funcs.h"
-#include "core/os/os.h"
-#include "core/project_settings.h"
-#include "rasterizer_canvas_gles3.h"
-#include "servers/camera/camera_feed.h"
-#include "servers/visual/visual_server_raster.h"
-
-#ifndef GLES_OVER_GL
-#define glClearDepth glClearDepthf
-#endif
-
-static const GLenum _cube_side_enum[6] = {
-
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- GL_TEXTURE_CUBE_MAP_POSITIVE_X,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
-
-};
-
-static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.elements[0][0];
- p_array[1] = p_mtx.basis.elements[1][0];
- p_array[2] = p_mtx.basis.elements[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.basis.elements[0][1];
- p_array[5] = p_mtx.basis.elements[1][1];
- p_array[6] = p_mtx.basis.elements[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.basis.elements[0][2];
- p_array[9] = p_mtx.basis.elements[1][2];
- p_array[10] = p_mtx.basis.elements[2][2];
- p_array[11] = 0;
- p_array[12] = p_mtx.origin.x;
- p_array[13] = p_mtx.origin.y;
- p_array[14] = p_mtx.origin.z;
- p_array[15] = 1;
-}
-
-static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
-
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
- }
- }
-}
-
-/* SHADOW ATLAS API */
-
-RID RasterizerSceneGLES3::shadow_atlas_create() {
-
- ShadowAtlas *shadow_atlas = memnew(ShadowAtlas);
- shadow_atlas->fbo = 0;
- shadow_atlas->depth = 0;
- shadow_atlas->size = 0;
- shadow_atlas->smallest_subdiv = 0;
-
- for (int i = 0; i < 4; i++) {
- shadow_atlas->size_order[i] = i;
- }
-
- return shadow_atlas_owner.make_rid(shadow_atlas);
-}
-
-void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size) {
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
- ERR_FAIL_COND(!shadow_atlas);
- ERR_FAIL_COND(p_size < 0);
-
- p_size = next_power_of_2(p_size);
-
- if (p_size == shadow_atlas->size)
- return;
-
- // erasing atlas
- if (shadow_atlas->fbo) {
- glDeleteTextures(1, &shadow_atlas->depth);
- glDeleteFramebuffers(1, &shadow_atlas->fbo);
-
- shadow_atlas->depth = 0;
- shadow_atlas->fbo = 0;
- }
- for (int i = 0; i < 4; i++) {
- //clear subdivisions
- shadow_atlas->quadrants[i].shadows.resize(0);
- shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision);
- }
-
- //erase shadow atlas reference from lights
- for (Map::Element *E = shadow_atlas->shadow_owners.front(); E; E = E->next()) {
- LightInstance *li = light_instance_owner.getornull(E->key());
- ERR_CONTINUE(!li);
- li->shadow_atlases.erase(p_atlas);
- }
-
- //clear owners
- shadow_atlas->shadow_owners.clear();
-
- shadow_atlas->size = p_size;
-
- if (shadow_atlas->size) {
- glGenFramebuffers(1, &shadow_atlas->fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
-
- // Create a texture for storing the depth
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &shadow_atlas->depth);
- glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadow_atlas->size, shadow_atlas->size, 0,
- GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_TEXTURE_2D, shadow_atlas->depth, 0);
-
- glViewport(0, 0, shadow_atlas->size, shadow_atlas->size);
- glClearDepth(0.0f);
- glClear(GL_DEPTH_BUFFER_BIT);
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- }
-}
-
-void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
- ERR_FAIL_COND(!shadow_atlas);
- ERR_FAIL_INDEX(p_quadrant, 4);
- ERR_FAIL_INDEX(p_subdivision, 16384);
-
- uint32_t subdiv = next_power_of_2(p_subdivision);
- if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer
- subdiv <<= 1;
- }
-
- subdiv = int(Math::sqrt((float)subdiv));
-
- //obtain the number that will be x*x
-
- if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv)
- return;
-
- //erase all data from quadrant
- for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) {
-
- if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) {
- shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
- LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
- ERR_CONTINUE(!li);
- li->shadow_atlases.erase(p_atlas);
- }
- }
-
- shadow_atlas->quadrants[p_quadrant].shadows.resize(0);
- shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv);
- shadow_atlas->quadrants[p_quadrant].subdivision = subdiv;
-
- //cache the smallest subdiv (for faster allocation in light update)
-
- shadow_atlas->smallest_subdiv = 1 << 30;
-
- for (int i = 0; i < 4; i++) {
- if (shadow_atlas->quadrants[i].subdivision) {
- shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision);
- }
- }
-
- if (shadow_atlas->smallest_subdiv == 1 << 30) {
- shadow_atlas->smallest_subdiv = 0;
- }
-
- //resort the size orders, simple bublesort for 4 elements..
-
- int swaps = 0;
- do {
- swaps = 0;
-
- for (int i = 0; i < 3; i++) {
- if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) {
- SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]);
- swaps++;
- }
- }
- } while (swaps > 0);
-}
-
-bool RasterizerSceneGLES3::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) {
-
- for (int i = p_quadrant_count - 1; i >= 0; i--) {
-
- int qidx = p_in_quadrants[i];
-
- if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {
- return false;
- }
-
- //look for an empty space
- int sc = shadow_atlas->quadrants[qidx].shadows.size();
- ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptrw();
-
- int found_free_idx = -1; //found a free one
- int found_used_idx = -1; //found existing one, must steal it
- 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_valid()) {
- found_free_idx = j;
- break;
- }
-
- LightInstance *sli = light_instance_owner.getornull(sarr[j].owner);
- ERR_CONTINUE(!sli);
-
- if (sli->last_scene_pass != scene_pass) {
-
- //was just allocated, don't kill it so soon, wait a bit..
- if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec)
- continue;
-
- if (found_used_idx == -1 || sli->last_scene_pass < min_pass) {
- found_used_idx = j;
- min_pass = sli->last_scene_pass;
- }
- }
- }
-
- if (found_free_idx == -1 && found_used_idx == -1)
- continue; //nothing found
-
- if (found_free_idx == -1 && found_used_idx != -1) {
- found_free_idx = found_used_idx;
- }
-
- r_quadrant = qidx;
- r_shadow = found_free_idx;
-
- return true;
- }
-
- return false;
-}
-
-bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
- ERR_FAIL_COND_V(!shadow_atlas, false);
-
- LightInstance *li = light_instance_owner.getornull(p_light_intance);
- ERR_FAIL_COND_V(!li, false);
-
- if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) {
- return false;
- }
-
- uint32_t quad_size = shadow_atlas->size >> 1;
- int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage));
-
- int valid_quadrants[4];
- int valid_quadrant_count = 0;
- int best_size = -1; //best size found
- int best_subdiv = -1; //subdiv for the best size
-
- //find the quadrants this fits into, and the best possible size it can fit into
- for (int i = 0; i < 4; i++) {
- int q = shadow_atlas->size_order[i];
- int sd = shadow_atlas->quadrants[q].subdivision;
- if (sd == 0)
- continue; //unused
-
- int max_fit = quad_size / sd;
-
- if (best_size != -1 && max_fit > best_size)
- break; //too large
-
- valid_quadrants[valid_quadrant_count++] = q;
- best_subdiv = sd;
-
- if (max_fit >= desired_fit) {
- best_size = max_fit;
- }
- }
-
- ERR_FAIL_COND_V(valid_quadrant_count == 0, false);
-
- uint64_t tick = OS::get_singleton()->get_ticks_msec();
-
- //see if it already exists
-
- if (shadow_atlas->shadow_owners.has(p_light_intance)) {
- //it does!
- uint32_t key = shadow_atlas->shadow_owners[p_light_intance];
- uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- bool should_realloc = shadow_atlas->quadrants[q].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec);
- bool should_redraw = shadow_atlas->quadrants[q].shadows[s].version != p_light_version;
-
- if (!should_realloc) {
- shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version;
- //already existing, see if it should redraw or it's just OK
- return should_redraw;
- }
-
- int new_quadrant, new_shadow;
-
- //find a better place
- if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, shadow_atlas->quadrants[q].subdivision, tick, new_quadrant, new_shadow)) {
- //found a better place!
- ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
- if (sh->owner.is_valid()) {
- //is taken, but is invalid, erasing it
- shadow_atlas->shadow_owners.erase(sh->owner);
- LightInstance *sli = light_instance_owner.getornull(sh->owner);
- sli->shadow_atlases.erase(p_atlas);
- }
-
- //erase previous
- shadow_atlas->quadrants[q].shadows.write[s].version = 0;
- shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
-
- sh->owner = p_light_intance;
- sh->alloc_tick = tick;
- sh->version = p_light_version;
- li->shadow_atlases.insert(p_atlas);
-
- //make new key
- key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
- key |= new_shadow;
- //update it in map
- shadow_atlas->shadow_owners[p_light_intance] = key;
- //make it dirty, as it should redraw anyway
- return true;
- }
-
- //no better place for this shadow found, keep current
-
- //already existing, see if it should redraw or it's just OK
-
- shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version;
-
- return should_redraw;
- }
-
- int new_quadrant, new_shadow;
-
- //find a better place
- if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, -1, tick, new_quadrant, new_shadow)) {
- //found a better place!
- ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
- if (sh->owner.is_valid()) {
- //is taken, but is invalid, erasing it
- shadow_atlas->shadow_owners.erase(sh->owner);
- LightInstance *sli = light_instance_owner.getornull(sh->owner);
- sli->shadow_atlases.erase(p_atlas);
- }
-
- sh->owner = p_light_intance;
- sh->alloc_tick = tick;
- sh->version = p_light_version;
- li->shadow_atlases.insert(p_atlas);
-
- //make new key
- uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
- key |= new_shadow;
- //update it in map
- shadow_atlas->shadow_owners[p_light_intance] = key;
- //make it dirty, as it should redraw anyway
-
- return true;
- }
-
- //no place to allocate this light, apologies
-
- return false;
-}
-
-void RasterizerSceneGLES3::set_directional_shadow_count(int p_count) {
-
- directional_shadow.light_count = p_count;
- directional_shadow.current_light = 0;
-}
-
-int RasterizerSceneGLES3::get_directional_light_shadow_size(RID p_light_intance) {
-
- ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
-
- int shadow_size;
-
- if (directional_shadow.light_count == 1) {
- shadow_size = directional_shadow.size;
- } else {
- shadow_size = directional_shadow.size / 2; //more than 4 not supported anyway
- }
-
- LightInstance *light_instance = light_instance_owner.getornull(p_light_intance);
- ERR_FAIL_COND_V(!light_instance, 0);
-
- switch (light_instance->light_ptr->directional_shadow_mode) {
- case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
- break; //none
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break;
- }
-
- return shadow_size;
-}
-//////////////////////////////////////////////////////
-
-RID RasterizerSceneGLES3::reflection_atlas_create() {
-
- ReflectionAtlas *reflection_atlas = memnew(ReflectionAtlas);
- reflection_atlas->subdiv = 0;
- reflection_atlas->color = 0;
- reflection_atlas->size = 0;
- for (int i = 0; i < 6; i++) {
- reflection_atlas->fbo[i] = 0;
- }
-
- return reflection_atlas_owner.make_rid(reflection_atlas);
-}
-
-void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_size) {
-
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas);
- ERR_FAIL_COND(!reflection_atlas);
-
- int size = next_power_of_2(p_size);
-
- if (size == reflection_atlas->size)
- return;
- if (reflection_atlas->size) {
- for (int i = 0; i < 6; i++) {
- glDeleteFramebuffers(1, &reflection_atlas->fbo[i]);
- reflection_atlas->fbo[i] = 0;
- }
- glDeleteTextures(1, &reflection_atlas->color);
- reflection_atlas->color = 0;
- }
-
- reflection_atlas->size = size;
-
- for (int i = 0; i < reflection_atlas->reflections.size(); i++) {
- //erase probes reference to this
- if (reflection_atlas->reflections[i].owner.is_valid()) {
- ReflectionProbeInstance *reflection_probe_instance = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[i].owner);
- reflection_atlas->reflections.write[i].owner = RID();
-
- ERR_CONTINUE(!reflection_probe_instance);
- reflection_probe_instance->reflection_atlas_index = -1;
- reflection_probe_instance->atlas = RID();
- reflection_probe_instance->render_step = -1;
- }
- }
-
- if (reflection_atlas->size) {
-
- bool use_float = true;
-
- GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2;
- GLenum format = GL_RGBA;
- GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV;
-
- // Create a texture for storing the color
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &reflection_atlas->color);
- glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
-
- int mmsize = reflection_atlas->size;
- glTexStorage2DCustom(GL_TEXTURE_2D, 6, internal_format, mmsize, mmsize, format, type);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5);
-
- for (int i = 0; i < 6; i++) {
- glGenFramebuffers(1, &reflection_atlas->fbo[i]);
- glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[i]);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reflection_atlas->color, i);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
-
- glDisable(GL_SCISSOR_TEST);
- glViewport(0, 0, mmsize, mmsize);
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT); //it needs to be cleared, to avoid generating garbage
-
- mmsize >>= 1;
- }
- }
-}
-
-void RasterizerSceneGLES3::reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) {
-
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas);
- ERR_FAIL_COND(!reflection_atlas);
-
- int subdiv = next_power_of_2(p_subdiv);
- if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer
- subdiv <<= 1;
- }
-
- subdiv = int(Math::sqrt((float)subdiv));
-
- if (reflection_atlas->subdiv == subdiv)
- return;
-
- if (subdiv) {
-
- for (int i = 0; i < reflection_atlas->reflections.size(); i++) {
- //erase probes reference to this
- if (reflection_atlas->reflections[i].owner.is_valid()) {
- ReflectionProbeInstance *reflection_probe_instance = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[i].owner);
- reflection_atlas->reflections.write[i].owner = RID();
-
- ERR_CONTINUE(!reflection_probe_instance);
- reflection_probe_instance->reflection_atlas_index = -1;
- reflection_probe_instance->atlas = RID();
- reflection_probe_instance->render_step = -1;
- }
- }
- }
-
- reflection_atlas->subdiv = subdiv;
-
- reflection_atlas->reflections.resize(subdiv * subdiv);
-}
-
-////////////////////////////////////////////////////
-
-RID RasterizerSceneGLES3::reflection_probe_instance_create(RID p_probe) {
-
- RasterizerStorageGLES3::ReflectionProbe *probe = storage->reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!probe, RID());
-
- ReflectionProbeInstance *rpi = memnew(ReflectionProbeInstance);
-
- rpi->probe_ptr = probe;
- rpi->self = reflection_probe_instance_owner.make_rid(rpi);
- rpi->probe = p_probe;
- rpi->reflection_atlas_index = -1;
- rpi->render_step = -1;
- rpi->last_pass = 0;
-
- return rpi->self;
-}
-
-void RasterizerSceneGLES3::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND(!rpi);
- rpi->transform = p_transform;
-}
-
-void RasterizerSceneGLES3::reflection_probe_release_atlas_index(RID p_instance) {
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND(!rpi);
- if (rpi->reflection_atlas_index == -1)
- return;
-
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(rpi->atlas);
- ERR_FAIL_COND(!reflection_atlas);
-
- ERR_FAIL_INDEX(rpi->reflection_atlas_index, reflection_atlas->reflections.size());
-
- ERR_FAIL_COND(reflection_atlas->reflections[rpi->reflection_atlas_index].owner != rpi->self);
-
- reflection_atlas->reflections.write[rpi->reflection_atlas_index].owner = RID();
-
- rpi->reflection_atlas_index = -1;
- rpi->atlas = RID();
- rpi->render_step = -1;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_needs_redraw(RID p_instance) {
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND_V(!rpi, false);
-
- return rpi->reflection_atlas_index == -1 || rpi->probe_ptr->update_mode == VS::REFLECTION_PROBE_UPDATE_ALWAYS;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_has_reflection(RID p_instance) {
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND_V(!rpi, false);
-
- return rpi->reflection_atlas_index != -1;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND_V(!rpi, false);
-
- rpi->render_step = 0;
-
- if (rpi->reflection_atlas_index != -1) {
- return true; //got one already
- }
-
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
- ERR_FAIL_COND_V(!reflection_atlas, false);
-
- if (reflection_atlas->size == 0 || reflection_atlas->subdiv == 0) {
- return false;
- }
-
- int best_free = -1;
- int best_used = -1;
- uint64_t best_used_frame = 0;
-
- for (int i = 0; i < reflection_atlas->reflections.size(); i++) {
- if (reflection_atlas->reflections[i].owner == RID()) {
- best_free = i;
- break;
- }
-
- if (rpi->render_step < 0 && reflection_atlas->reflections[i].last_frame < storage->frame.count &&
- (best_used == -1 || reflection_atlas->reflections[i].last_frame < best_used_frame)) {
- best_used = i;
- best_used_frame = reflection_atlas->reflections[i].last_frame;
- }
- }
-
- if (best_free == -1 && best_used == -1) {
- return false; // sorry, can not do. Try again next frame.
- }
-
- if (best_free == -1) {
- //find best from what is used
- best_free = best_used;
-
- ReflectionProbeInstance *victim_rpi = reflection_probe_instance_owner.getornull(reflection_atlas->reflections[best_free].owner);
- ERR_FAIL_COND_V(!victim_rpi, false);
- victim_rpi->atlas = RID();
- victim_rpi->reflection_atlas_index = -1;
- }
-
- reflection_atlas->reflections.write[best_free].owner = p_instance;
- reflection_atlas->reflections.write[best_free].last_frame = storage->frame.count;
-
- rpi->reflection_atlas_index = best_free;
- rpi->atlas = p_reflection_atlas;
- rpi->render_step = 0;
-
- return true;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_postprocess_step(RID p_instance) {
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND_V(!rpi, true);
-
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(rpi->atlas);
- ERR_FAIL_COND_V(!reflection_atlas, false);
-
- ERR_FAIL_COND_V(rpi->render_step >= 6, true);
-
- glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[rpi->render_step]);
- state.cube_to_dp_shader.bind();
-
- int target_size = reflection_atlas->size / reflection_atlas->subdiv;
-
- int cubemap_index = reflection_cubemaps.size() - 1;
-
- for (int i = reflection_cubemaps.size() - 1; i >= 0; i--) {
- //find appropriate cubemap to render to
- if (reflection_cubemaps[i].size > target_size * 2)
- break;
-
- cubemap_index = i;
- }
-
- glDisable(GL_BLEND);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_CUBE_MAP, reflection_cubemaps[cubemap_index].cubemap);
- glDisable(GL_CULL_FACE);
-
- storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
- storage->shaders.cubemap_filter.bind();
-
- int cell_size = reflection_atlas->size / reflection_atlas->subdiv;
- for (int i = 0; i < rpi->render_step; i++) {
- cell_size >>= 1; //mipmaps!
- }
- int x = (rpi->reflection_atlas_index % reflection_atlas->subdiv) * cell_size;
- int y = (rpi->reflection_atlas_index / reflection_atlas->subdiv) * cell_size;
- int width = cell_size;
- int height = cell_size;
-
- storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE, rpi->render_step == 0);
- storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, rpi->probe_ptr->update_mode == VS::REFLECTION_PROBE_UPDATE_ALWAYS);
- for (int i = 0; i < 2; i++) {
-
- storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i == 0);
- storage->shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, rpi->render_step / 5.0);
-
- uint32_t local_width = width, local_height = height;
- uint32_t local_x = x, local_y = y;
-
- local_height /= 2;
- local_y += i * local_height;
-
- glViewport(local_x, local_y, local_width, local_height);
-
- _copy_screen();
- }
- storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DIRECT_WRITE, false);
- storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, false);
-
- rpi->render_step++;
-
- return rpi->render_step == 6;
-}
-
-/* ENVIRONMENT API */
-
-RID RasterizerSceneGLES3::environment_create() {
-
- Environment *env = memnew(Environment);
-
- return environment_owner.make_rid(env);
-}
-
-void RasterizerSceneGLES3::environment_set_background(RID p_env, VS::EnvironmentBG p_bg) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
- env->bg_mode = p_bg;
-}
-
-void RasterizerSceneGLES3::environment_set_sky(RID p_env, RID p_sky) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->sky = p_sky;
-}
-
-void RasterizerSceneGLES3::environment_set_sky_custom_fov(RID p_env, float p_scale) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->sky_custom_fov = p_scale;
-}
-
-void RasterizerSceneGLES3::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->sky_orientation = p_orientation;
-}
-
-void RasterizerSceneGLES3::environment_set_bg_color(RID p_env, const Color &p_color) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->bg_color = p_color;
-}
-void RasterizerSceneGLES3::environment_set_bg_energy(RID p_env, float p_energy) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->bg_energy = p_energy;
-}
-
-void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->canvas_max_layer = p_max_layer;
-}
-void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy, float p_sky_contribution) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->ambient_color = p_color;
- env->ambient_energy = p_energy;
- env->ambient_sky_contribution = p_sky_contribution;
-}
-void RasterizerSceneGLES3::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) {
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->camera_feed_id = p_camera_feed_id;
-}
-
-void RasterizerSceneGLES3::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->dof_blur_far_enabled = p_enable;
- env->dof_blur_far_distance = p_distance;
- env->dof_blur_far_transition = p_transition;
- env->dof_blur_far_amount = p_amount;
- env->dof_blur_far_quality = p_quality;
-}
-
-void RasterizerSceneGLES3::environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->dof_blur_near_enabled = p_enable;
- env->dof_blur_near_distance = p_distance;
- env->dof_blur_near_transition = p_transition;
- env->dof_blur_near_amount = p_amount;
- env->dof_blur_near_quality = p_quality;
-}
-void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->glow_enabled = p_enable;
- env->glow_levels = p_level_flags;
- env->glow_intensity = p_intensity;
- env->glow_strength = p_strength;
- env->glow_bloom = p_bloom_threshold;
- env->glow_blend_mode = p_blend_mode;
- env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
- env->glow_hdr_bleed_scale = p_hdr_bleed_scale;
- env->glow_hdr_luminance_cap = p_hdr_luminance_cap;
- env->glow_bicubic_upscale = p_bicubic_upscale;
-}
-void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {
-}
-
-void RasterizerSceneGLES3::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->ssr_enabled = p_enable;
- env->ssr_max_steps = p_max_steps;
- env->ssr_fade_in = p_fade_in;
- env->ssr_fade_out = p_fade_out;
- env->ssr_depth_tolerance = p_depth_tolerance;
- env->ssr_roughness = p_roughness;
-}
-
-void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->ssao_enabled = p_enable;
- env->ssao_radius = p_radius;
- env->ssao_intensity = p_intensity;
- env->ssao_radius2 = p_radius2;
- env->ssao_intensity2 = p_intensity2;
- env->ssao_bias = p_bias;
- env->ssao_light_affect = p_light_affect;
- env->ssao_ao_channel_affect = p_ao_channel_affect;
- env->ssao_color = p_color;
- env->ssao_filter = p_blur;
- env->ssao_quality = p_quality;
- env->ssao_bilateral_sharpness = p_bilateral_sharpness;
-}
-
-void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->tone_mapper = p_tone_mapper;
- env->tone_mapper_exposure = p_exposure;
- env->tone_mapper_exposure_white = p_white;
- env->auto_exposure = p_auto_exposure;
- env->auto_exposure_speed = p_auto_exp_speed;
- env->auto_exposure_min = p_min_luminance;
- env->auto_exposure_max = p_max_luminance;
- env->auto_exposure_grey = p_auto_exp_scale;
-}
-
-void RasterizerSceneGLES3::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->adjustments_enabled = p_enable;
- env->adjustments_brightness = p_brightness;
- env->adjustments_contrast = p_contrast;
- env->adjustments_saturation = p_saturation;
- env->color_correction = p_ramp;
-}
-
-void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->fog_enabled = p_enable;
- env->fog_color = p_color;
- env->fog_sun_color = p_sun_color;
- env->fog_sun_amount = p_sun_amount;
-}
-
-void RasterizerSceneGLES3::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->fog_depth_enabled = p_enable;
- env->fog_depth_begin = p_depth_begin;
- env->fog_depth_end = p_depth_end;
- env->fog_depth_curve = p_depth_curve;
- env->fog_transmit_enabled = p_transmit;
- env->fog_transmit_curve = p_transmit_curve;
-}
-
-void RasterizerSceneGLES3::environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {
-
- Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND(!env);
-
- env->fog_height_enabled = p_enable;
- env->fog_height_min = p_min_height;
- env->fog_height_max = p_max_height;
- env->fog_height_curve = p_height_curve;
-}
-
-bool RasterizerSceneGLES3::is_environment(RID p_env) {
-
- return environment_owner.owns(p_env);
-}
-
-VS::EnvironmentBG RasterizerSceneGLES3::environment_get_background(RID p_env) {
-
- const Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX);
-
- return env->bg_mode;
-}
-
-int RasterizerSceneGLES3::environment_get_canvas_max_layer(RID p_env) {
-
- const Environment *env = environment_owner.getornull(p_env);
- ERR_FAIL_COND_V(!env, -1);
-
- return env->canvas_max_layer;
-}
-
-RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
-
- LightInstance *light_instance = memnew(LightInstance);
-
- light_instance->last_pass = 0;
- light_instance->last_scene_pass = 0;
- light_instance->last_scene_shadow_pass = 0;
-
- light_instance->light = p_light;
- light_instance->light_ptr = storage->light_owner.getornull(p_light);
-
- if (!light_instance->light_ptr) {
- memdelete(light_instance);
- ERR_FAIL_V_MSG(RID(), "Condition ' !light_instance->light_ptr ' is true.");
- }
-
- light_instance->self = light_instance_owner.make_rid(light_instance);
-
- return light_instance->self;
-}
-
-void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {
-
- LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- light_instance->transform = p_transform;
-}
-
-void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) {
-
- LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- if (light_instance->light_ptr->type != VS::LIGHT_DIRECTIONAL) {
- p_pass = 0;
- }
-
- ERR_FAIL_INDEX(p_pass, 4);
-
- light_instance->shadow_transform[p_pass].camera = p_projection;
- light_instance->shadow_transform[p_pass].transform = p_transform;
- light_instance->shadow_transform[p_pass].farplane = p_far;
- light_instance->shadow_transform[p_pass].split = p_split;
- light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;
-}
-
-void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) {
-
- LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- light_instance->last_scene_pass = scene_pass;
-}
-
-//////////////////////
-
-RID RasterizerSceneGLES3::gi_probe_instance_create() {
-
- GIProbeInstance *gipi = memnew(GIProbeInstance);
-
- return gi_probe_instance_owner.make_rid(gipi);
-}
-
-void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {
-
- GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
- ERR_FAIL_COND(!gipi);
- gipi->data = p_data;
- gipi->probe = storage->gi_probe_owner.getornull(p_base);
- if (p_data.is_valid()) {
- RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data);
- ERR_FAIL_COND(!gipd);
-
- gipi->tex_cache = gipd->tex_id;
- gipi->cell_size_cache.x = 1.0 / gipd->width;
- gipi->cell_size_cache.y = 1.0 / gipd->height;
- gipi->cell_size_cache.z = 1.0 / gipd->depth;
- }
-}
-void RasterizerSceneGLES3::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
-
- GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
- ERR_FAIL_COND(!gipi);
- gipi->transform_to_data = p_xform;
-}
-
-void RasterizerSceneGLES3::gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) {
-
- GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
- ERR_FAIL_COND(!gipi);
- gipi->bounds = p_bounds;
-}
-
-////////////////////////////
-////////////////////////////
-////////////////////////////
-
-bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_alpha_pass) {
-
- /* this is handled outside
- if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_DISABLED) {
- glDisable(GL_CULL_FACE);
- } else {
- glEnable(GL_CULL_FACE);
- } */
-
- if (state.current_line_width != p_material->line_width) {
- //glLineWidth(MAX(p_material->line_width,1.0));
- state.current_line_width = p_material->line_width;
- }
-
- if (state.current_depth_test != (!p_material->shader->spatial.no_depth_test)) {
- if (p_material->shader->spatial.no_depth_test) {
- glDisable(GL_DEPTH_TEST);
-
- } else {
- glEnable(GL_DEPTH_TEST);
- }
-
- state.current_depth_test = !p_material->shader->spatial.no_depth_test;
- }
-
- if (state.current_depth_draw != p_material->shader->spatial.depth_draw_mode) {
- switch (p_material->shader->spatial.depth_draw_mode) {
- case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS: {
- glDepthMask(p_depth_pass);
- // If some transparent objects write to depth, we need to re-copy depth texture when we need it
- if (p_alpha_pass && !state.used_depth_prepass) {
- state.prepared_depth_texture = false;
- }
- } break;
- case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_OPAQUE: {
-
- glDepthMask(!p_alpha_pass);
- } break;
- case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALWAYS: {
- glDepthMask(GL_TRUE);
- // If some transparent objects write to depth, we need to re-copy depth texture when we need it
- if (p_alpha_pass) {
- state.prepared_depth_texture = false;
- }
- } break;
- case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER: {
- glDepthMask(GL_FALSE);
- } break;
- }
-
- state.current_depth_draw = p_material->shader->spatial.depth_draw_mode;
- }
-
- //material parameters
-
- state.scene_shader.set_custom_shader(p_material->shader->custom_code_id);
- bool rebind = state.scene_shader.bind();
-
- if (p_material->ubo_id) {
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 1, p_material->ubo_id);
- }
-
- int tc = p_material->textures.size();
- RID *textures = p_material->textures.ptrw();
- ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptrw();
- const ShaderLanguage::DataType *texture_types = p_material->shader->texture_types.ptr();
-
- state.current_main_tex = 0;
-
- for (int i = 0; i < tc; i++) {
-
- glActiveTexture(GL_TEXTURE0 + i);
-
- GLenum target = GL_TEXTURE_2D;
- GLuint tex = 0;
-
- RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(textures[i]);
-
- if (t) {
-
- if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies
- VisualServerRaster::redraw_request();
- }
-
- t = t->get_ptr(); //resolve for proxies
-
-#ifdef TOOLS_ENABLED
- if (t->detect_3d) {
- t->detect_3d(t->detect_3d_ud);
- }
-#endif
-
-#ifdef TOOLS_ENABLED
- if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) {
- t->detect_normal(t->detect_normal_ud);
- }
-#endif
- if (t->render_target)
- t->render_target->used_in_frame = true;
-
- target = t->target;
- tex = t->tex_id;
- } else {
-
- switch (texture_types[i]) {
- case ShaderLanguage::TYPE_ISAMPLER2D:
- case ShaderLanguage::TYPE_USAMPLER2D:
- case ShaderLanguage::TYPE_SAMPLER2D: {
- target = GL_TEXTURE_2D;
-
- switch (texture_hints[i]) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
- tex = storage->resources.black_tex;
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
- tex = storage->resources.aniso_tex;
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- tex = storage->resources.normal_tex;
-
- } break;
- default: {
- tex = storage->resources.white_tex;
- } break;
- }
-
- } break;
-
- case ShaderLanguage::TYPE_SAMPLERCUBE: {
- // TODO
- } break;
-
- case ShaderLanguage::TYPE_ISAMPLER3D:
- case ShaderLanguage::TYPE_USAMPLER3D:
- case ShaderLanguage::TYPE_SAMPLER3D: {
-
- target = GL_TEXTURE_3D;
- tex = storage->resources.white_tex_3d;
-
- //switch (texture_hints[i]) {
- // TODO
- //}
-
- } break;
-
- case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
- case ShaderLanguage::TYPE_USAMPLER2DARRAY:
- case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
-
- target = GL_TEXTURE_2D_ARRAY;
- tex = storage->resources.white_tex_array;
-
- //switch (texture_hints[i]) {
- // TODO
- //}
-
- } break;
-
- default: {
- }
- }
- }
-
- glBindTexture(target, tex);
-
- if (t && storage->config.srgb_decode_supported) {
- //if SRGB decode extension is present, simply switch the texture to whathever is needed
- bool must_srgb = false;
-
- if (t->srgb && (texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) {
- must_srgb = true;
- }
-
- if (t->using_srgb != must_srgb) {
- if (must_srgb) {
- glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT);
-#ifdef TOOLS_ENABLED
- if (t->detect_srgb) {
- t->detect_srgb(t->detect_srgb_ud);
- }
-#endif
-
- } else {
- glTexParameteri(t->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT);
- }
- t->using_srgb = must_srgb;
- }
- }
-
- if (i == 0) {
- state.current_main_tex = tex;
- }
- }
-
- return rebind;
-}
-
-struct RasterizerGLES3Particle {
-
- float color[4];
- float velocity_active[4];
- float custom[4];
- float xform_1[4];
- float xform_2[4];
- float xform_3[4];
-};
-
-struct RasterizerGLES3ParticleSort {
-
- Vector3 z_dir;
- bool operator()(const RasterizerGLES3Particle &p_a, const RasterizerGLES3Particle &p_b) const {
-
- return z_dir.dot(Vector3(p_a.xform_1[3], p_a.xform_2[3], p_a.xform_3[3])) < z_dir.dot(Vector3(p_b.xform_1[3], p_b.xform_2[3], p_b.xform_3[3]));
- }
-};
-
-void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transform &p_view_transform) {
-
- switch (e->instance->base_type) {
-
- case VS::INSTANCE_MESH: {
-
- RasterizerStorageGLES3::Surface *s = static_cast(e->geometry);
-
- if (s->blend_shapes.size() && e->instance->blend_values.size()) {
- //blend shapes, use transform feedback
- storage->mesh_render_blend_shapes(s, e->instance->blend_values.ptr());
- //rebind shader
- state.scene_shader.bind();
-#ifdef DEBUG_ENABLED
- } else if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) {
- glBindVertexArray(s->array_wireframe_id); // everything is so easy nowadays
-#endif
- } else {
- glBindVertexArray(s->array_id); // everything is so easy nowadays
- }
-
- } break;
-
- case VS::INSTANCE_MULTIMESH: {
-
- RasterizerStorageGLES3::MultiMesh *multi_mesh = static_cast(e->owner);
- RasterizerStorageGLES3::Surface *s = static_cast(e->geometry);
-#ifdef DEBUG_ENABLED
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) {
-
- glBindVertexArray(s->instancing_array_wireframe_id); // use the instancing array ID
- } else
-#endif
- {
- glBindVertexArray(s->instancing_array_id); // use the instancing array ID
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer
-
- int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4;
- glEnableVertexAttribArray(8);
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, NULL);
- glVertexAttribDivisor(8, 1);
- glEnableVertexAttribArray(9);
- glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4));
- glVertexAttribDivisor(9, 1);
-
- int color_ofs;
-
- if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) {
- glEnableVertexAttribArray(10);
- glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4));
- glVertexAttribDivisor(10, 1);
- color_ofs = 12 * 4;
- } else {
- glDisableVertexAttribArray(10);
- glVertexAttrib4f(10, 0, 0, 1, 0);
- color_ofs = 8 * 4;
- }
-
- int custom_data_ofs = color_ofs;
-
- switch (multi_mesh->color_format) {
-
- case VS::MULTIMESH_COLOR_MAX:
- case VS::MULTIMESH_COLOR_NONE: {
- glDisableVertexAttribArray(11);
- glVertexAttrib4f(11, 1, 1, 1, 1);
- } break;
- case VS::MULTIMESH_COLOR_8BIT: {
- glEnableVertexAttribArray(11);
- glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs));
- glVertexAttribDivisor(11, 1);
- custom_data_ofs += 4;
-
- } break;
- case VS::MULTIMESH_COLOR_FLOAT: {
- glEnableVertexAttribArray(11);
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs));
- glVertexAttribDivisor(11, 1);
- custom_data_ofs += 4 * 4;
- } break;
- }
-
- switch (multi_mesh->custom_data_format) {
-
- case VS::MULTIMESH_CUSTOM_DATA_MAX:
- case VS::MULTIMESH_CUSTOM_DATA_NONE: {
- glDisableVertexAttribArray(12);
- glVertexAttrib4f(12, 1, 1, 1, 1);
- } break;
- case VS::MULTIMESH_CUSTOM_DATA_8BIT: {
- glEnableVertexAttribArray(12);
- glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs));
- glVertexAttribDivisor(12, 1);
-
- } break;
- case VS::MULTIMESH_CUSTOM_DATA_FLOAT: {
- glEnableVertexAttribArray(12);
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs));
- glVertexAttribDivisor(12, 1);
- } break;
- }
-
- } break;
- case VS::INSTANCE_PARTICLES: {
-
- RasterizerStorageGLES3::Particles *particles = static_cast(e->owner);
- RasterizerStorageGLES3::Surface *s = static_cast(e->geometry);
-
- if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) {
-
- glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing
- RasterizerGLES3Particle *particle_array;
-#ifndef __EMSCRIPTEN__
- particle_array = static_cast(glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
-#else
- PoolVector particle_vector;
- particle_vector.resize(particles->amount);
- PoolVector::Write particle_writer = particle_vector.write();
- particle_array = particle_writer.ptr();
- glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), particle_array);
-#endif
-
- SortArray sorter;
-
- if (particles->use_local_coords) {
- sorter.compare.z_dir = e->instance->transform.affine_inverse().xform(p_view_transform.basis.get_axis(2)).normalized();
- } else {
- sorter.compare.z_dir = p_view_transform.basis.get_axis(2).normalized();
- }
-
- sorter.sort(particle_array, particles->amount);
-
-#ifndef __EMSCRIPTEN__
- glUnmapBuffer(GL_ARRAY_BUFFER);
-#else
- particle_writer.release();
- particle_array = NULL;
- {
- PoolVector::Read r = particle_vector.read();
- glBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), r.ptr());
- }
- particle_vector = PoolVector();
-#endif
-#ifdef DEBUG_ENABLED
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) {
- glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID
- } else
-#endif
- {
-
- glBindVertexArray(s->instancing_array_id); // use the instancing array ID
- }
- glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer
-
- } else {
-#ifdef DEBUG_ENABLED
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) {
- glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID
- } else
-#endif
- {
- glBindVertexArray(s->instancing_array_id); // use the instancing array ID
- }
- glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //modify the buffer
- }
-
- int stride = sizeof(float) * 4 * 6;
-
- //transform
-
- if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) {
-
- glEnableVertexAttribArray(8); //xform x
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3));
- glVertexAttribDivisor(8, 1);
- glEnableVertexAttribArray(9); //xform y
- glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4));
- glVertexAttribDivisor(9, 1);
- glEnableVertexAttribArray(10); //xform z
- glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5));
- glVertexAttribDivisor(10, 1);
- glEnableVertexAttribArray(11); //color
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL);
- glVertexAttribDivisor(11, 1);
- glEnableVertexAttribArray(12); //custom
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2));
- glVertexAttribDivisor(12, 1);
- }
-
- } break;
- default: {
- }
- }
-}
-
-static const GLenum gl_primitive[] = {
- GL_POINTS,
- GL_LINES,
- GL_LINE_STRIP,
- GL_LINE_LOOP,
- GL_TRIANGLES,
- GL_TRIANGLE_STRIP,
- GL_TRIANGLE_FAN
-};
-
-void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
-
- switch (e->instance->base_type) {
-
- case VS::INSTANCE_MESH: {
-
- RasterizerStorageGLES3::Surface *s = static_cast(e->geometry);
-
-#ifdef DEBUG_ENABLED
-
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) {
-
- glDrawElements(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0);
- storage->info.render.vertices_count += s->index_array_len;
- } else
-#endif
- if (s->index_array_len > 0) {
-
- glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0);
-
- storage->info.render.vertices_count += s->index_array_len;
-
- } else {
-
- glDrawArrays(gl_primitive[s->primitive], 0, s->array_len);
-
- storage->info.render.vertices_count += s->array_len;
- }
-
- } break;
- case VS::INSTANCE_MULTIMESH: {
-
- RasterizerStorageGLES3::MultiMesh *multi_mesh = static_cast(e->owner);
- RasterizerStorageGLES3::Surface *s = static_cast(e->geometry);
-
- int amount = MIN(multi_mesh->size, multi_mesh->visible_instances);
-
- if (amount == -1) {
- amount = multi_mesh->size;
- }
-#ifdef DEBUG_ENABLED
-
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) {
-
- glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount);
- storage->info.render.vertices_count += s->index_array_len * amount;
- } else
-#endif
- if (s->index_array_len > 0) {
-
- glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);
-
- storage->info.render.vertices_count += s->index_array_len * amount;
-
- } else {
-
- glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount);
-
- storage->info.render.vertices_count += s->array_len * amount;
- }
-
- } break;
- case VS::INSTANCE_IMMEDIATE: {
-
- bool restore_tex = false;
- const RasterizerStorageGLES3::Immediate *im = static_cast(e->geometry);
-
- if (im->building) {
- return;
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer);
- glBindVertexArray(state.immediate_array);
-
- for (const List::Element *E = im->chunks.front(); E; E = E->next()) {
-
- const RasterizerStorageGLES3::Immediate::Chunk &c = E->get();
- if (c.vertices.empty()) {
- continue;
- }
-
- int vertices = c.vertices.size();
- uint32_t buf_ofs = 0;
-
- storage->info.render.vertices_count += vertices;
-
- if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) {
-
- RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(c.texture);
-
- if (t->redraw_if_visible) {
- VisualServerRaster::redraw_request();
- }
- t = t->get_ptr(); //resolve for proxies
-
-#ifdef TOOLS_ENABLED
- if (t->detect_3d) {
- t->detect_3d(t->detect_3d_ud);
- }
-#endif
-
- if (t->render_target) {
- t->render_target->used_in_frame = true;
- }
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(t->target, t->tex_id);
- restore_tex = true;
-
- } else if (restore_tex) {
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, state.current_main_tex);
- restore_tex = false;
- }
-
- if (!c.normals.empty()) {
-
- glEnableVertexAttribArray(VS::ARRAY_NORMAL);
- glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.normals.ptr());
- glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs));
- buf_ofs += sizeof(Vector3) * vertices;
-
- } else {
-
- glDisableVertexAttribArray(VS::ARRAY_NORMAL);
- }
-
- if (!c.tangents.empty()) {
-
- glEnableVertexAttribArray(VS::ARRAY_TANGENT);
- glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Plane) * vertices, c.tangents.ptr());
- glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false, sizeof(Plane), CAST_INT_TO_UCHAR_PTR(buf_ofs));
- buf_ofs += sizeof(Plane) * vertices;
-
- } else {
-
- glDisableVertexAttribArray(VS::ARRAY_TANGENT);
- }
-
- if (!c.colors.empty()) {
-
- glEnableVertexAttribArray(VS::ARRAY_COLOR);
- glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Color) * vertices, c.colors.ptr());
- glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buf_ofs));
- buf_ofs += sizeof(Color) * vertices;
-
- } else {
-
- glDisableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
- }
-
- if (!c.uvs.empty()) {
-
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs.ptr());
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs));
- buf_ofs += sizeof(Vector2) * vertices;
-
- } else {
-
- glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
- }
-
- if (!c.uvs2.empty()) {
-
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV2);
- glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs2.ptr());
- glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs));
- buf_ofs += sizeof(Vector2) * vertices;
-
- } else {
-
- glDisableVertexAttribArray(VS::ARRAY_TEX_UV2);
- }
-
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.vertices.ptr());
- glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs));
- glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size());
- }
-
- if (restore_tex) {
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, state.current_main_tex);
- restore_tex = false;
- }
- } break;
- case VS::INSTANCE_PARTICLES: {
-
- RasterizerStorageGLES3::Particles *particles = static_cast(e->owner);
- RasterizerStorageGLES3::Surface *s = static_cast(e->geometry);
-
- if (!particles->use_local_coords) //not using local coordinates? then clear transform..
- state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, Transform());
-
- int amount = particles->amount;
-
- if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_LIFETIME) {
- //split
-
- int stride = sizeof(float) * 4 * 6;
- int split = int(Math::ceil(particles->phase * particles->amount));
-
- if (amount - split > 0) {
- glEnableVertexAttribArray(8); //xform x
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3));
- glVertexAttribDivisor(8, 1);
- glEnableVertexAttribArray(9); //xform y
- glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4));
- glVertexAttribDivisor(9, 1);
- glEnableVertexAttribArray(10); //xform z
- glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5));
- glVertexAttribDivisor(10, 1);
- glEnableVertexAttribArray(11); //color
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0));
- glVertexAttribDivisor(11, 1);
- glEnableVertexAttribArray(12); //custom
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2));
- glVertexAttribDivisor(12, 1);
-#ifdef DEBUG_ENABLED
-
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) {
-
- glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount - split);
- storage->info.render.vertices_count += s->index_array_len * (amount - split);
- } else
-#endif
- if (s->index_array_len > 0) {
-
- glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount - split);
-
- storage->info.render.vertices_count += s->index_array_len * (amount - split);
-
- } else {
-
- glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount - split);
-
- storage->info.render.vertices_count += s->array_len * (amount - split);
- }
- }
-
- if (split > 0) {
- glEnableVertexAttribArray(8); //xform x
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3));
- glVertexAttribDivisor(8, 1);
- glEnableVertexAttribArray(9); //xform y
- glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4));
- glVertexAttribDivisor(9, 1);
- glEnableVertexAttribArray(10); //xform z
- glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5));
- glVertexAttribDivisor(10, 1);
- glEnableVertexAttribArray(11); //color
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL);
- glVertexAttribDivisor(11, 1);
- glEnableVertexAttribArray(12); //custom
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2));
- glVertexAttribDivisor(12, 1);
-#ifdef DEBUG_ENABLED
-
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) {
-
- glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, split);
- storage->info.render.vertices_count += s->index_array_len * split;
- } else
-#endif
- if (s->index_array_len > 0) {
-
- glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, split);
-
- storage->info.render.vertices_count += s->index_array_len * split;
-
- } else {
-
- glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, split);
-
- storage->info.render.vertices_count += s->array_len * split;
- }
- }
-
- } else {
-
-#ifdef DEBUG_ENABLED
-
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) {
-
- glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount);
- storage->info.render.vertices_count += s->index_array_len * amount;
- } else
-#endif
-
- if (s->index_array_len > 0) {
-
- glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);
-
- storage->info.render.vertices_count += s->index_array_len * amount;
-
- } else {
-
- glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount);
-
- storage->info.render.vertices_count += s->array_len * amount;
- }
- }
-
- } break;
- default: {
- }
- }
-}
-
-void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform &p_view_transform) {
-
- int omni_indices[16];
- int omni_count = 0;
- int spot_indices[16];
- int spot_count = 0;
- int reflection_indices[16];
- int reflection_count = 0;
-
- int maxobj = MIN(16, state.max_forward_lights_per_object);
-
- int lc = e->instance->light_instances.size();
- if (lc) {
-
- const RID *lights = e->instance->light_instances.ptr();
-
- for (int i = 0; i < lc; i++) {
- LightInstance *li = light_instance_owner.getornull(lights[i]);
- if (!li || li->last_pass != render_pass) //not visible
- continue;
-
- if (li && li->light_ptr->type == VS::LIGHT_OMNI) {
- if (omni_count < maxobj && e->instance->layer_mask & li->light_ptr->cull_mask) {
- omni_indices[omni_count++] = li->light_index;
- }
- }
-
- if (li && li->light_ptr->type == VS::LIGHT_SPOT) {
- if (spot_count < maxobj && e->instance->layer_mask & li->light_ptr->cull_mask) {
- spot_indices[spot_count++] = li->light_index;
- }
- }
- }
- }
-
- state.scene_shader.set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, omni_count);
-
- if (omni_count) {
- glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES), omni_count, omni_indices);
- }
-
- state.scene_shader.set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, spot_count);
- if (spot_count) {
- glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES), spot_count, spot_indices);
- }
-
- int rc = e->instance->reflection_probe_instances.size();
-
- if (rc) {
-
- const RID *reflections = e->instance->reflection_probe_instances.ptr();
-
- for (int i = 0; i < rc; i++) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(reflections[i]);
- if (rpi->last_pass != render_pass) //not visible
- continue;
-
- if (reflection_count < maxobj) {
- reflection_indices[reflection_count++] = rpi->reflection_index;
- }
- }
- }
-
- state.scene_shader.set_uniform(SceneShaderGLES3::REFLECTION_COUNT, reflection_count);
- if (reflection_count) {
- glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::REFLECTION_INDICES), reflection_count, reflection_indices);
- }
-
- int gi_probe_count = e->instance->gi_probe_instances.size();
- if (gi_probe_count) {
- const RID *ridp = e->instance->gi_probe_instances.ptr();
-
- GIProbeInstance *gipi = gi_probe_instance_owner.getornull(ridp[0]);
-
- float bias_scale = e->instance->baked_light ? 1 : 0;
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 9);
- glBindTexture(GL_TEXTURE_3D, gipi->tex_cache);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER1, gipi->probe ? gipi->probe->dynamic_range * gipi->probe->energy : 0.0);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS1, gipi->probe ? gipi->probe->bias * bias_scale : 0.0);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_NORMAL_BIAS1, gipi->probe ? gipi->probe->normal_bias * bias_scale : 0.0);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT1, gipi->probe ? !gipi->probe->interior : false);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache);
- if (gi_probe_count > 1) {
-
- GIProbeInstance *gipi2 = gi_probe_instance_owner.getornull(ridp[1]);
-
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 10);
- glBindTexture(GL_TEXTURE_3D, gipi2->tex_cache);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER2, gipi2->probe ? gipi2->probe->dynamic_range * gipi2->probe->energy : 0.0);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS2, gipi2->probe ? gipi2->probe->bias * bias_scale : 0.0);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_NORMAL_BIAS2, gipi2->probe ? gipi2->probe->normal_bias * bias_scale : 0.0);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT2, gipi2->probe ? !gipi2->probe->interior : false);
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true);
- } else {
-
- state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, false);
- }
- } else if (!e->instance->lightmap_capture_data.empty()) {
-
- glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES3::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr());
- state.scene_shader.set_uniform(SceneShaderGLES3::LIGHTMAP_CAPTURE_SKY, false);
-
- } else if (e->instance->lightmap.is_valid()) {
- RasterizerStorageGLES3::Texture *lightmap = storage->texture_owner.getornull(e->instance->lightmap);
- RasterizerStorageGLES3::LightmapCapture *capture = storage->lightmap_capture_data_owner.getornull(e->instance->lightmap_capture->base);
-
- if (lightmap && capture) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 9);
- glBindTexture(GL_TEXTURE_2D, lightmap->tex_id);
- state.scene_shader.set_uniform(SceneShaderGLES3::LIGHTMAP_ENERGY, capture->energy);
- }
- }
-}
-
-void RasterizerSceneGLES3::_set_cull(bool p_front, bool p_disabled, bool p_reverse_cull) {
-
- bool front = p_front;
- if (p_reverse_cull)
- front = !front;
-
- if (p_disabled != state.cull_disabled) {
- if (p_disabled)
- glDisable(GL_CULL_FACE);
- else
- glEnable(GL_CULL_FACE);
-
- state.cull_disabled = p_disabled;
- }
-
- if (front != state.cull_front) {
-
- glCullFace(front ? GL_FRONT : GL_BACK);
- state.cull_front = front;
- }
-}
-
-void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RasterizerStorageGLES3::Sky *p_sky, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) {
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.scene_ubo); //bind globals ubo
-
- bool use_radiance_map = false;
- if (!p_shadow && !p_directional_add) {
- glBindBufferBase(GL_UNIFORM_BUFFER, 2, state.env_radiance_ubo); //bind environment radiance info
-
- if (p_sky != NULL) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
- if (storage->config.use_texture_array_environment) {
- glBindTexture(GL_TEXTURE_2D_ARRAY, p_sky->radiance);
- } else {
- glBindTexture(GL_TEXTURE_2D, p_sky->radiance);
- }
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
- glBindTexture(GL_TEXTURE_2D, p_sky->irradiance);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, true);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, storage->config.use_texture_array_environment);
- use_radiance_map = true;
- } else {
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, false);
- }
- } else {
-
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, false);
- }
-
- state.cull_front = false;
- state.cull_disabled = false;
- glCullFace(GL_BACK);
- glEnable(GL_CULL_FACE);
-
- state.current_depth_test = true;
- glEnable(GL_DEPTH_TEST);
-
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, false);
-
- state.current_blend_mode = -1;
- state.current_line_width = -1;
- state.current_depth_draw = -1;
-
- RasterizerStorageGLES3::Material *prev_material = NULL;
- RasterizerStorageGLES3::Geometry *prev_geometry = NULL;
- RasterizerStorageGLES3::GeometryOwner *prev_owner = NULL;
- VS::InstanceType prev_base_type = VS::INSTANCE_MAX;
-
- int current_blend_mode = -1;
-
- int prev_shading = -1;
- RasterizerStorageGLES3::Skeleton *prev_skeleton = NULL;
-
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, true); //by default unshaded (easier to set)
-
- bool first = true;
- bool prev_use_instancing = false;
-
- storage->info.render.draw_call_count += p_element_count;
- bool prev_opaque_prepass = false;
-
- for (int i = 0; i < p_element_count; i++) {
-
- RenderList::Element *e = p_elements[i];
- RasterizerStorageGLES3::Material *material = e->material;
- RasterizerStorageGLES3::Skeleton *skeleton = NULL;
- if (e->instance->skeleton.is_valid()) {
- skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
- }
-
- bool rebind = first;
-
- int shading = (e->sort_key >> RenderList::SORT_KEY_SHADING_SHIFT) & RenderList::SORT_KEY_SHADING_MASK;
-
- if (!p_shadow) {
-
- if (p_directional_add) {
- if (e->sort_key & SORT_KEY_UNSHADED_FLAG || !(e->instance->layer_mask & directional_light->light_ptr->cull_mask)) {
- continue;
- }
-
- shading &= ~1; //ignore the ignore directional for base pass
- }
-
- if (shading != prev_shading) {
-
- if (e->sort_key & SORT_KEY_UNSHADED_FLAG) {
-
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, true);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP_CAPTURE, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false);
-
- //state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true);
- } else {
-
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, e->instance->gi_probe_instances.size() > 0);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP, e->instance->lightmap.is_valid() && e->instance->gi_probe_instances.size() == 0);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP_CAPTURE, !e->instance->lightmap_capture_data.empty() && !e->instance->lightmap.is_valid() && e->instance->gi_probe_instances.size() == 0);
-
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, false);
-
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING, !p_directional_add);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, (e->sort_key & SORT_KEY_VERTEX_LIT_FLAG));
-
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5);
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, use_radiance_map);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, state.used_contact_shadows);
-
- if (p_directional_add || (directional_light && (e->sort_key & SORT_KEY_NO_DIRECTIONAL_FLAG) == 0)) {
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, true);
-
- if (p_directional_shadows && directional_light->light_ptr->shadow) {
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, true);
-
- switch (directional_light->light_ptr->directional_shadow_mode) {
- case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
- break; //none
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, true);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits);
- break;
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, true);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits);
- break;
- }
- }
- }
- }
-
- rebind = true;
- }
-
- if (p_alpha_pass || p_directional_add) {
- int desired_blend_mode;
- if (p_directional_add) {
- desired_blend_mode = RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD;
- } else {
- desired_blend_mode = material->shader->spatial.blend_mode;
- }
-
- if (desired_blend_mode != current_blend_mode) {
-
- switch (desired_blend_mode) {
-
- case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX: {
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- } break;
- case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_ADD: {
-
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(p_alpha_pass ? GL_SRC_ALPHA : GL_ONE, GL_ONE);
-
- } break;
- case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_SUB: {
-
- glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- } break;
- case RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MUL: {
- glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
- } else {
- glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
- }
-
- } break;
- }
-
- current_blend_mode = desired_blend_mode;
- }
- }
- }
-
- bool use_opaque_prepass = e->sort_key & RenderList::SORT_KEY_OPAQUE_PRE_PASS;
-
- if (use_opaque_prepass != prev_opaque_prepass) {
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, use_opaque_prepass);
- rebind = true;
- }
-
- bool use_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH || e->instance->base_type == VS::INSTANCE_PARTICLES;
-
- if (use_instancing != prev_use_instancing) {
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, use_instancing);
- rebind = true;
- }
-
- if (prev_skeleton != skeleton) {
- if ((prev_skeleton == NULL) != (skeleton == NULL)) {
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, skeleton != NULL);
- rebind = true;
- }
-
- if (skeleton) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
- glBindTexture(GL_TEXTURE_2D, skeleton->texture);
- }
- }
-
- if (material != prev_material || rebind) {
-
- storage->info.render.material_switch_count++;
-
- rebind = _setup_material(material, use_opaque_prepass, p_alpha_pass);
-
- if (rebind) {
- storage->info.render.shader_rebind_count++;
- }
- }
-
- if (!(e->sort_key & SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) {
- _setup_light(e, p_view_transform);
- }
-
- if (e->owner != prev_owner || prev_base_type != e->instance->base_type || prev_geometry != e->geometry) {
-
- _setup_geometry(e, p_view_transform);
- storage->info.render.surface_switch_count++;
- }
-
- _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, e->sort_key & RenderList::SORT_KEY_CULL_DISABLED_FLAG, p_reverse_cull);
-
- state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform);
-
- _render_geometry(e);
-
- prev_material = material;
- prev_base_type = e->instance->base_type;
- prev_geometry = e->geometry;
- prev_owner = e->owner;
- prev_shading = shading;
- prev_skeleton = skeleton;
- prev_use_instancing = use_instancing;
- prev_opaque_prepass = use_opaque_prepass;
- first = false;
- }
-
- glBindVertexArray(0);
-
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHTMAP_CAPTURE, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, false);
-}
-
-void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass) {
-
- RasterizerStorageGLES3::Material *m = NULL;
- RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : (p_material >= 0 ? p_instance->materials[p_material] : p_geometry->material);
-
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
- m_src = default_overdraw_material;
- }
-
- /*
-#ifdef DEBUG_ENABLED
- if (current_debug==VS::SCENARIO_DEBUG_OVERDRAW) {
- m_src=overdraw_material;
- }
-
-#endif
-*/
-
- if (m_src.is_valid()) {
- m = storage->material_owner.getornull(m_src);
-
- if (!m->shader || !m->shader->valid) {
- m = NULL;
- }
- }
-
- if (!m) {
- m = storage->material_owner.getornull(default_material);
- }
-
- ERR_FAIL_COND(!m);
-
- _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass);
-
- while (m->next_pass.is_valid()) {
- m = storage->material_owner.getornull(m->next_pass);
- if (!m || !m->shader || !m->shader->valid)
- break;
- _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass);
- }
-}
-
-void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_shadow_pass) {
-
- bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture || p_material->shader->spatial.uses_depth_texture;
- bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX;
- bool has_alpha = has_base_alpha || has_blend_alpha;
-
- bool mirror = p_instance->mirror;
- bool no_cull = false;
-
- if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_DISABLED) {
- no_cull = true;
- mirror = false;
- } else if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_FRONT) {
- mirror = !mirror;
- }
-
- if (p_material->shader->spatial.uses_sss) {
- state.used_sss = true;
- }
-
- if (p_material->shader->spatial.uses_screen_texture) {
- state.used_screen_texture = true;
- }
-
- if (p_material->shader->spatial.uses_depth_texture) {
- state.used_depth_texture = true;
- }
-
- if (p_depth_pass) {
-
- if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) || p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER || p_material->shader->spatial.no_depth_test || p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF)
- return; //bye
-
- if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
- //shader does not use discard and does not write a vertex position, use generic material
- if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
- p_material = storage->material_owner.getornull(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material_twosided : default_material_twosided);
- no_cull = true;
- mirror = false;
- } else {
- p_material = storage->material_owner.getornull(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material : default_material);
- }
- }
-
- has_alpha = false;
- }
-
- RenderList::Element *e = (has_alpha || p_material->shader->spatial.no_depth_test) ? render_list.add_alpha_element() : render_list.add_element();
-
- if (!e)
- return;
-
- e->geometry = p_geometry;
- e->material = p_material;
- e->instance = p_instance;
- e->owner = p_owner;
- e->sort_key = 0;
-
- if (e->geometry->last_pass != render_pass) {
- e->geometry->last_pass = render_pass;
- e->geometry->index = current_geometry_index++;
- }
-
- if (!p_depth_pass && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) {
- e->sort_key |= SORT_KEY_NO_DIRECTIONAL_FLAG;
- }
-
- e->sort_key |= uint64_t(e->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
- e->sort_key |= uint64_t(e->instance->base_type) << RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
-
- if (e->material->last_pass != render_pass) {
- e->material->last_pass = render_pass;
- e->material->index = current_material_index++;
- }
-
- e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
- e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT;
-
- if (!p_depth_pass) {
-
- if (e->instance->gi_probe_instances.size()) {
- e->sort_key |= SORT_KEY_GI_PROBES_FLAG;
- }
-
- if (e->instance->lightmap.is_valid()) {
- e->sort_key |= SORT_KEY_LIGHTMAP_FLAG;
- }
-
- if (!e->instance->lightmap_capture_data.empty()) {
- e->sort_key |= SORT_KEY_LIGHTMAP_CAPTURE_FLAG;
- }
-
- e->sort_key |= (uint64_t(p_material->render_priority) + 128) << RenderList::SORT_KEY_PRIORITY_SHIFT;
- }
-
- /*
- if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE)
- e->sort_flags|=RenderList::SORT_FLAG_INSTANCING;
- */
-
- if (mirror) {
- e->sort_key |= RenderList::SORT_KEY_MIRROR_FLAG;
- }
-
- if (no_cull) {
- e->sort_key |= RenderList::SORT_KEY_CULL_DISABLED_FLAG;
- }
-
- //e->light_type=0xFF; // no lights!
-
- if (p_depth_pass || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
- e->sort_key |= SORT_KEY_UNSHADED_FLAG;
- }
-
- if (p_depth_pass && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
- e->sort_key |= RenderList::SORT_KEY_OPAQUE_PRE_PASS;
- }
-
- if (!p_depth_pass && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
-
- e->sort_key |= SORT_KEY_VERTEX_LIT_FLAG;
- }
-
- if (p_material->shader->spatial.uses_time) {
- VisualServerRaster::redraw_request();
- }
-}
-
-void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation) {
-
- ERR_FAIL_COND(!p_sky);
-
- RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_sky->panorama);
-
- ERR_FAIL_COND(!tex);
- glActiveTexture(GL_TEXTURE0);
-
- tex = tex->get_ptr(); //resolve for proxies
-
- glBindTexture(tex->target, tex->tex_id);
-
- if (storage->config.srgb_decode_supported && tex->srgb && !tex->using_srgb) {
-
- glTexParameteri(tex->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT);
- tex->using_srgb = true;
-#ifdef TOOLS_ENABLED
- if (!(tex->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
- tex->flags |= VS::TEXTURE_FLAG_CONVERT_TO_LINEAR;
- //notify that texture must be set to linear beforehand, so it works in other platforms when exported
- }
-#endif
- }
-
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthFunc(GL_LEQUAL);
- glColorMask(1, 1, 1, 1);
-
- // Camera
- CameraMatrix camera;
-
- if (p_custom_fov) {
-
- float near_plane = p_projection.get_z_near();
- float far_plane = p_projection.get_z_far();
- float aspect = p_projection.get_aspect();
-
- camera.set_perspective(p_custom_fov, aspect, near_plane, far_plane);
-
- } else {
- camera = p_projection;
- }
-
- float flip_sign = p_vflip ? -1 : 1;
-
- /*
- If matrix[2][0] or matrix[2][1] we're dealing with an asymmetrical projection matrix. This is the case for stereoscopic rendering (i.e. VR).
- To ensure the image rendered is perspective correct we need to move some logic into the shader. For this the USE_ASYM_PANO option is introduced.
- It also means the uv coordinates are ignored in this mode and we don't need our loop.
- */
- bool asymmetrical = ((camera.matrix[2][0] != 0.0) || (camera.matrix[2][1] != 0.0));
-
- Vector3 vertices[8] = {
- Vector3(-1, -1 * flip_sign, 1),
- Vector3(0, 1, 0),
- Vector3(1, -1 * flip_sign, 1),
- Vector3(1, 1, 0),
- Vector3(1, 1 * flip_sign, 1),
- Vector3(1, 0, 0),
- Vector3(-1, 1 * flip_sign, 1),
- Vector3(0, 0, 0)
- };
-
- if (!asymmetrical) {
- Vector2 vp_he = camera.get_viewport_half_extents();
- float zn;
- zn = p_projection.get_z_near();
-
- for (int i = 0; i < 4; i++) {
- Vector3 uv = vertices[i * 2 + 1];
- uv.x = (uv.x * 2.0 - 1.0) * vp_he.x;
- uv.y = -(uv.y * 2.0 - 1.0) * vp_he.y;
- uv.z = -zn;
- vertices[i * 2 + 1] = p_transform.basis.xform(uv).normalized();
- vertices[i * 2 + 1].z = -vertices[i * 2 + 1].z;
- }
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts);
- glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, vertices, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- glBindVertexArray(state.sky_array);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_ASYM_PANO, asymmetrical);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, !asymmetrical);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, true);
- storage->shaders.copy.bind();
-
- storage->shaders.copy.set_uniform(CopyShaderGLES3::MULTIPLIER, p_energy);
-
- // don't know why but I always have problems setting a uniform mat3, so we're using a transform
- storage->shaders.copy.set_uniform(CopyShaderGLES3::SKY_TRANSFORM, Transform(p_sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse());
-
- if (asymmetrical) {
- // pack the bits we need from our projection matrix
- storage->shaders.copy.set_uniform(CopyShaderGLES3::ASYM_PROJ, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1]);
- ///@TODO I couldn't get mat3 + p_transform.basis to work, that would be better here.
- storage->shaders.copy.set_uniform(CopyShaderGLES3::PANO_TRANSFORM, p_transform);
- }
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- glBindVertexArray(0);
- glColorMask(1, 1, 1, 1);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_ASYM_PANO, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_MULTIPLIER, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false);
-}
-
-void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) {
- Transform sky_orientation;
-
- //store camera into ubo
- store_camera(p_cam_projection, state.ubo_data.projection_matrix);
- store_camera(p_cam_projection.inverse(), state.ubo_data.inv_projection_matrix);
- store_transform(p_cam_transform, state.ubo_data.camera_matrix);
- store_transform(p_cam_transform.affine_inverse(), state.ubo_data.camera_inverse_matrix);
-
- //time global variables
- state.ubo_data.time = storage->frame.time[0];
-
- state.ubo_data.z_far = p_cam_projection.get_z_far();
- //bg and ambient
- if (env) {
- state.ubo_data.bg_energy = env->bg_energy;
- state.ubo_data.ambient_energy = env->ambient_energy;
- Color linear_ambient_color = env->ambient_color.to_linear();
- state.ubo_data.ambient_light_color[0] = linear_ambient_color.r;
- state.ubo_data.ambient_light_color[1] = linear_ambient_color.g;
- state.ubo_data.ambient_light_color[2] = linear_ambient_color.b;
- state.ubo_data.ambient_light_color[3] = linear_ambient_color.a;
-
- Color bg_color;
-
- switch (env->bg_mode) {
- case VS::ENV_BG_CLEAR_COLOR: {
- bg_color = storage->frame.clear_request_color.to_linear();
- } break;
- case VS::ENV_BG_COLOR: {
- bg_color = env->bg_color.to_linear();
- } break;
- default: {
- bg_color = Color(0, 0, 0, 1);
- } break;
- }
-
- state.ubo_data.bg_color[0] = bg_color.r;
- state.ubo_data.bg_color[1] = bg_color.g;
- state.ubo_data.bg_color[2] = bg_color.b;
- state.ubo_data.bg_color[3] = bg_color.a;
-
- //use the inverse of our sky_orientation, we may need to skip this if we're using a reflection probe?
- sky_orientation = Transform(env->sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse();
-
- state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution;
- state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect;
- state.ubo_data.ambient_occlusion_affect_ssao = env->ssao_ao_channel_affect;
-
- //fog
-
- Color linear_fog = env->fog_color.to_linear();
- state.ubo_data.fog_color_enabled[0] = linear_fog.r;
- state.ubo_data.fog_color_enabled[1] = linear_fog.g;
- state.ubo_data.fog_color_enabled[2] = linear_fog.b;
- state.ubo_data.fog_color_enabled[3] = (!p_no_fog && env->fog_enabled) ? 1.0 : 0.0;
- state.ubo_data.fog_density = linear_fog.a;
-
- Color linear_sun = env->fog_sun_color.to_linear();
- state.ubo_data.fog_sun_color_amount[0] = linear_sun.r;
- state.ubo_data.fog_sun_color_amount[1] = linear_sun.g;
- state.ubo_data.fog_sun_color_amount[2] = linear_sun.b;
- state.ubo_data.fog_sun_color_amount[3] = env->fog_sun_amount;
- state.ubo_data.fog_depth_enabled = env->fog_depth_enabled;
- state.ubo_data.fog_depth_begin = env->fog_depth_begin;
- state.ubo_data.fog_depth_end = env->fog_depth_end;
- state.ubo_data.fog_depth_curve = env->fog_depth_curve;
- state.ubo_data.fog_transmit_enabled = env->fog_transmit_enabled;
- state.ubo_data.fog_transmit_curve = env->fog_transmit_curve;
- state.ubo_data.fog_height_enabled = env->fog_height_enabled;
- state.ubo_data.fog_height_min = env->fog_height_min;
- state.ubo_data.fog_height_max = env->fog_height_max;
- state.ubo_data.fog_height_curve = env->fog_height_curve;
-
- } else {
- state.ubo_data.bg_energy = 1.0;
- state.ubo_data.ambient_energy = 1.0;
- //use from clear color instead, since there is no ambient
- Color linear_ambient_color = storage->frame.clear_request_color.to_linear();
- state.ubo_data.ambient_light_color[0] = linear_ambient_color.r;
- state.ubo_data.ambient_light_color[1] = linear_ambient_color.g;
- state.ubo_data.ambient_light_color[2] = linear_ambient_color.b;
- state.ubo_data.ambient_light_color[3] = linear_ambient_color.a;
-
- state.ubo_data.bg_color[0] = linear_ambient_color.r;
- state.ubo_data.bg_color[1] = linear_ambient_color.g;
- state.ubo_data.bg_color[2] = linear_ambient_color.b;
- state.ubo_data.bg_color[3] = linear_ambient_color.a;
-
- state.env_radiance_data.ambient_contribution = 0;
- state.ubo_data.ambient_occlusion_affect_light = 0;
-
- state.ubo_data.fog_color_enabled[3] = 0.0;
- }
-
- {
- //directional shadow
-
- state.ubo_data.shadow_directional_pixel_size[0] = 1.0 / directional_shadow.size;
- state.ubo_data.shadow_directional_pixel_size[1] = 1.0 / directional_shadow.size;
-
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
- glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
- }
-
- glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.ubo_data, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- //fill up environment
-
- store_transform(sky_orientation * p_cam_transform, state.env_radiance_data.transform);
-
- glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-}
-
-void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows) {
-
- LightInstance *li = directional_lights[p_index];
-
- LightDataUBO ubo_data; //used for filling
-
- float sign = li->light_ptr->negative ? -1 : 1;
-
- Color linear_col = li->light_ptr->color.to_linear();
- //compensate normalized diffuse range by multiplying by PI
- ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[3] = 0;
-
- //omni, keep at 0
- ubo_data.light_pos_inv_radius[0] = 0.0;
- ubo_data.light_pos_inv_radius[1] = 0.0;
- ubo_data.light_pos_inv_radius[2] = 0.0;
- ubo_data.light_pos_inv_radius[3] = 0.0;
-
- Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0, 0, -1))).normalized();
- ubo_data.light_direction_attenuation[0] = direction.x;
- ubo_data.light_direction_attenuation[1] = direction.y;
- ubo_data.light_direction_attenuation[2] = direction.z;
- ubo_data.light_direction_attenuation[3] = 1.0;
-
- ubo_data.light_params[0] = 0;
- ubo_data.light_params[1] = 0;
- ubo_data.light_params[2] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
- ubo_data.light_params[3] = 0;
-
- Color shadow_color = li->light_ptr->shadow_color.to_linear();
- ubo_data.light_shadow_color_contact[0] = shadow_color.r;
- ubo_data.light_shadow_color_contact[1] = shadow_color.g;
- ubo_data.light_shadow_color_contact[2] = shadow_color.b;
- ubo_data.light_shadow_color_contact[3] = li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE];
-
- if (p_use_shadows && li->light_ptr->shadow) {
-
- int shadow_count = 0;
-
- switch (li->light_ptr->directional_shadow_mode) {
- case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
- shadow_count = 1;
- } break;
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
- shadow_count = 2;
- } break;
- case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
- shadow_count = 4;
- } break;
- }
-
- for (int j = 0; j < shadow_count; j++) {
-
- uint32_t x = li->directional_rect.position.x;
- uint32_t y = li->directional_rect.position.y;
- uint32_t width = li->directional_rect.size.x;
- uint32_t height = li->directional_rect.size.y;
-
- if (li->light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
-
- width /= 2;
- height /= 2;
-
- if (j == 1) {
- x += width;
- } else if (j == 2) {
- y += height;
- } else if (j == 3) {
- x += width;
- y += height;
- }
-
- } else if (li->light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
-
- height /= 2;
-
- if (j != 0) {
- y += height;
- }
- }
-
- ubo_data.shadow_split_offsets[j] = li->shadow_transform[j].split;
-
- Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).affine_inverse();
-
- CameraMatrix bias;
- bias.set_light_bias();
- CameraMatrix rectm;
- Rect2 atlas_rect = Rect2(float(x) / directional_shadow.size, float(y) / directional_shadow.size, float(width) / directional_shadow.size, float(height) / directional_shadow.size);
- rectm.set_light_atlas_rect(atlas_rect);
-
- CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview;
-
- store_camera(shadow_mtx, &ubo_data.shadow.matrix[16 * j]);
-
- ubo_data.light_clamp[0] = atlas_rect.position.x;
- ubo_data.light_clamp[1] = atlas_rect.position.y;
- ubo_data.light_clamp[2] = atlas_rect.size.x;
- ubo_data.light_clamp[3] = atlas_rect.size.y;
- }
- }
-
- glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDataUBO), &ubo_data, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- directional_light = li;
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 3, state.directional_ubo);
-}
-
-void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas) {
-
- state.omni_light_count = 0;
- state.spot_light_count = 0;
- state.directional_light_count = 0;
-
- directional_light = NULL;
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
-
- for (int i = 0; i < p_light_cull_count; i++) {
-
- ERR_BREAK(i >= render_list.max_lights);
-
- LightInstance *li = light_instance_owner.getornull(p_light_cull_result[i]);
-
- LightDataUBO ubo_data; //used for filling
-
- switch (li->light_ptr->type) {
-
- case VS::LIGHT_DIRECTIONAL: {
-
- if (state.directional_light_count < RenderList::MAX_DIRECTIONAL_LIGHTS) {
- directional_lights[state.directional_light_count++] = li;
- }
-
- } break;
- case VS::LIGHT_OMNI: {
-
- float sign = li->light_ptr->negative ? -1 : 1;
-
- Color linear_col = li->light_ptr->color.to_linear();
- ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[3] = 0;
-
- Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin);
-
- //directional, keep at 0
- ubo_data.light_pos_inv_radius[0] = pos.x;
- ubo_data.light_pos_inv_radius[1] = pos.y;
- ubo_data.light_pos_inv_radius[2] = pos.z;
- ubo_data.light_pos_inv_radius[3] = 1.0 / MAX(0.001, li->light_ptr->param[VS::LIGHT_PARAM_RANGE]);
-
- ubo_data.light_direction_attenuation[0] = 0;
- ubo_data.light_direction_attenuation[1] = 0;
- ubo_data.light_direction_attenuation[2] = 0;
- ubo_data.light_direction_attenuation[3] = li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
-
- ubo_data.light_params[0] = 0;
- ubo_data.light_params[1] = 0;
- ubo_data.light_params[2] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
- ubo_data.light_params[3] = 0;
-
- Color shadow_color = li->light_ptr->shadow_color.to_linear();
- ubo_data.light_shadow_color_contact[0] = shadow_color.r;
- ubo_data.light_shadow_color_contact[1] = shadow_color.g;
- ubo_data.light_shadow_color_contact[2] = shadow_color.b;
- ubo_data.light_shadow_color_contact[3] = li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE];
-
- if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) {
- // fill in the shadow information
-
- uint32_t key = shadow_atlas->shadow_owners[li->self];
-
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- ERR_CONTINUE(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size());
-
- uint32_t atlas_size = shadow_atlas->size;
- uint32_t quadrant_size = atlas_size >> 1;
-
- uint32_t x = (quadrant & 1) * quadrant_size;
- uint32_t y = (quadrant >> 1) * quadrant_size;
-
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
- x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
-
- uint32_t width = shadow_size;
- uint32_t height = shadow_size;
-
- if (li->light_ptr->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
-
- height /= 2;
- } else {
- width /= 2;
- }
-
- Transform proj = (p_camera_inverse_transform * li->transform).inverse();
-
- store_transform(proj, ubo_data.shadow.matrix1);
-
- ubo_data.light_params[3] = 1.0; //means it has shadow
- ubo_data.light_clamp[0] = float(x) / atlas_size;
- ubo_data.light_clamp[1] = float(y) / atlas_size;
- ubo_data.light_clamp[2] = float(width) / atlas_size;
- ubo_data.light_clamp[3] = float(height) / atlas_size;
- }
-
- li->light_index = state.omni_light_count;
- copymem(&state.omni_array_tmp[li->light_index * state.ubo_light_size], &ubo_data, state.ubo_light_size);
- state.omni_light_count++;
-
- } break;
- case VS::LIGHT_SPOT: {
-
- float sign = li->light_ptr->negative ? -1 : 1;
-
- Color linear_col = li->light_ptr->color.to_linear();
- ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
- ubo_data.light_color_energy[3] = 0;
-
- Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin);
-
- //directional, keep at 0
- ubo_data.light_pos_inv_radius[0] = pos.x;
- ubo_data.light_pos_inv_radius[1] = pos.y;
- ubo_data.light_pos_inv_radius[2] = pos.z;
- ubo_data.light_pos_inv_radius[3] = 1.0 / MAX(0.001, li->light_ptr->param[VS::LIGHT_PARAM_RANGE]);
-
- Vector3 direction = p_camera_inverse_transform.basis.xform(li->transform.basis.xform(Vector3(0, 0, -1))).normalized();
- ubo_data.light_direction_attenuation[0] = direction.x;
- ubo_data.light_direction_attenuation[1] = direction.y;
- ubo_data.light_direction_attenuation[2] = direction.z;
- ubo_data.light_direction_attenuation[3] = li->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
-
- ubo_data.light_params[0] = li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION];
- ubo_data.light_params[1] = Math::cos(Math::deg2rad(li->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE]));
- ubo_data.light_params[2] = li->light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
- ubo_data.light_params[3] = 0;
-
- Color shadow_color = li->light_ptr->shadow_color.to_linear();
- ubo_data.light_shadow_color_contact[0] = shadow_color.r;
- ubo_data.light_shadow_color_contact[1] = shadow_color.g;
- ubo_data.light_shadow_color_contact[2] = shadow_color.b;
- ubo_data.light_shadow_color_contact[3] = li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE];
-
- if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) {
- // fill in the shadow information
-
- uint32_t key = shadow_atlas->shadow_owners[li->self];
-
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- ERR_CONTINUE(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size());
-
- uint32_t atlas_size = shadow_atlas->size;
- uint32_t quadrant_size = atlas_size >> 1;
-
- uint32_t x = (quadrant & 1) * quadrant_size;
- uint32_t y = (quadrant >> 1) * quadrant_size;
-
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
- x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
-
- uint32_t width = shadow_size;
- uint32_t height = shadow_size;
-
- Rect2 rect(float(x) / atlas_size, float(y) / atlas_size, float(width) / atlas_size, float(height) / atlas_size);
-
- ubo_data.light_params[3] = 1.0; //means it has shadow
- ubo_data.light_clamp[0] = rect.position.x;
- ubo_data.light_clamp[1] = rect.position.y;
- ubo_data.light_clamp[2] = rect.size.x;
- ubo_data.light_clamp[3] = rect.size.y;
-
- Transform modelview = (p_camera_inverse_transform * li->transform).inverse();
-
- CameraMatrix bias;
- bias.set_light_bias();
- CameraMatrix rectm;
- rectm.set_light_atlas_rect(rect);
-
- CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview;
-
- store_camera(shadow_mtx, ubo_data.shadow.matrix1);
- }
-
- li->light_index = state.spot_light_count;
- copymem(&state.spot_array_tmp[li->light_index * state.ubo_light_size], &ubo_data, state.ubo_light_size);
- state.spot_light_count++;
- } break;
- }
-
- li->last_pass = render_pass;
-
- //update UBO for forward rendering, blit to texture for clustered
- }
-
- if (state.omni_light_count) {
-
- glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, state.omni_light_count * state.ubo_light_size, state.omni_array_tmp);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
- }
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 4, state.omni_array_ubo);
-
- if (state.spot_light_count) {
-
- glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, state.spot_light_count * state.ubo_light_size, state.spot_array_tmp);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
- }
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 5, state.spot_array_ubo);
-}
-
-void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_reflection_atlas, Environment *p_env) {
-
- state.reflection_probe_count = 0;
-
- for (int i = 0; i < p_reflection_probe_cull_count; i++) {
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe_cull_result[i]);
- ERR_CONTINUE(!rpi);
-
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
- ERR_CONTINUE(!reflection_atlas);
-
- ERR_CONTINUE(rpi->reflection_atlas_index < 0);
-
- if (state.reflection_probe_count >= state.max_ubo_reflections)
- break;
-
- rpi->last_pass = render_pass;
-
- ReflectionProbeDataUBO reflection_ubo;
-
- reflection_ubo.box_extents[0] = rpi->probe_ptr->extents.x;
- reflection_ubo.box_extents[1] = rpi->probe_ptr->extents.y;
- reflection_ubo.box_extents[2] = rpi->probe_ptr->extents.z;
- reflection_ubo.box_extents[3] = 0;
-
- reflection_ubo.box_ofs[0] = rpi->probe_ptr->origin_offset.x;
- reflection_ubo.box_ofs[1] = rpi->probe_ptr->origin_offset.y;
- reflection_ubo.box_ofs[2] = rpi->probe_ptr->origin_offset.z;
- reflection_ubo.box_ofs[3] = 0;
-
- reflection_ubo.params[0] = rpi->probe_ptr->intensity;
- reflection_ubo.params[1] = 0;
- reflection_ubo.params[2] = rpi->probe_ptr->interior ? 1.0 : 0.0;
- reflection_ubo.params[3] = rpi->probe_ptr->box_projection ? 1.0 : 0.0;
-
- if (rpi->probe_ptr->interior) {
- Color ambient_linear = rpi->probe_ptr->interior_ambient.to_linear();
- reflection_ubo.ambient[0] = ambient_linear.r * rpi->probe_ptr->interior_ambient_energy;
- reflection_ubo.ambient[1] = ambient_linear.g * rpi->probe_ptr->interior_ambient_energy;
- reflection_ubo.ambient[2] = ambient_linear.b * rpi->probe_ptr->interior_ambient_energy;
- reflection_ubo.ambient[3] = rpi->probe_ptr->interior_ambient_probe_contrib;
- } else {
- Color ambient_linear;
- if (p_env) {
- ambient_linear = p_env->ambient_color.to_linear();
- ambient_linear.r *= p_env->ambient_energy;
- ambient_linear.g *= p_env->ambient_energy;
- ambient_linear.b *= p_env->ambient_energy;
- }
-
- reflection_ubo.ambient[0] = ambient_linear.r;
- reflection_ubo.ambient[1] = ambient_linear.g;
- reflection_ubo.ambient[2] = ambient_linear.b;
- reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light
- }
-
- int cell_size = reflection_atlas->size / reflection_atlas->subdiv;
- int x = (rpi->reflection_atlas_index % reflection_atlas->subdiv) * cell_size;
- int y = (rpi->reflection_atlas_index / reflection_atlas->subdiv) * cell_size;
- int width = cell_size;
- int height = cell_size;
-
- reflection_ubo.atlas_clamp[0] = float(x) / reflection_atlas->size;
- reflection_ubo.atlas_clamp[1] = float(y) / reflection_atlas->size;
- reflection_ubo.atlas_clamp[2] = float(width) / reflection_atlas->size;
- reflection_ubo.atlas_clamp[3] = float(height) / reflection_atlas->size;
-
- Transform proj = (p_camera_inverse_transform * rpi->transform).inverse();
- store_transform(proj, reflection_ubo.local_matrix);
-
- rpi->reflection_index = state.reflection_probe_count;
- copymem(&state.reflection_array_tmp[rpi->reflection_index * sizeof(ReflectionProbeDataUBO)], &reflection_ubo, sizeof(ReflectionProbeDataUBO));
- state.reflection_probe_count++;
- }
-
- if (state.reflection_probe_count) {
-
- glBindBuffer(GL_UNIFORM_BUFFER, state.reflection_array_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, state.reflection_probe_count * sizeof(ReflectionProbeDataUBO), state.reflection_array_tmp);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
- }
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 6, state.reflection_array_ubo);
-}
-
-void RasterizerSceneGLES3::_copy_screen(bool p_invalidate_color, bool p_invalidate_depth) {
-
-#ifndef GLES_OVER_GL
- if (p_invalidate_color) {
-
- GLenum attachments[2] = {
- GL_COLOR_ATTACHMENT0,
- GL_DEPTH_ATTACHMENT
- };
-
- glInvalidateFramebuffer(GL_FRAMEBUFFER, p_invalidate_depth ? 2 : 1, attachments);
- }
-#endif
-
- glBindVertexArray(storage->resources.quadie_array);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindVertexArray(0);
-}
-
-void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
-
- //copy to front buffer
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
-
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthFunc(GL_LEQUAL);
- glColorMask(1, 1, 1, 1);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, p_texture);
-
- glViewport(0, 0, storage->frame.current_rt->width * 0.5, storage->frame.current_rt->height * 0.5);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true);
- storage->shaders.copy.bind();
-
- _copy_screen();
-
- //turn off everything used
- storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
-}
-
-void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass) {
-
- current_geometry_index = 0;
- current_material_index = 0;
- state.used_sss = false;
- state.used_screen_texture = false;
- state.used_depth_texture = false;
-
- //fill list
-
- for (int i = 0; i < p_cull_count; i++) {
-
- InstanceBase *inst = p_cull_result[i];
- switch (inst->base_type) {
-
- case VS::INSTANCE_MESH: {
-
- RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(inst->base);
- ERR_CONTINUE(!mesh);
-
- int ssize = mesh->surfaces.size();
-
- for (int j = 0; j < ssize; j++) {
-
- int mat_idx = inst->materials[j].is_valid() ? j : -1;
- RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
- _add_geometry(s, inst, NULL, mat_idx, p_depth_pass, p_shadow_pass);
- }
-
- //mesh->last_pass=frame;
-
- } break;
- case VS::INSTANCE_MULTIMESH: {
-
- RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(inst->base);
- ERR_CONTINUE(!multi_mesh);
-
- if (multi_mesh->size == 0 || multi_mesh->visible_instances == 0)
- continue;
-
- RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(multi_mesh->mesh);
- if (!mesh)
- continue; //mesh not assigned
-
- int ssize = mesh->surfaces.size();
-
- for (int j = 0; j < ssize; j++) {
-
- RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
- _add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass);
- }
-
- } break;
- case VS::INSTANCE_IMMEDIATE: {
-
- RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
- ERR_CONTINUE(!immediate);
-
- _add_geometry(immediate, inst, NULL, -1, p_depth_pass, p_shadow_pass);
-
- } break;
- case VS::INSTANCE_PARTICLES: {
-
- RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(inst->base);
- ERR_CONTINUE(!particles);
-
- for (int j = 0; j < particles->draw_passes.size(); j++) {
-
- RID pmesh = particles->draw_passes[j];
- if (!pmesh.is_valid())
- continue;
- RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(pmesh);
- if (!mesh)
- continue; //mesh not assigned
-
- int ssize = mesh->surfaces.size();
-
- for (int k = 0; k < ssize; k++) {
-
- RasterizerStorageGLES3::Surface *s = mesh->surfaces[k];
- _add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass);
- }
- }
-
- } break;
- default: {
- }
- }
- }
-}
-
-void RasterizerSceneGLES3::_blur_effect_buffer() {
-
- //blur diffuse into effect mipmaps using separatable convolution
- //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
- for (int i = 0; i < storage->frame.current_rt->effects.mip_maps[1].sizes.size(); i++) {
-
- int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width;
- int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height;
- glViewport(0, 0, vp_w, vp_h);
- //horizontal pass
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, true);
- state.effect_blur_shader.bind();
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo);
- _copy_screen(true);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, false);
-
- //vertical pass
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, true);
- state.effect_blur_shader.bind();
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color);
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger
- _copy_screen(true);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, false);
- }
-}
-
-void RasterizerSceneGLES3::_prepare_depth_texture() {
- if (!state.prepared_depth_texture) {
- //resolve depth buffer
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- state.prepared_depth_texture = true;
- }
-}
-
-void RasterizerSceneGLES3::_bind_depth_texture() {
- if (!state.bound_depth_texture) {
- ERR_FAIL_COND(!state.prepared_depth_texture);
- //bind depth for read
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
- state.bound_depth_texture = true;
- }
-}
-
-void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_cam_projection) {
-
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
-
- _prepare_depth_texture();
-
- if (env->ssao_enabled || env->ssr_enabled) {
-
- //copy normal and roughness to effect buffer
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glReadBuffer(GL_COLOR_ATTACHMENT2);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_fbo);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
-
- if (env->ssao_enabled) {
- //copy diffuse to front buffer
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-
- //copy from depth, convert to linear
- GLint ss[2];
- ss[0] = storage->frame.current_rt->width;
- ss[1] = storage->frame.current_rt->height;
-
- for (int i = 0; i < storage->frame.current_rt->effects.ssao.depth_mipmap_fbos.size(); i++) {
-
- state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::MINIFY_START, i == 0);
- state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
- state.ssao_minify_shader.bind();
- state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
- state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
- state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::SOURCE_MIPMAP, MAX(0, i - 1));
- glUniform2iv(state.ssao_minify_shader.get_uniform(SsaoMinifyShaderGLES3::FROM_SIZE), 1, ss);
- ss[0] >>= 1;
- ss[1] >>= 1;
-
- glActiveTexture(GL_TEXTURE0);
- if (i == 0) {
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
- } else {
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.linear_depth);
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.depth_mipmap_fbos[i]); //copy to front first
- glViewport(0, 0, ss[0], ss[1]);
-
- _copy_screen(true);
- }
- ss[0] = storage->frame.current_rt->width;
- ss[1] = storage->frame.current_rt->height;
-
- glViewport(0, 0, ss[0], ss[1]);
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_GREATER);
- // do SSAO!
- state.ssao_shader.set_conditional(SsaoShaderGLES3::ENABLE_RADIUS2, env->ssao_radius2 > 0.001);
- state.ssao_shader.set_conditional(SsaoShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
- state.ssao_shader.set_conditional(SsaoShaderGLES3::SSAO_QUALITY_LOW, env->ssao_quality == VS::ENV_SSAO_QUALITY_LOW);
- state.ssao_shader.set_conditional(SsaoShaderGLES3::SSAO_QUALITY_HIGH, env->ssao_quality == VS::ENV_SSAO_QUALITY_HIGH);
- state.ssao_shader.bind();
- state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
- state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
- glUniform2iv(state.ssao_shader.get_uniform(SsaoShaderGLES3::SCREEN_SIZE), 1, ss);
- float radius = env->ssao_radius;
- state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS, radius);
- float intensity = env->ssao_intensity;
- state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R6, intensity / pow(radius, 6.0f));
-
- if (env->ssao_radius2 > 0.001) {
-
- float radius2 = env->ssao_radius2;
- state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS2, radius2);
- float intensity2 = env->ssao_intensity2;
- state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R62, intensity2 / pow(radius2, 6.0f));
- }
-
- float proj_info[4] = {
- -2.0f / (ss[0] * p_cam_projection.matrix[0][0]),
- -2.0f / (ss[1] * p_cam_projection.matrix[1][1]),
- (1.0f - p_cam_projection.matrix[0][2]) / p_cam_projection.matrix[0][0],
- (1.0f + p_cam_projection.matrix[1][2]) / p_cam_projection.matrix[1][1]
- };
-
- glUniform4fv(state.ssao_shader.get_uniform(SsaoShaderGLES3::PROJ_INFO), 1, proj_info);
- float pixels_per_meter = float(p_cam_projection.get_pixels_per_meter(ss[0]));
-
- state.ssao_shader.set_uniform(SsaoShaderGLES3::PROJ_SCALE, pixels_per_meter);
- state.ssao_shader.set_uniform(SsaoShaderGLES3::BIAS, env->ssao_bias);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.linear_depth);
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect);
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[0]); //copy to front first
- Color white(1, 1, 1, 1);
- glClearBufferfv(GL_COLOR, 0, white.components); // specular
-
- _copy_screen(true);
-
- //do the batm, i mean blur
-
- state.ssao_blur_shader.bind();
-
- if (env->ssao_filter) {
- for (int i = 0; i < 2; i++) {
-
- state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
- state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
- state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::EDGE_SHARPNESS, env->ssao_bilateral_sharpness);
- state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::FILTER_SCALE, int(env->ssao_filter));
-
- GLint axis[2] = { i, 1 - i };
- glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::AXIS), 1, axis);
- glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::SCREEN_SIZE), 1, ss);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[i]);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect);
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[1 - i]);
- if (i == 0) {
- glClearBufferfv(GL_COLOR, 0, white.components); // specular
- }
- _copy_screen(true);
- }
- }
-
- glDisable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
-
- // just copy diffuse while applying SSAO
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE, true);
- state.effect_blur_shader.bind();
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::SSAO_COLOR, env->ssao_color);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); //previous level, since mipmaps[0] starts one level bigger
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
- _copy_screen(true);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE, false);
-
- } else {
-
- //copy diffuse to effect buffer
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- }
-
- if (state.used_sss) { //sss enabled
- //copy diffuse while performing sss
-
- Plane p = p_cam_projection.xform4(Plane(1, 0, -1, 1));
- p.normal /= p.d;
- float unit_size = p.normal.x;
-
- //copy normal and roughness to effect buffer
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glReadBuffer(GL_COLOR_ATTACHMENT3);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[0]);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
- state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
- state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_11_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_LOW);
- state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_17_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_MEDIUM);
- state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_25_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_HIGH);
- state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::ENABLE_FOLLOW_SURFACE, subsurface_scatter_follow_surface);
- state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::ENABLE_STRENGTH_WEIGHTING, subsurface_scatter_weight_samples);
- state.sss_shader.bind();
- state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::MAX_RADIUS, subsurface_scatter_size);
- state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::UNIT_SIZE, unit_size);
- state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
- state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
- state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR, Vector2(1, 0));
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //disable filter (fixes bugs on AMD)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.ssao.blur_red[0]);
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first
-
- _copy_screen(true);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
- state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR, Vector2(0, 1));
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
- _copy_screen(true);
-
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //restore filter
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- }
-
- if (env->ssr_enabled) {
-
- //blur diffuse into effect mipmaps using separatable convolution
- //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
- _blur_effect_buffer();
-
- //perform SSR
-
- state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::REFLECT_ROUGHNESS, env->ssr_roughness);
- state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
-
- state.ssr_shader.bind();
-
- int ssr_w = storage->frame.current_rt->effects.mip_maps[1].sizes[0].width;
- int ssr_h = storage->frame.current_rt->effects.mip_maps[1].sizes[0].height;
-
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PIXEL_SIZE, Vector2(1.0 / (ssr_w * 0.5), 1.0 / (ssr_h * 0.5)));
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PROJECTION, p_cam_projection);
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::INVERSE_PROJECTION, p_cam_projection.inverse());
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::VIEWPORT_SIZE, Size2(ssr_w, ssr_h));
- //state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FRAME_INDEX,int(render_pass));
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FILTER_MIPMAP_LEVELS, float(storage->frame.current_rt->effects.mip_maps[0].sizes.size()));
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::NUM_STEPS, env->ssr_max_steps);
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DEPTH_TOLERANCE, env->ssr_depth_tolerance);
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DISTANCE_FADE, env->ssr_fade_out);
- state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CURVE_FADE_IN, env->ssr_fade_in);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.effect);
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[0].fbo);
- glViewport(0, 0, ssr_w, ssr_h);
-
- _copy_screen(true);
- glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
- }
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glReadBuffer(GL_COLOR_ATTACHMENT1);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
- //glDrawBuffer(GL_COLOR_ATTACHMENT0);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-
- //copy reflection over diffuse, resolving SSR if needed
- state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR, env->ssr_enabled);
- state.resolve_shader.bind();
- state.resolve_shader.set_uniform(ResolveShaderGLES3::PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height));
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
- if (env->ssr_enabled) {
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color);
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
- glEnable(GL_BLEND);
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_ONE, GL_ONE); //use additive to accumulate one over the other
-
- _copy_screen(true);
-
- glDisable(GL_BLEND); //end additive
-
- if (state.used_screen_texture) {
- _blur_effect_buffer();
- //restored framebuffer
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
- glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
- }
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY, true);
- state.effect_blur_shader.bind();
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(0));
-
- {
- GLuint db = GL_COLOR_ATTACHMENT0;
- glDrawBuffers(1, &db);
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
-
- _copy_screen(true);
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY, false);
-}
-
-void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p_cam_projection) {
-
- //copy to front buffer
-
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthFunc(GL_LEQUAL);
- glColorMask(1, 1, 1, 1);
-
- //turn off everything used
-
- //copy specular to front buffer
- //copy diffuse to effect buffer
-
- if (storage->frame.current_rt->buffers.active) {
- //transfer to effect buffer if using buffers, also resolve MSAA
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- }
-
- if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] || storage->frame.current_rt->width < 4 || storage->frame.current_rt->height < 4) { //no post process on small render targets
- //no environment or transparent render, simply return and convert to SRGB
- if (storage->frame.current_rt->external.fbo != 0) {
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->external.fbo);
- } else {
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
- }
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]);
- storage->shaders.copy.bind();
-
- _copy_screen(true);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); //compute luminance
- storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, false);
-
- return;
- }
-
- //order of operation
- //1) DOF Blur (first blur, then copy to buffer applying the blur)
- //2) Motion Blur
- //3) Bloom
- //4) Tonemap
- //5) Adjustments
-
- GLuint composite_from = storage->frame.current_rt->effects.mip_maps[0].color;
-
- if (env->dof_blur_far_enabled) {
-
- //blur diffuse into effect mipmaps using separatable convolution
- //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
-
- int vp_h = storage->frame.current_rt->height;
- int vp_w = storage->frame.current_rt->width;
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, true);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_HIGH);
-
- state.effect_blur_shader.bind();
- int qsteps[3] = { 4, 10, 20 };
-
- float radius = (env->dof_blur_far_amount * env->dof_blur_far_amount) / qsteps[env->dof_blur_far_quality];
-
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_far_distance);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_far_distance + env->dof_blur_far_transition);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(1, 0));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, composite_from);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first
-
- _copy_screen(true);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(0, 1));
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
- _copy_screen();
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, false);
-
- composite_from = storage->frame.current_rt->effects.mip_maps[0].color;
- }
-
- if (env->dof_blur_near_enabled) {
-
- //blur diffuse into effect mipmaps using separatable convolution
- //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
-
- int vp_h = storage->frame.current_rt->height;
- int vp_w = storage->frame.current_rt->width;
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR, true);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, true);
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_HIGH);
-
- state.effect_blur_shader.bind();
- int qsteps[3] = { 4, 10, 20 };
-
- float radius = (env->dof_blur_near_amount * env->dof_blur_near_amount) / qsteps[env->dof_blur_near_quality];
-
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_near_distance);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(1, 0));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, composite_from);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first
-
- _copy_screen();
- //manually do the blend if this is the first operation resolving from the diffuse buffer
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE, composite_from == storage->frame.current_rt->buffers.diffuse);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, false);
- state.effect_blur_shader.bind();
-
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_near_distance);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(0, 1));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
-
- if (composite_from != storage->frame.current_rt->buffers.diffuse) {
-
- glEnable(GL_BLEND);
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- } else {
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse);
- }
-
- _copy_screen(true);
-
- if (composite_from != storage->frame.current_rt->buffers.diffuse) {
-
- glDisable(GL_BLEND);
- }
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, false);
-
- composite_from = storage->frame.current_rt->effects.mip_maps[0].color;
- }
-
- if (env->dof_blur_near_enabled || env->dof_blur_far_enabled) {
- //these needed to disable filtering, reenamble
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
-
- if (env->auto_exposure) {
-
- //compute auto exposure
- //first step, copy from image to luminance buffer
- state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN, true);
- state.exposure_shader.bind();
- int ss[2] = {
- storage->frame.current_rt->width,
- storage->frame.current_rt->height,
- };
- int ds[2] = {
- exposure_shrink_size,
- exposure_shrink_size,
- };
-
- glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::SOURCE_RENDER_SIZE), 1, ss);
- glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::TARGET_SIZE), 1, ds);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, composite_from);
-
- glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[0].fbo);
- glViewport(0, 0, exposure_shrink_size, exposure_shrink_size);
-
- _copy_screen(true);
-
- //second step, shrink to 2x2 pixels
- state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN, false);
- state.exposure_shader.bind();
- //shrink from second to previous to last level
-
- int s_size = exposure_shrink_size / 3;
- for (int i = 1; i < exposure_shrink.size() - 1; i++) {
-
- glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[i].fbo);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, exposure_shrink[i - 1].color);
-
- _copy_screen();
-
- glViewport(0, 0, s_size, s_size);
-
- s_size /= 3;
- }
- //third step, shrink to 1x1 pixel taking in consideration the previous exposure
- state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END, true);
-
- uint64_t tick = OS::get_singleton()->get_ticks_usec();
- uint64_t tick_diff = storage->frame.current_rt->last_exposure_tick == 0 ? 0 : tick - storage->frame.current_rt->last_exposure_tick;
- storage->frame.current_rt->last_exposure_tick = tick;
-
- if (tick_diff == 0 || tick_diff > 1000000) {
- state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET, true);
- }
-
- state.exposure_shader.bind();
-
- glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[exposure_shrink.size() - 1].fbo);
- glViewport(0, 0, 1, 1);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, exposure_shrink[exposure_shrink.size() - 2].color);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color); //read from previous
-
- state.exposure_shader.set_uniform(ExposureShaderGLES3::EXPOSURE_ADJUST, env->auto_exposure_speed * (tick_diff / 1000000.0));
- state.exposure_shader.set_uniform(ExposureShaderGLES3::MAX_LUMINANCE, env->auto_exposure_max);
- state.exposure_shader.set_uniform(ExposureShaderGLES3::MIN_LUMINANCE, env->auto_exposure_min);
-
- _copy_screen(true);
-
- state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET, false);
- state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END, false);
-
- //last step, swap with the framebuffer exposure, so the right exposure is kept int he framebuffer
- SWAP(exposure_shrink.write[exposure_shrink.size() - 1].fbo, storage->frame.current_rt->exposure.fbo);
- SWAP(exposure_shrink.write[exposure_shrink.size() - 1].color, storage->frame.current_rt->exposure.color);
-
- glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
-
- VisualServerRaster::redraw_request(); //if using auto exposure, redraw must happen
- }
-
- int max_glow_level = -1;
- int glow_mask = 0;
-
- if (env->glow_enabled) {
-
- for (int i = 0; i < VS::MAX_GLOW_LEVELS; i++) {
- if (env->glow_levels & (1 << i)) {
-
- if (i >= storage->frame.current_rt->effects.mip_maps[1].sizes.size()) {
- max_glow_level = storage->frame.current_rt->effects.mip_maps[1].sizes.size() - 1;
- glow_mask |= 1 << max_glow_level;
-
- } else {
- max_glow_level = i;
- glow_mask |= (1 << i);
- }
- }
- }
-
- //blur diffuse into effect mipmaps using separatable convolution
- //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
-
- for (int i = 0; i < (max_glow_level + 1); i++) {
-
- int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width;
- int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height;
- glViewport(0, 0, vp_w, vp_h);
- //horizontal pass
- if (i == 0) {
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS, true);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE, env->auto_exposure);
- }
-
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_HORIZONTAL, true);
- state.effect_blur_shader.bind();
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH, env->glow_strength);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LUMINANCE_CAP, env->glow_hdr_luminance_cap);
-
- glActiveTexture(GL_TEXTURE0);
- if (i == 0) {
- glBindTexture(GL_TEXTURE_2D, composite_from);
-
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::EXPOSURE, env->tone_mapper_exposure);
- if (env->auto_exposure) {
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::AUTO_EXPOSURE_GREY, env->auto_exposure_grey);
- }
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color);
-
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_BLOOM, env->glow_bloom);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_THRESHOLD, env->glow_hdr_bleed_threshold);
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_SCALE, env->glow_hdr_bleed_scale);
-
- } else {
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger
- }
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo);
- _copy_screen(true);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_HORIZONTAL, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS, false);
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE, false);
-
- //vertical pass
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_VERTICAL, true);
- state.effect_blur_shader.bind();
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i));
- state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH, env->glow_strength);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color);
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger
- _copy_screen();
- state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_GAUSSIAN_VERTICAL, false);
- }
-
- glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
- }
-
- if (storage->frame.current_rt->external.fbo != 0) {
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->external.fbo);
- } else {
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
- }
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, composite_from);
-
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_FILMIC);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_ACES);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINHARD_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_REINHARD);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::KEEP_3D_LINEAR, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]);
-
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, env->auto_exposure);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, env->glow_bicubic_upscale);
-
- if (max_glow_level >= 0) {
-
- for (int i = 0; i < (max_glow_level + 1); i++) {
-
- if (glow_mask & (1 << i)) {
- if (i == 0) {
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL1, true);
- }
- if (i == 1) {
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL2, true);
- }
- if (i == 2) {
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL3, true);
- }
- if (i == 3) {
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL4, true);
- }
- if (i == 4) {
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL5, true);
- }
- if (i == 5) {
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL6, true);
- }
- if (i == 6) {
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL7, true);
- }
- }
- }
-
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_SCREEN);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_SOFTLIGHT);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_REPLACE);
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
- }
-
- if (env->adjustments_enabled) {
-
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_BCS, true);
- RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(env->color_correction);
- if (tex) {
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, true);
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(tex->target, tex->tex_id);
- }
- }
-
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]);
- state.tonemap_shader.bind();
-
- state.tonemap_shader.set_uniform(TonemapShaderGLES3::EXPOSURE, env->tone_mapper_exposure);
- state.tonemap_shader.set_uniform(TonemapShaderGLES3::WHITE, env->tone_mapper_exposure_white);
-
- if (max_glow_level >= 0) {
-
- state.tonemap_shader.set_uniform(TonemapShaderGLES3::GLOW_INTENSITY, env->glow_intensity);
- int ss[2] = {
- storage->frame.current_rt->width,
- storage->frame.current_rt->height,
- };
- glUniform2iv(state.tonemap_shader.get_uniform(TonemapShaderGLES3::GLOW_TEXTURE_SIZE), 1, ss);
- }
-
- if (env->auto_exposure) {
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->exposure.color);
- state.tonemap_shader.set_uniform(TonemapShaderGLES3::AUTO_EXPOSURE_GREY, env->auto_exposure_grey);
- }
-
- if (env->adjustments_enabled) {
-
- state.tonemap_shader.set_uniform(TonemapShaderGLES3::BCS, Vector3(env->adjustments_brightness, env->adjustments_contrast, env->adjustments_saturation));
- }
-
- _copy_screen(true, true);
-
- //turn off everything used
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINHARD_TONEMAPPER, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL1, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL2, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL3, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL4, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL5, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL6, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL7, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_BCS, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, false);
- state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, false);
-}
-
-void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
-
- //first of all, make a new render pass
- render_pass++;
-
- //fill up ubo
-
- storage->info.render.object_count += p_cull_count;
-
- Environment *env = environment_owner.getornull(p_environment);
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
-
- bool use_shadows = shadow_atlas && shadow_atlas->size;
-
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_SHADOW, use_shadows);
-
- if (use_shadows) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
- glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
- state.ubo_data.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size;
- state.ubo_data.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size;
- }
-
- if (reflection_atlas && reflection_atlas->size) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
- glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
- }
-
- if (p_reflection_probe.is_valid()) {
- state.ubo_data.reflection_multiplier = 0.0;
- } else {
- state.ubo_data.reflection_multiplier = 1.0;
- }
-
- state.ubo_data.subsurface_scatter_width = subsurface_scatter_size;
-
- state.ubo_data.z_offset = 0;
- state.ubo_data.z_slope_scale = 0;
- state.ubo_data.shadow_dual_paraboloid_render_side = 0;
- state.ubo_data.shadow_dual_paraboloid_render_zfar = 0;
- state.ubo_data.opaque_prepass_threshold = 0.99;
-
- if (storage->frame.current_rt) {
- int viewport_width_pixels = storage->frame.current_rt->width;
- int viewport_height_pixels = storage->frame.current_rt->height;
-
- state.ubo_data.viewport_size[0] = viewport_width_pixels;
- state.ubo_data.viewport_size[1] = viewport_height_pixels;
-
- state.ubo_data.screen_pixel_size[0] = 1.0 / viewport_width_pixels;
- state.ubo_data.screen_pixel_size[1] = 1.0 / viewport_height_pixels;
- }
-
- _setup_environment(env, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid());
-
- bool fb_cleared = false;
-
- glDepthFunc(GL_LEQUAL);
-
- state.used_contact_shadows = false;
- state.prepared_depth_texture = false;
- state.bound_depth_texture = false;
-
- for (int i = 0; i < p_light_cull_count; i++) {
-
- ERR_BREAK(i >= render_list.max_lights);
-
- LightInstance *li = light_instance_owner.getornull(p_light_cull_result[i]);
- if (li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] > CMP_EPSILON) {
- state.used_contact_shadows = true;
- }
- }
-
- // Do depth prepass if it's explicitly enabled
- bool use_depth_prepass = storage->config.use_depth_prepass;
-
- // If contact shadows are used then we need to do depth prepass even if it's otherwise disabled
- use_depth_prepass = use_depth_prepass || state.used_contact_shadows;
-
- // Never do depth prepass if effects are disabled or if we render overdraws
- use_depth_prepass = use_depth_prepass && storage->frame.current_rt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS];
- use_depth_prepass = use_depth_prepass && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW;
-
- if (use_depth_prepass) {
- //pre z pass
-
- glDisable(GL_BLEND);
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glDrawBuffers(0, NULL);
-
- glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
-
- glColorMask(0, 0, 0, 0);
- glClearDepth(1.0f);
- glClear(GL_DEPTH_BUFFER_BIT);
-
- render_list.clear();
- _fill_render_list(p_cull_result, p_cull_count, true, false);
- render_list.sort_by_key(false);
- state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true);
- _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, NULL, false, false, true, false, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false);
-
- glColorMask(1, 1, 1, 1);
-
- if (state.used_contact_shadows) {
-
- _prepare_depth_texture();
- _bind_depth_texture();
- }
-
- fb_cleared = true;
- render_pass++;
- state.used_depth_prepass = true;
- } else {
- state.used_depth_prepass = false;
- }
-
- _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_shadow_atlas);
- _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_reflection_atlas, env);
-
- bool use_mrt = false;
-
- render_list.clear();
- _fill_render_list(p_cull_result, p_cull_count, false, false);
- //
-
- glEnable(GL_BLEND);
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
-
- //rendering to a probe cubemap side
- ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe);
- GLuint current_fbo;
-
- if (probe) {
-
- ReflectionAtlas *ref_atlas = reflection_atlas_owner.getornull(probe->atlas);
- ERR_FAIL_COND(!ref_atlas);
-
- int target_size = ref_atlas->size / ref_atlas->subdiv;
-
- int cubemap_index = reflection_cubemaps.size() - 1;
-
- for (int i = reflection_cubemaps.size() - 1; i >= 0; i--) {
- //find appropriate cubemap to render to
- if (reflection_cubemaps[i].size > target_size * 2)
- break;
-
- cubemap_index = i;
- }
-
- current_fbo = reflection_cubemaps[cubemap_index].fbo_id[p_reflection_probe_pass];
- use_mrt = false;
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false);
-
- glViewport(0, 0, reflection_cubemaps[cubemap_index].size, reflection_cubemaps[cubemap_index].size);
- glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
-
- } else {
-
- use_mrt = env && (state.used_sss || env->ssao_enabled || env->ssr_enabled || env->dof_blur_far_enabled || env->dof_blur_near_enabled); //only enable MRT rendering if any of these is enabled
- //effects disabled and transparency also prevent using MRTs
- use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT];
- use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS];
- use_mrt = use_mrt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW;
- use_mrt = use_mrt && (env->bg_mode != VS::ENV_BG_KEEP && env->bg_mode != VS::ENV_BG_CANVAS);
-
- glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
-
- if (use_mrt) {
-
- current_fbo = storage->frame.current_rt->buffers.fbo;
-
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, true);
-
- Vector draw_buffers;
- draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
- draw_buffers.push_back(GL_COLOR_ATTACHMENT1);
- draw_buffers.push_back(GL_COLOR_ATTACHMENT2);
- if (state.used_sss) {
- draw_buffers.push_back(GL_COLOR_ATTACHMENT3);
- }
- glDrawBuffers(draw_buffers.size(), draw_buffers.ptr());
-
- Color black(0, 0, 0, 0);
- glClearBufferfv(GL_COLOR, 1, black.components); // specular
- glClearBufferfv(GL_COLOR, 2, black.components); // normal metal rough
- if (state.used_sss) {
- glClearBufferfv(GL_COLOR, 3, black.components); // normal metal rough
- }
-
- } else {
-
- if (storage->frame.current_rt->buffers.active) {
- current_fbo = storage->frame.current_rt->buffers.fbo;
- } else {
- if (storage->frame.current_rt->effects.mip_maps[0].sizes.size() == 0) {
- ERR_PRINT_ONCE("Can't use canvas background mode in a render target configured without sampling");
- return;
- }
- current_fbo = storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo;
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false);
-
- Vector draw_buffers;
- draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
- glDrawBuffers(draw_buffers.size(), draw_buffers.ptr());
- }
- }
-
- if (!fb_cleared) {
- glClearDepth(1.0f);
- glClear(GL_DEPTH_BUFFER_BIT);
- }
-
- Color clear_color(0, 0, 0, 0);
-
- RasterizerStorageGLES3::Sky *sky = NULL;
- Ref feed;
-
- if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
- clear_color = Color(0, 0, 0, 0);
- storage->frame.clear_request = false;
- } else if (!probe && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- clear_color = Color(0, 0, 0, 0);
- storage->frame.clear_request = false;
-
- } else if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR) {
-
- if (storage->frame.clear_request) {
-
- clear_color = storage->frame.clear_request_color.to_linear();
- storage->frame.clear_request = false;
- }
-
- } else if (env->bg_mode == VS::ENV_BG_CANVAS) {
-
- clear_color = env->bg_color.to_linear();
- storage->frame.clear_request = false;
- } else if (env->bg_mode == VS::ENV_BG_COLOR) {
-
- clear_color = env->bg_color.to_linear();
- storage->frame.clear_request = false;
- } else if (env->bg_mode == VS::ENV_BG_SKY) {
-
- storage->frame.clear_request = false;
-
- } else if (env->bg_mode == VS::ENV_BG_COLOR_SKY) {
-
- clear_color = env->bg_color.to_linear();
- storage->frame.clear_request = false;
-
- } else if (env->bg_mode == VS::ENV_BG_CAMERA_FEED) {
- feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id);
- storage->frame.clear_request = false;
- } else {
- storage->frame.clear_request = false;
- }
-
- if (!env || env->bg_mode != VS::ENV_BG_KEEP) {
- glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular
- }
-
- VS::EnvironmentBG bg_mode = (!env || (probe && env->bg_mode == VS::ENV_BG_CANVAS)) ? VS::ENV_BG_CLEAR_COLOR : env->bg_mode; //if no environment, or canvas while rendering a probe (invalid use case), use color.
-
- if (env) {
- switch (bg_mode) {
- case VS::ENV_BG_COLOR_SKY:
- case VS::ENV_BG_SKY:
-
- sky = storage->sky_owner.getornull(env->sky);
-
- break;
- case VS::ENV_BG_CANVAS:
- //copy canvas to 3d buffer and convert it to linear
-
- glDisable(GL_BLEND);
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true);
-
- storage->shaders.copy.bind();
-
- _copy_screen(true, true);
-
- //turn off everything used
- storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
-
- //restore
- glEnable(GL_BLEND);
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
- break;
- case VS::ENV_BG_CAMERA_FEED:
- if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) {
- // copy our camera feed to our background
-
- glDisable(GL_BLEND);
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, true);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true);
-
- if (feed->get_datatype() == CameraFeed::FEED_RGB) {
- RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE);
-
- VS::get_singleton()->texture_bind(camera_RGBA, 0);
- } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR) {
- RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCBCR_IMAGE);
-
- VS::get_singleton()->texture_bind(camera_YCbCr, 0);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true);
-
- } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR_SEP) {
- RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE);
- RID camera_CbCr = feed->get_texture(CameraServer::FEED_CBCR_IMAGE);
-
- VS::get_singleton()->texture_bind(camera_Y, 0);
- VS::get_singleton()->texture_bind(camera_CbCr, 1);
-
- storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, true);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true);
- };
-
- storage->shaders.copy.bind();
- storage->shaders.copy.set_uniform(CopyShaderGLES3::DISPLAY_TRANSFORM, feed->get_transform());
-
- _copy_screen(true, true);
-
- //turn off everything used
- storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, false);
- storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, false);
-
- //restore
- glEnable(GL_BLEND);
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
- } else {
- // don't have a feed, just show greenscreen :)
- clear_color = Color(0.0, 1.0, 0.0, 1.0);
- }
- break;
- default: {
- }
- }
- }
-
- if (probe && probe->probe_ptr->interior) {
- sky = NULL; //for rendering probe interiors, radiance must not be used.
- }
-
- state.texscreen_copied = false;
-
- glBlendEquation(GL_FUNC_ADD);
-
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- } else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_BLEND);
- }
-
- render_list.sort_by_key(false);
-
- if (state.directional_light_count == 0) {
- directional_light = NULL;
- _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, false, use_shadows);
- } else {
- for (int i = 0; i < state.directional_light_count; i++) {
- directional_light = directional_lights[i];
- if (i > 0) {
- glEnable(GL_BLEND);
- }
- _setup_directional_light(i, p_cam_transform.affine_inverse(), use_shadows);
- _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, i > 0, use_shadows);
- }
- }
-
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false);
-
- if (use_mrt) {
- GLenum gldb = GL_COLOR_ATTACHMENT0;
- glDrawBuffers(1, &gldb);
- }
-
- if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || (!storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW))) {
-
- /*
- if (use_mrt) {
- glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters
- */
-
- if (sky && sky->panorama.is_valid())
- _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation);
- }
-
- //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);
- //glColorMask(1,1,1,1);
-
- //state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false);
-
- if (use_mrt) {
-
- _render_mrts(env, p_cam_projection);
- } else {
- // Here we have to do the blits/resolves that otherwise are done in the MRT rendering, in particular
- // - prepare screen texture for any geometry that uses a shader with screen texture
- // - prepare depth texture for any geometry that uses a shader with depth texture
-
- bool framebuffer_dirty = false;
-
- if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_screen_texture) {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
- glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- _blur_effect_buffer();
- framebuffer_dirty = true;
- }
-
- if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_depth_texture) {
- _prepare_depth_texture();
- framebuffer_dirty = true;
- }
-
- if (framebuffer_dirty) {
- // Restore framebuffer
- glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
- glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
- }
- }
-
- if (storage->frame.current_rt && state.used_depth_texture && storage->frame.current_rt->buffers.active) {
- _bind_depth_texture();
- }
-
- if (storage->frame.current_rt && state.used_screen_texture && storage->frame.current_rt->buffers.active) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
- }
-
- glEnable(GL_BLEND);
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
-
- render_list.sort_by_reverse_depth_and_priority(true);
-
- if (state.directional_light_count == 0) {
- directional_light = NULL;
- _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, false, use_shadows);
- } else {
- for (int i = 0; i < state.directional_light_count; i++) {
- directional_light = directional_lights[i];
- _setup_directional_light(i, p_cam_transform.affine_inverse(), use_shadows);
- _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, i > 0, use_shadows);
- }
- }
-
- if (probe) {
- //rendering a probe, do no more!
- return;
- }
-
- if (env && (env->dof_blur_far_enabled || env->dof_blur_near_enabled) && storage->frame.current_rt && storage->frame.current_rt->buffers.active)
- _prepare_depth_texture();
- _post_process(env, p_cam_projection);
- // Needed only for debugging
- /* if (shadow_atlas && storage->frame.current_rt) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
- }
-
- if (storage->frame.current_rt) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, exposure_shrink[4].color);
- //glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1));
- }
-
- if (reflection_atlas && storage->frame.current_rt) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
- }
-
- if (directional_shadow.fbo) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
- }
-
- if ( env_radiance_tex) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, env_radiance_tex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }*/
- //disable all stuff
-}
-
-void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
-
- render_pass++;
-
- directional_light = NULL;
-
- LightInstance *light_instance = light_instance_owner.getornull(p_light);
- ERR_FAIL_COND(!light_instance);
- RasterizerStorageGLES3::Light *light = storage->light_owner.getornull(light_instance->light);
- ERR_FAIL_COND(!light);
-
- uint32_t x, y, width, height;
-
- float dp_direction = 0.0;
- float zfar = 0;
- bool flip_facing = false;
- int custom_vp_size = 0;
- GLuint fbo;
- int current_cubemap = -1;
- float bias = 0;
- float normal_bias = 0;
-
- state.used_depth_prepass = false;
-
- CameraMatrix light_projection;
- Transform light_transform;
-
- if (light->type == VS::LIGHT_DIRECTIONAL) {
- //set pssm stuff
- if (light_instance->last_scene_shadow_pass != scene_pass) {
- //assign rect if unassigned
- light_instance->light_directional_index = directional_shadow.current_light;
- light_instance->last_scene_shadow_pass = scene_pass;
- directional_shadow.current_light++;
-
- if (directional_shadow.light_count == 1) {
- light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size);
- } else if (directional_shadow.light_count == 2) {
- light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size / 2);
- if (light_instance->light_directional_index == 1) {
- light_instance->directional_rect.position.x += light_instance->directional_rect.size.x;
- }
- } else { //3 and 4
- light_instance->directional_rect = Rect2(0, 0, directional_shadow.size / 2, directional_shadow.size / 2);
- if (light_instance->light_directional_index & 1) {
- light_instance->directional_rect.position.x += light_instance->directional_rect.size.x;
- }
- if (light_instance->light_directional_index / 2) {
- light_instance->directional_rect.position.y += light_instance->directional_rect.size.y;
- }
- }
- }
-
- light_projection = light_instance->shadow_transform[p_pass].camera;
- light_transform = light_instance->shadow_transform[p_pass].transform;
-
- x = light_instance->directional_rect.position.x;
- y = light_instance->directional_rect.position.y;
- width = light_instance->directional_rect.size.x;
- height = light_instance->directional_rect.size.y;
-
- if (light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
-
- width /= 2;
- height /= 2;
-
- if (p_pass == 1) {
- x += width;
- } else if (p_pass == 2) {
- y += height;
- } else if (p_pass == 3) {
- x += width;
- y += height;
- }
-
- } else if (light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
-
- height /= 2;
-
- if (p_pass == 0) {
-
- } else {
- y += height;
- }
- }
-
- float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]);
- zfar = light->param[VS::LIGHT_PARAM_RANGE];
- bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS] * bias_mult;
- normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * bias_mult;
- fbo = directional_shadow.fbo;
-
- } else {
- //set from shadow atlas
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
- ERR_FAIL_COND(!shadow_atlas);
- ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light));
-
- fbo = shadow_atlas->fbo;
-
- uint32_t key = shadow_atlas->shadow_owners[p_light];
-
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- ERR_FAIL_INDEX((int)shadow, shadow_atlas->quadrants[quadrant].shadows.size());
-
- uint32_t quadrant_size = shadow_atlas->size >> 1;
-
- x = (quadrant & 1) * quadrant_size;
- y = (quadrant >> 1) * quadrant_size;
-
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
- x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
-
- width = shadow_size;
- height = shadow_size;
-
- if (light->type == VS::LIGHT_OMNI) {
-
- if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE) {
-
- int cubemap_index = shadow_cubemaps.size() - 1;
-
- for (int i = shadow_cubemaps.size() - 1; i >= 0; i--) {
- //find appropriate cubemap to render to
- if (shadow_cubemaps[i].size > shadow_size * 2)
- break;
-
- cubemap_index = i;
- }
-
- fbo = shadow_cubemaps[cubemap_index].fbo_id[p_pass];
- light_projection = light_instance->shadow_transform[0].camera;
- light_transform = light_instance->shadow_transform[0].transform;
- custom_vp_size = shadow_cubemaps[cubemap_index].size;
- zfar = light->param[VS::LIGHT_PARAM_RANGE];
-
- current_cubemap = cubemap_index;
-
- } else {
-
- light_projection = light_instance->shadow_transform[0].camera;
- light_transform = light_instance->shadow_transform[0].transform;
-
- if (light->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
-
- height /= 2;
- y += p_pass * height;
- } else {
- width /= 2;
- x += p_pass * width;
- }
-
- dp_direction = p_pass == 0 ? 1.0 : -1.0;
- flip_facing = (p_pass == 1);
- zfar = light->param[VS::LIGHT_PARAM_RANGE];
- bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS];
-
- state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH_DUAL_PARABOLOID, true);
- }
-
- } else if (light->type == VS::LIGHT_SPOT) {
-
- light_projection = light_instance->shadow_transform[0].camera;
- light_transform = light_instance->shadow_transform[0].transform;
-
- dp_direction = 1.0;
- flip_facing = false;
- zfar = light->param[VS::LIGHT_PARAM_RANGE];
- bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS];
- normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS];
- }
- }
-
- render_list.clear();
- _fill_render_list(p_cull_result, p_cull_count, true, true);
-
- render_list.sort_by_depth(false); //shadow is front to back for performance
-
- glDisable(GL_BLEND);
- glDisable(GL_DITHER);
- glEnable(GL_DEPTH_TEST);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- glDepthMask(true);
- glColorMask(0, 0, 0, 0);
-
- if (custom_vp_size) {
- glViewport(0, 0, custom_vp_size, custom_vp_size);
- glScissor(0, 0, custom_vp_size, custom_vp_size);
-
- } else {
- glViewport(x, y, width, height);
- glScissor(x, y, width, height);
- }
-
- glEnable(GL_SCISSOR_TEST);
- glClearDepth(1.0f);
- glClear(GL_DEPTH_BUFFER_BIT);
- glDisable(GL_SCISSOR_TEST);
-
- state.ubo_data.z_offset = bias;
- state.ubo_data.z_slope_scale = normal_bias;
- state.ubo_data.shadow_dual_paraboloid_render_side = dp_direction;
- state.ubo_data.shadow_dual_paraboloid_render_zfar = zfar;
- state.ubo_data.opaque_prepass_threshold = 0.1;
-
- _setup_environment(NULL, light_projection, light_transform);
-
- state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true);
-
- if (light->reverse_cull) {
- flip_facing = !flip_facing;
- }
- _render_list(render_list.elements, render_list.element_count, light_transform, light_projection, NULL, flip_facing, false, true, false, false);
-
- state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false);
- state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH_DUAL_PARABOLOID, false);
-
- if (light->type == VS::LIGHT_OMNI && light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && p_pass == 5) {
- //convert the chosen cubemap to dual paraboloid!
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
-
- glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
- state.cube_to_dp_shader.bind();
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_CUBE_MAP, shadow_cubemaps[current_cubemap].cubemap);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glDisable(GL_CULL_FACE);
-
- for (int i = 0; i < 2; i++) {
-
- state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_FLIP, i == 1);
- state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_NEAR, light_projection.get_z_near());
- state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::Z_FAR, light_projection.get_z_far());
- state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES3::BIAS, light->param[VS::LIGHT_PARAM_SHADOW_BIAS]);
-
- uint32_t local_width = width, local_height = height;
- uint32_t local_x = x, local_y = y;
- if (light->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) {
-
- local_height /= 2;
- local_y += i * local_height;
- } else {
- local_width /= 2;
- local_x += i * local_width;
- }
-
- glViewport(local_x, local_y, local_width, local_height);
- glScissor(local_x, local_y, local_width, local_height);
- glEnable(GL_SCISSOR_TEST);
- glClearDepth(1.0f);
- glClear(GL_DEPTH_BUFFER_BIT);
- glDisable(GL_SCISSOR_TEST);
- //glDisable(GL_DEPTH_TEST);
- glDisable(GL_BLEND);
-
- _copy_screen();
- }
- }
-
- glColorMask(1, 1, 1, 1);
-}
-
-void RasterizerSceneGLES3::set_scene_pass(uint64_t p_pass) {
- scene_pass = p_pass;
-}
-
-bool RasterizerSceneGLES3::free(RID p_rid) {
-
- if (light_instance_owner.owns(p_rid)) {
-
- LightInstance *light_instance = light_instance_owner.getornull(p_rid);
-
- //remove from shadow atlases..
- for (Set::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(E->get());
- ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid));
- uint32_t key = shadow_atlas->shadow_owners[p_rid];
- uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
- shadow_atlas->shadow_owners.erase(p_rid);
- }
-
- light_instance_owner.free(p_rid);
- memdelete(light_instance);
-
- } else if (shadow_atlas_owner.owns(p_rid)) {
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_rid);
- shadow_atlas_set_size(p_rid, 0);
- shadow_atlas_owner.free(p_rid);
- memdelete(shadow_atlas);
- } else if (reflection_atlas_owner.owns(p_rid)) {
-
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_rid);
- reflection_atlas_set_size(p_rid, 0);
- reflection_atlas_owner.free(p_rid);
- memdelete(reflection_atlas);
- } else if (reflection_probe_instance_owner.owns(p_rid)) {
-
- ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.getornull(p_rid);
-
- reflection_probe_release_atlas_index(p_rid);
- reflection_probe_instance_owner.free(p_rid);
- memdelete(reflection_instance);
-
- } else if (environment_owner.owns(p_rid)) {
-
- Environment *environment = environment_owner.getornull(p_rid);
-
- environment_owner.free(p_rid);
- memdelete(environment);
-
- } else if (gi_probe_instance_owner.owns(p_rid)) {
-
- GIProbeInstance *gi_probe_instance = gi_probe_instance_owner.getornull(p_rid);
-
- gi_probe_instance_owner.free(p_rid);
- memdelete(gi_probe_instance);
-
- } else {
- return false;
- }
-
- return true;
-}
-
-void RasterizerSceneGLES3::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {
-
- state.debug_draw = p_debug_draw;
-}
-
-void RasterizerSceneGLES3::initialize() {
-
- render_pass = 0;
-
- state.scene_shader.init();
-
- {
- //default material and shader
-
- default_shader = storage->shader_create();
- storage->shader_set_code(default_shader, "shader_type spatial;\n");
- default_material = storage->material_create();
- storage->material_set_shader(default_material, default_shader);
-
- default_shader_twosided = storage->shader_create();
- default_material_twosided = storage->material_create();
- storage->shader_set_code(default_shader_twosided, "shader_type spatial; render_mode cull_disabled;\n");
- storage->material_set_shader(default_material_twosided, default_shader_twosided);
-
- //default for shaders using world coordinates (typical for triplanar)
-
- default_worldcoord_shader = storage->shader_create();
- storage->shader_set_code(default_worldcoord_shader, "shader_type spatial; render_mode world_vertex_coords;\n");
- default_worldcoord_material = storage->material_create();
- storage->material_set_shader(default_worldcoord_material, default_worldcoord_shader);
-
- default_worldcoord_shader_twosided = storage->shader_create();
- default_worldcoord_material_twosided = storage->material_create();
- storage->shader_set_code(default_worldcoord_shader_twosided, "shader_type spatial; render_mode cull_disabled,world_vertex_coords;\n");
- storage->material_set_shader(default_worldcoord_material_twosided, default_worldcoord_shader_twosided);
- }
-
- {
- //default material and shader
-
- default_overdraw_shader = storage->shader_create();
- storage->shader_set_code(default_overdraw_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }");
- default_overdraw_material = storage->material_create();
- storage->material_set_shader(default_overdraw_material, default_overdraw_shader);
- }
-
- glGenBuffers(1, &state.scene_ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(State::SceneDataUBO), &state.scene_ubo, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- glGenBuffers(1, &state.env_radiance_ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_ubo, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,1000000,1"));
- render_list.max_lights = GLOBAL_DEF("rendering/limits/rendering/max_renderable_lights", (int)RenderList::DEFAULT_MAX_LIGHTS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_lights", PROPERTY_HINT_RANGE, "16,4096,1"));
- render_list.max_reflections = GLOBAL_DEF("rendering/limits/rendering/max_renderable_reflections", (int)RenderList::DEFAULT_MAX_REFLECTIONS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/rendering/max_renderable_reflections", PropertyInfo(Variant::INT, "rendering/limits/rendering/max_renderable_reflections", PROPERTY_HINT_RANGE, "8,1024,1"));
-
- {
- //quad buffers
-
- glGenBuffers(1, &state.sky_verts);
- glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts);
- glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, NULL, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- glGenVertexArrays(1, &state.sky_array);
- glBindVertexArray(state.sky_array);
- glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0);
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, CAST_INT_TO_UCHAR_PTR(sizeof(Vector3)));
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
- }
- render_list.init();
- state.cube_to_dp_shader.init();
-
- shadow_atlas_realloc_tolerance_msec = 500;
-
- int max_shadow_cubemap_sampler_size = 512;
-
- int cube_size = max_shadow_cubemap_sampler_size;
-
- glActiveTexture(GL_TEXTURE0);
-
- while (cube_size >= 32) {
-
- ShadowCubeMap cube;
- cube.size = cube_size;
-
- glGenTextures(1, &cube.cubemap);
- glBindTexture(GL_TEXTURE_CUBE_MAP, cube.cubemap);
- //gen cubemap first
- for (int i = 0; i < 6; i++) {
-
- glTexImage2D(_cube_side_enum[i], 0, GL_DEPTH_COMPONENT24, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
- }
-
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- // Remove artifact on the edges of the shadowmap
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- //gen renderbuffers second, because it needs a complete cubemap
- for (int i = 0; i < 6; i++) {
-
- glGenFramebuffers(1, &cube.fbo_id[i]);
- glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo_id[i]);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _cube_side_enum[i], cube.cubemap, 0);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
- }
-
- shadow_cubemaps.push_back(cube);
-
- cube_size >>= 1;
- }
-
- {
- //directional light shadow
- directional_shadow.light_count = 0;
- directional_shadow.size = next_power_of_2(GLOBAL_GET("rendering/quality/directional_shadow/size"));
- glGenFramebuffers(1, &directional_shadow.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo);
- glGenTextures(1, &directional_shadow.depth);
- glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0);
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- ERR_PRINT("Directional shadow framebuffer status invalid");
- }
- }
-
- {
- //spot and omni ubos
-
- int max_ubo_size;
- glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_ubo_size);
- const int ubo_light_size = 160;
- state.ubo_light_size = ubo_light_size;
- state.max_ubo_lights = MIN(render_list.max_lights, max_ubo_size / ubo_light_size);
-
- state.spot_array_tmp = (uint8_t *)memalloc(ubo_light_size * state.max_ubo_lights);
- state.omni_array_tmp = (uint8_t *)memalloc(ubo_light_size * state.max_ubo_lights);
-
- glGenBuffers(1, &state.spot_array_ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo);
- glBufferData(GL_UNIFORM_BUFFER, ubo_light_size * state.max_ubo_lights, NULL, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- glGenBuffers(1, &state.omni_array_ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo);
- glBufferData(GL_UNIFORM_BUFFER, ubo_light_size * state.max_ubo_lights, NULL, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- glGenBuffers(1, &state.directional_ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, state.directional_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDataUBO), NULL, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- state.max_forward_lights_per_object = 8;
-
- state.scene_shader.add_custom_define("#define MAX_LIGHT_DATA_STRUCTS " + itos(state.max_ubo_lights) + "\n");
- state.scene_shader.add_custom_define("#define MAX_FORWARD_LIGHTS " + itos(state.max_forward_lights_per_object) + "\n");
-
- state.max_ubo_reflections = MIN(render_list.max_reflections, max_ubo_size / (int)sizeof(ReflectionProbeDataUBO));
-
- state.reflection_array_tmp = (uint8_t *)memalloc(sizeof(ReflectionProbeDataUBO) * state.max_ubo_reflections);
-
- glGenBuffers(1, &state.reflection_array_ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, state.reflection_array_ubo);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeDataUBO) * state.max_ubo_reflections, NULL, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- state.scene_shader.add_custom_define("#define MAX_REFLECTION_DATA_STRUCTS " + itos(state.max_ubo_reflections) + "\n");
-
- state.max_skeleton_bones = MIN(2048, max_ubo_size / (12 * sizeof(float)));
- state.scene_shader.add_custom_define("#define MAX_SKELETON_BONES " + itos(state.max_skeleton_bones) + "\n");
- }
-
- shadow_filter_mode = SHADOW_FILTER_NEAREST;
-
- { //reflection cubemaps
- int max_reflection_cubemap_sampler_size = 512;
-
- int rcube_size = max_reflection_cubemap_sampler_size;
-
- glActiveTexture(GL_TEXTURE0);
-
- bool use_float = true;
-
- GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2;
- GLenum format = GL_RGBA;
- GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV;
-
- while (rcube_size >= 32) {
-
- ReflectionCubeMap cube;
- cube.size = rcube_size;
-
- glGenTextures(1, &cube.depth);
- glBindTexture(GL_TEXTURE_2D, cube.depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glGenTextures(1, &cube.cubemap);
- glBindTexture(GL_TEXTURE_CUBE_MAP, cube.cubemap);
- //gen cubemap first
- for (int i = 0; i < 6; i++) {
-
- glTexImage2D(_cube_side_enum[i], 0, internal_format, cube.size, cube.size, 0, format, type, NULL);
- }
-
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- // Remove artifact on the edges of the reflectionmap
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- //gen renderbuffers second, because it needs a complete cubemap
- for (int i = 0; i < 6; i++) {
-
- glGenFramebuffers(1, &cube.fbo_id[i]);
- glBindFramebuffer(GL_FRAMEBUFFER, cube.fbo_id[i]);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], cube.cubemap, 0);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, cube.depth, 0);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
- }
-
- reflection_cubemaps.push_back(cube);
-
- rcube_size >>= 1;
- }
- }
-
- {
-
- uint32_t immediate_buffer_size = GLOBAL_DEF("rendering/limits/buffers/immediate_buffer_size_kb", 2048);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/immediate_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/immediate_buffer_size_kb", PROPERTY_HINT_RANGE, "0,8192,1,or_greater"));
-
- glGenBuffers(1, &state.immediate_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, state.immediate_buffer);
- glBufferData(GL_ARRAY_BUFFER, immediate_buffer_size * 1024, NULL, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glGenVertexArrays(1, &state.immediate_array);
- }
-
-#ifdef GLES_OVER_GL
- //"desktop" opengl needs this.
- glEnable(GL_PROGRAM_POINT_SIZE);
-
-#endif
-
- state.resolve_shader.init();
- state.ssr_shader.init();
- state.effect_blur_shader.init();
- state.sss_shader.init();
- state.ssao_minify_shader.init();
- state.ssao_shader.init();
- state.ssao_blur_shader.init();
- state.exposure_shader.init();
- state.tonemap_shader.init();
-
- {
- GLOBAL_DEF("rendering/quality/subsurface_scattering/quality", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/quality", PropertyInfo(Variant::INT, "rendering/quality/subsurface_scattering/quality", PROPERTY_HINT_ENUM, "Low,Medium,High"));
- GLOBAL_DEF("rendering/quality/subsurface_scattering/scale", 1.0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/scale", PropertyInfo(Variant::INT, "rendering/quality/subsurface_scattering/scale", PROPERTY_HINT_RANGE, "0.01,8,0.01"));
- GLOBAL_DEF("rendering/quality/subsurface_scattering/follow_surface", false);
- GLOBAL_DEF("rendering/quality/subsurface_scattering/weight_samples", true);
-
- GLOBAL_DEF("rendering/quality/voxel_cone_tracing/high_quality", false);
- }
-
- exposure_shrink_size = 243;
- int max_exposure_shrink_size = exposure_shrink_size;
-
- while (max_exposure_shrink_size > 0) {
-
- RasterizerStorageGLES3::RenderTarget::Exposure e;
-
- glGenFramebuffers(1, &e.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, e.fbo);
-
- glGenTextures(1, &e.color);
- glBindTexture(GL_TEXTURE_2D, e.color);
-
- if (storage->config.framebuffer_float_supported) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL);
- } else if (storage->config.framebuffer_half_float_supported) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_HALF_FLOAT, NULL);
- } else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_UNSIGNED_INT_2_10_10_10_REV, NULL);
- }
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, e.color, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- exposure_shrink.push_back(e);
- max_exposure_shrink_size /= 3;
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
- }
-
- state.debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED;
-
- glFrontFace(GL_CW);
-}
-
-void RasterizerSceneGLES3::iteration() {
-
- shadow_filter_mode = ShadowFilterMode(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));
- subsurface_scatter_follow_surface = GLOBAL_GET("rendering/quality/subsurface_scattering/follow_surface");
- subsurface_scatter_weight_samples = GLOBAL_GET("rendering/quality/subsurface_scattering/weight_samples");
- subsurface_scatter_quality = SubSurfaceScatterQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/quality")));
- subsurface_scatter_size = GLOBAL_GET("rendering/quality/subsurface_scattering/scale");
-
- state.scene_shader.set_conditional(SceneShaderGLES3::VCT_QUALITY_HIGH, GLOBAL_GET("rendering/quality/voxel_cone_tracing/high_quality"));
-}
-
-void RasterizerSceneGLES3::finalize() {
-
- storage->free(default_material);
- storage->free(default_material_twosided);
- storage->free(default_shader);
- storage->free(default_shader_twosided);
-
- storage->free(default_worldcoord_material);
- storage->free(default_worldcoord_material_twosided);
- storage->free(default_worldcoord_shader);
- storage->free(default_worldcoord_shader_twosided);
-
- storage->free(default_overdraw_material);
- storage->free(default_overdraw_shader);
-}
-
-RasterizerSceneGLES3::RasterizerSceneGLES3() {
-}
-
-RasterizerSceneGLES3::~RasterizerSceneGLES3() {
-
- memfree(state.spot_array_tmp);
- memfree(state.omni_array_tmp);
- memfree(state.reflection_array_tmp);
-}
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
deleted file mode 100644
index abf6bb24cf..0000000000
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ /dev/null
@@ -1,878 +0,0 @@
-/*************************************************************************/
-/* rasterizer_scene_gles3.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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 RASTERIZERSCENEGLES3_H
-#define RASTERIZERSCENEGLES3_H
-
-/* Must come before shaders or the Windows build fails... */
-#include "rasterizer_storage_gles3.h"
-
-#include "drivers/gles3/shaders/cube_to_dp.glsl.gen.h"
-#include "drivers/gles3/shaders/effect_blur.glsl.gen.h"
-#include "drivers/gles3/shaders/exposure.glsl.gen.h"
-#include "drivers/gles3/shaders/resolve.glsl.gen.h"
-#include "drivers/gles3/shaders/scene.glsl.gen.h"
-#include "drivers/gles3/shaders/screen_space_reflection.glsl.gen.h"
-#include "drivers/gles3/shaders/ssao.glsl.gen.h"
-#include "drivers/gles3/shaders/ssao_blur.glsl.gen.h"
-#include "drivers/gles3/shaders/ssao_minify.glsl.gen.h"
-#include "drivers/gles3/shaders/subsurf_scattering.glsl.gen.h"
-#include "drivers/gles3/shaders/tonemap.glsl.gen.h"
-
-class RasterizerSceneGLES3 : public RasterizerScene {
-public:
- enum ShadowFilterMode {
- SHADOW_FILTER_NEAREST,
- SHADOW_FILTER_PCF5,
- SHADOW_FILTER_PCF13,
- };
-
- ShadowFilterMode shadow_filter_mode;
-
- uint64_t shadow_atlas_realloc_tolerance_msec;
-
- enum SubSurfaceScatterQuality {
- SSS_QUALITY_LOW,
- SSS_QUALITY_MEDIUM,
- SSS_QUALITY_HIGH,
- };
-
- SubSurfaceScatterQuality subsurface_scatter_quality;
- float subsurface_scatter_size;
- bool subsurface_scatter_follow_surface;
- bool subsurface_scatter_weight_samples;
-
- uint64_t render_pass;
- uint64_t scene_pass;
- uint32_t current_material_index;
- uint32_t current_geometry_index;
-
- RID default_material;
- RID default_material_twosided;
- RID default_shader;
- RID default_shader_twosided;
-
- RID default_worldcoord_material;
- RID default_worldcoord_material_twosided;
- RID default_worldcoord_shader;
- RID default_worldcoord_shader_twosided;
-
- RID default_overdraw_material;
- RID default_overdraw_shader;
-
- RasterizerStorageGLES3 *storage;
-
- Vector exposure_shrink;
- int exposure_shrink_size;
-
- struct State {
-
- bool texscreen_copied;
- int current_blend_mode;
- float current_line_width;
- int current_depth_draw;
- bool current_depth_test;
- GLuint current_main_tex;
-
- SceneShaderGLES3 scene_shader;
- CubeToDpShaderGLES3 cube_to_dp_shader;
- ResolveShaderGLES3 resolve_shader;
- ScreenSpaceReflectionShaderGLES3 ssr_shader;
- EffectBlurShaderGLES3 effect_blur_shader;
- SubsurfScatteringShaderGLES3 sss_shader;
- SsaoMinifyShaderGLES3 ssao_minify_shader;
- SsaoShaderGLES3 ssao_shader;
- SsaoBlurShaderGLES3 ssao_blur_shader;
- ExposureShaderGLES3 exposure_shader;
- TonemapShaderGLES3 tonemap_shader;
-
- struct SceneDataUBO {
- //this is a std140 compatible struct. Please read the OpenGL 3.3 Specification spec before doing any changes
- float projection_matrix[16];
- float inv_projection_matrix[16];
- float camera_inverse_matrix[16];
- float camera_matrix[16];
- float ambient_light_color[4];
- float bg_color[4];
- float fog_color_enabled[4];
- float fog_sun_color_amount[4];
-
- float ambient_energy;
- float bg_energy;
- float z_offset;
- float z_slope_scale;
- float shadow_dual_paraboloid_render_zfar;
- float shadow_dual_paraboloid_render_side;
- float viewport_size[2];
- float screen_pixel_size[2];
- float shadow_atlas_pixel_size[2];
- float shadow_directional_pixel_size[2];
-
- float time;
- float z_far;
- float reflection_multiplier;
- float subsurface_scatter_width;
- float ambient_occlusion_affect_light;
- float ambient_occlusion_affect_ssao;
- float opaque_prepass_threshold;
-
- uint32_t fog_depth_enabled;
- float fog_depth_begin;
- float fog_depth_end;
- float fog_density;
- float fog_depth_curve;
- uint32_t fog_transmit_enabled;
- float fog_transmit_curve;
- uint32_t fog_height_enabled;
- float fog_height_min;
- float fog_height_max;
- float fog_height_curve;
- // make sure this struct is padded to be a multiple of 16 bytes for webgl
- float pad[2];
-
- } ubo_data;
-
- GLuint scene_ubo;
-
- struct EnvironmentRadianceUBO {
-
- float transform[16];
- float ambient_contribution;
- uint8_t padding[12];
-
- } env_radiance_data;
-
- GLuint env_radiance_ubo;
-
- GLuint sky_verts;
- GLuint sky_array;
-
- GLuint directional_ubo;
-
- GLuint spot_array_ubo;
- GLuint omni_array_ubo;
- GLuint reflection_array_ubo;
-
- GLuint immediate_buffer;
- GLuint immediate_array;
-
- uint32_t ubo_light_size;
- uint8_t *spot_array_tmp;
- uint8_t *omni_array_tmp;
- uint8_t *reflection_array_tmp;
-
- int max_ubo_lights;
- int max_forward_lights_per_object;
- int max_ubo_reflections;
- int max_skeleton_bones;
-
- bool used_contact_shadows;
-
- int spot_light_count;
- int omni_light_count;
- int directional_light_count;
- int reflection_probe_count;
-
- bool cull_front;
- bool cull_disabled;
- bool used_sss;
- bool used_screen_texture;
-
- bool used_depth_prepass;
-
- bool used_depth_texture;
- bool prepared_depth_texture;
- bool bound_depth_texture;
-
- VS::ViewportDebugDraw debug_draw;
- } state;
-
- /* SHADOW ATLAS API */
-
- struct ShadowAtlas {
-
- enum {
- QUADRANT_SHIFT = 27,
- SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1,
- SHADOW_INVALID = 0xFFFFFFFF
- };
-
- struct Quadrant {
-
- uint32_t subdivision;
-
- struct Shadow {
- RID owner;
- uint64_t version;
- uint64_t alloc_tick;
-
- Shadow() {
- version = 0;
- alloc_tick = 0;
- }
- };
-
- Vector shadows;
-
- Quadrant() {
- subdivision = 0; //not in use
- }
-
- } quadrants[4];
-
- int size_order[4];
- uint32_t smallest_subdiv;
-
- int size;
-
- GLuint fbo;
- GLuint depth;
-
- Map shadow_owners;
- };
-
- struct ShadowCubeMap {
-
- GLuint fbo_id[6];
- GLuint cubemap;
- uint32_t size;
- };
-
- Vector shadow_cubemaps;
-
- RID_PtrOwner shadow_atlas_owner;
-
- RID shadow_atlas_create();
- void shadow_atlas_set_size(RID p_atlas, int p_size);
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
- bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
-
- struct DirectionalShadow {
- GLuint fbo;
- GLuint depth;
- int light_count;
- int size;
- int current_light;
- } directional_shadow;
-
- virtual int get_directional_light_shadow_size(RID p_light_intance);
- virtual void set_directional_shadow_count(int p_count);
-
- /* REFLECTION PROBE ATLAS API */
-
- struct ReflectionAtlas {
-
- int subdiv;
- int size;
-
- struct Reflection {
- RID owner;
- uint64_t last_frame;
- };
-
- GLuint fbo[6];
- GLuint color;
-
- Vector reflections;
- };
-
- mutable RID_PtrOwner reflection_atlas_owner;
-
- virtual RID reflection_atlas_create();
- virtual void reflection_atlas_configure(RID p_ref_atlas, int p_size, int p_count);
-
- /* REFLECTION CUBEMAPS */
-
- struct ReflectionCubeMap {
-
- GLuint fbo_id[6];
- GLuint cubemap;
- GLuint depth;
- int size;
- };
-
- Vector reflection_cubemaps;
-
- /* REFLECTION PROBE INSTANCE */
-
- struct ReflectionProbeInstance {
-
- RasterizerStorageGLES3::ReflectionProbe *probe_ptr;
- RID probe;
- RID self;
- RID atlas;
-
- int reflection_atlas_index;
-
- int render_step;
-
- uint64_t last_pass;
- int reflection_index;
-
- Transform transform;
- };
-
- struct ReflectionProbeDataUBO {
-
- float box_extents[4];
- float box_ofs[4];
- float params[4]; // intensity, 0, 0, boxproject
- float ambient[4]; //color, probe contrib
- float atlas_clamp[4];
- float local_matrix[16]; //up to here for spot and omni, rest is for directional
- //notes: for ambientblend, use distance to edge to blend between already existing global environment
- };
-
- mutable RID_PtrOwner reflection_probe_instance_owner;
-
- virtual RID reflection_probe_instance_create(RID p_probe);
- virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
- virtual void reflection_probe_release_atlas_index(RID p_instance);
- virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
- virtual bool reflection_probe_instance_has_reflection(RID p_instance);
- virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas);
- virtual bool reflection_probe_instance_postprocess_step(RID p_instance);
-
- /* ENVIRONMENT API */
-
- struct Environment {
-
- VS::EnvironmentBG bg_mode;
-
- RID sky;
- float sky_custom_fov;
- Basis sky_orientation;
-
- Color bg_color;
- float bg_energy;
- float sky_ambient;
-
- int camera_feed_id;
-
- Color ambient_color;
- float ambient_energy;
- float ambient_sky_contribution;
-
- int canvas_max_layer;
-
- bool ssr_enabled;
- int ssr_max_steps;
- float ssr_fade_in;
- float ssr_fade_out;
- float ssr_depth_tolerance;
- bool ssr_roughness;
-
- bool ssao_enabled;
- float ssao_intensity;
- float ssao_radius;
- float ssao_intensity2;
- float ssao_radius2;
- float ssao_bias;
- float ssao_light_affect;
- float ssao_ao_channel_affect;
- Color ssao_color;
- VS::EnvironmentSSAOQuality ssao_quality;
- float ssao_bilateral_sharpness;
- VS::EnvironmentSSAOBlur ssao_filter;
-
- bool glow_enabled;
- int glow_levels;
- float glow_intensity;
- float glow_strength;
- float glow_bloom;
- VS::EnvironmentGlowBlendMode glow_blend_mode;
- float glow_hdr_bleed_threshold;
- float glow_hdr_bleed_scale;
- float glow_hdr_luminance_cap;
- bool glow_bicubic_upscale;
-
- VS::EnvironmentToneMapper tone_mapper;
- float tone_mapper_exposure;
- float tone_mapper_exposure_white;
- bool auto_exposure;
- float auto_exposure_speed;
- float auto_exposure_min;
- float auto_exposure_max;
- float auto_exposure_grey;
-
- bool dof_blur_far_enabled;
- float dof_blur_far_distance;
- float dof_blur_far_transition;
- float dof_blur_far_amount;
- VS::EnvironmentDOFBlurQuality dof_blur_far_quality;
-
- bool dof_blur_near_enabled;
- float dof_blur_near_distance;
- float dof_blur_near_transition;
- float dof_blur_near_amount;
- VS::EnvironmentDOFBlurQuality dof_blur_near_quality;
-
- bool adjustments_enabled;
- float adjustments_brightness;
- float adjustments_contrast;
- float adjustments_saturation;
- RID color_correction;
-
- bool fog_enabled;
- Color fog_color;
- Color fog_sun_color;
- float fog_sun_amount;
-
- bool fog_depth_enabled;
- float fog_depth_begin;
- float fog_depth_end;
- float fog_depth_curve;
- bool fog_transmit_enabled;
- float fog_transmit_curve;
- bool fog_height_enabled;
- float fog_height_min;
- float fog_height_max;
- float fog_height_curve;
-
- Environment() :
- bg_mode(VS::ENV_BG_CLEAR_COLOR),
- sky_custom_fov(0.0),
- bg_energy(1.0),
- sky_ambient(0),
- camera_feed_id(0),
- ambient_energy(1.0),
- ambient_sky_contribution(0.0),
- canvas_max_layer(0),
- ssr_enabled(false),
- ssr_max_steps(64),
- ssr_fade_in(0.15),
- ssr_fade_out(2.0),
- ssr_depth_tolerance(0.2),
- ssr_roughness(true),
- ssao_enabled(false),
- ssao_intensity(1.0),
- ssao_radius(1.0),
- ssao_intensity2(1.0),
- ssao_radius2(0.0),
- ssao_bias(0.01),
- ssao_light_affect(0),
- ssao_ao_channel_affect(0),
- ssao_quality(VS::ENV_SSAO_QUALITY_LOW),
- ssao_bilateral_sharpness(4),
- ssao_filter(VS::ENV_SSAO_BLUR_3x3),
- glow_enabled(false),
- glow_levels((1 << 2) | (1 << 4)),
- glow_intensity(0.8),
- glow_strength(1.0),
- glow_bloom(0.0),
- glow_blend_mode(VS::ENV_GLOW_BLEND_MODE_SOFTLIGHT),
- glow_hdr_bleed_threshold(1.0),
- glow_hdr_bleed_scale(2.0),
- glow_hdr_luminance_cap(12.0),
- glow_bicubic_upscale(false),
- tone_mapper(VS::ENV_TONE_MAPPER_LINEAR),
- tone_mapper_exposure(1.0),
- tone_mapper_exposure_white(1.0),
- auto_exposure(false),
- auto_exposure_speed(0.5),
- auto_exposure_min(0.05),
- auto_exposure_max(8),
- auto_exposure_grey(0.4),
- dof_blur_far_enabled(false),
- dof_blur_far_distance(10),
- dof_blur_far_transition(5),
- dof_blur_far_amount(0.1),
- dof_blur_far_quality(VS::ENV_DOF_BLUR_QUALITY_MEDIUM),
- dof_blur_near_enabled(false),
- dof_blur_near_distance(2),
- dof_blur_near_transition(1),
- dof_blur_near_amount(0.1),
- dof_blur_near_quality(VS::ENV_DOF_BLUR_QUALITY_MEDIUM),
- adjustments_enabled(false),
- adjustments_brightness(1.0),
- adjustments_contrast(1.0),
- adjustments_saturation(1.0),
- fog_enabled(false),
- fog_color(Color(0.5, 0.5, 0.5)),
- fog_sun_color(Color(0.8, 0.8, 0.0)),
- fog_sun_amount(0),
- fog_depth_enabled(true),
- fog_depth_begin(10),
- fog_depth_end(0),
- fog_depth_curve(1),
- fog_transmit_enabled(true),
- fog_transmit_curve(1),
- fog_height_enabled(false),
- fog_height_min(10),
- fog_height_max(0),
- fog_height_curve(1) {
- }
- };
-
- RID_PtrOwner environment_owner;
-
- virtual RID environment_create();
-
- virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg);
- virtual void environment_set_sky(RID p_env, RID p_sky);
- virtual void environment_set_sky_custom_fov(RID p_env, float p_scale);
- virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
- virtual void environment_set_bg_color(RID p_env, const Color &p_color);
- virtual void environment_set_bg_energy(RID p_env, float p_energy);
- virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0);
- virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id);
-
- virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality);
- virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality);
- virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale);
- virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture);
-
- virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness);
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness);
-
- virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
-
- virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp);
-
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount);
- virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve);
- virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve);
-
- virtual bool is_environment(RID p_env);
-
- virtual VS::EnvironmentBG environment_get_background(RID p_env);
- virtual int environment_get_canvas_max_layer(RID p_env);
-
- /* LIGHT INSTANCE */
-
- struct LightDataUBO {
-
- float light_pos_inv_radius[4];
- float light_direction_attenuation[4];
- float light_color_energy[4];
- float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled
- float light_clamp[4];
- float light_shadow_color_contact[4];
- union {
- struct {
- float matrix1[16]; //up to here for spot and omni, rest is for directional
- float matrix2[16];
- float matrix3[16];
- float matrix4[16];
- };
- float matrix[4 * 16];
- } shadow;
- float shadow_split_offsets[4];
- };
-
- struct LightInstance {
-
- struct ShadowTransform {
-
- CameraMatrix camera;
- Transform transform;
- float farplane;
- float split;
- float bias_scale;
- };
-
- ShadowTransform shadow_transform[4];
-
- RID self;
- RID light;
- RasterizerStorageGLES3::Light *light_ptr;
- Transform transform;
-
- Vector3 light_vector;
- Vector3 spot_vector;
- float linear_att;
-
- uint64_t shadow_pass;
- uint64_t last_scene_pass;
- uint64_t last_scene_shadow_pass;
- uint64_t last_pass;
- uint16_t light_index;
- uint16_t light_directional_index;
-
- uint32_t current_shadow_atlas_key;
-
- Vector2 dp;
-
- Rect2 directional_rect;
-
- Set shadow_atlases; //shadow atlases where this light is registered
-
- LightInstance() {}
- };
-
- mutable RID_PtrOwner light_instance_owner;
-
- virtual RID light_instance_create(RID p_light);
- virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
- virtual void light_instance_mark_visible(RID p_light_instance);
-
- /* REFLECTION INSTANCE */
-
- struct GIProbeInstance {
- RID data;
- RasterizerStorageGLES3::GIProbe *probe;
- GLuint tex_cache;
- Vector3 cell_size_cache;
- Vector3 bounds;
- Transform transform_to_data;
-
- GIProbeInstance() :
- probe(NULL),
- tex_cache(0) {
- }
- };
-
- mutable RID_PtrOwner gi_probe_instance_owner;
-
- virtual RID gi_probe_instance_create();
- virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data);
- virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
- virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds);
-
- /* RENDER LIST */
-
- struct RenderList {
-
- enum {
- DEFAULT_MAX_ELEMENTS = 65536,
- SORT_FLAG_SKELETON = 1,
- SORT_FLAG_INSTANCING = 2,
- MAX_DIRECTIONAL_LIGHTS = 16,
- DEFAULT_MAX_LIGHTS = 4096,
- DEFAULT_MAX_REFLECTIONS = 1024,
-
- SORT_KEY_PRIORITY_SHIFT = 56,
- SORT_KEY_PRIORITY_MASK = 0xFF,
- //depth layer for opaque (56-52)
- SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT = 52,
- SORT_KEY_OPAQUE_DEPTH_LAYER_MASK = 0xF,
-//64 bits unsupported in MSVC
-#define SORT_KEY_UNSHADED_FLAG (uint64_t(1) << 49)
-#define SORT_KEY_NO_DIRECTIONAL_FLAG (uint64_t(1) << 48)
-#define SORT_KEY_LIGHTMAP_CAPTURE_FLAG (uint64_t(1) << 47)
-#define SORT_KEY_LIGHTMAP_FLAG (uint64_t(1) << 46)
-#define SORT_KEY_GI_PROBES_FLAG (uint64_t(1) << 45)
-#define SORT_KEY_VERTEX_LIT_FLAG (uint64_t(1) << 44)
- SORT_KEY_SHADING_SHIFT = 44,
- SORT_KEY_SHADING_MASK = 63,
- //44-28 material index
- SORT_KEY_MATERIAL_INDEX_SHIFT = 28,
- //28-8 geometry index
- SORT_KEY_GEOMETRY_INDEX_SHIFT = 8,
- //bits 5-7 geometry type
- SORT_KEY_GEOMETRY_TYPE_SHIFT = 5,
- //bits 0-5 for flags
- SORT_KEY_OPAQUE_PRE_PASS = 8,
- SORT_KEY_CULL_DISABLED_FLAG = 4,
- SORT_KEY_SKELETON_FLAG = 2,
- SORT_KEY_MIRROR_FLAG = 1
-
- };
-
- int max_elements;
- int max_lights;
- int max_reflections;
-
- struct Element {
-
- RasterizerScene::InstanceBase *instance;
- RasterizerStorageGLES3::Geometry *geometry;
- RasterizerStorageGLES3::Material *material;
- RasterizerStorageGLES3::GeometryOwner *owner;
- uint64_t sort_key;
- };
-
- Element *base_elements;
- Element **elements;
-
- int element_count;
- int alpha_element_count;
-
- void clear() {
-
- element_count = 0;
- alpha_element_count = 0;
- }
-
- //should eventually be replaced by radix
-
- struct SortByKey {
-
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- return A->sort_key < B->sort_key;
- }
- };
-
- void sort_by_key(bool p_alpha) {
-
- SortArray sorter;
- if (p_alpha) {
- sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
- } else {
- sorter.sort(elements, element_count);
- }
- }
-
- struct SortByDepth {
-
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- return A->instance->depth < B->instance->depth;
- }
- };
-
- void sort_by_depth(bool p_alpha) { //used for shadows
-
- SortArray sorter;
- if (p_alpha) {
- sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
- } else {
- sorter.sort(elements, element_count);
- }
- }
-
- struct SortByReverseDepthAndPriority {
-
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- uint32_t layer_A = uint32_t(A->sort_key >> SORT_KEY_PRIORITY_SHIFT);
- uint32_t layer_B = uint32_t(B->sort_key >> SORT_KEY_PRIORITY_SHIFT);
- if (layer_A == layer_B) {
- return A->instance->depth > B->instance->depth;
- } else {
- return layer_A < layer_B;
- }
- }
- };
-
- void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
-
- SortArray sorter;
- if (p_alpha) {
- sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
- } else {
- sorter.sort(elements, element_count);
- }
- }
-
- _FORCE_INLINE_ Element *add_element() {
-
- if (element_count + alpha_element_count >= max_elements)
- return NULL;
- elements[element_count] = &base_elements[element_count];
- return elements[element_count++];
- }
-
- _FORCE_INLINE_ Element *add_alpha_element() {
-
- if (element_count + alpha_element_count >= max_elements)
- return NULL;
- int idx = max_elements - alpha_element_count - 1;
- elements[idx] = &base_elements[idx];
- alpha_element_count++;
- return elements[idx];
- }
-
- void init() {
-
- element_count = 0;
- alpha_element_count = 0;
- elements = memnew_arr(Element *, max_elements);
- base_elements = memnew_arr(Element, max_elements);
- for (int i = 0; i < max_elements; i++)
- elements[i] = &base_elements[i]; // assign elements
- }
-
- RenderList() {
-
- max_elements = DEFAULT_MAX_ELEMENTS;
- max_lights = DEFAULT_MAX_LIGHTS;
- max_reflections = DEFAULT_MAX_REFLECTIONS;
- }
-
- ~RenderList() {
- memdelete_arr(elements);
- memdelete_arr(base_elements);
- }
- };
-
- LightInstance *directional_light;
- LightInstance *directional_lights[RenderList::MAX_DIRECTIONAL_LIGHTS];
-
- RenderList render_list;
-
- _FORCE_INLINE_ void _set_cull(bool p_front, bool p_disabled, bool p_reverse_cull);
-
- _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_alpha_pass);
- _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e, const Transform &p_view_transform);
- _FORCE_INLINE_ void _render_geometry(RenderList::Element *e);
- _FORCE_INLINE_ void _setup_light(RenderList::Element *e, const Transform &p_view_transform);
-
- void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RasterizerStorageGLES3::Sky *p_sky, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
-
- _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass);
-
- _FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_shadow_pass);
-
- void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation);
-
- void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog = false);
- void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows);
- void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas);
- void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_reflection_atlas, Environment *p_env);
-
- void _copy_screen(bool p_invalidate_color = false, bool p_invalidate_depth = false);
- void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug
-
- void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass);
-
- void _blur_effect_buffer();
- void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);
- void _post_process(Environment *env, const CameraMatrix &p_cam_projection);
-
- void _prepare_depth_texture();
- void _bind_depth_texture();
-
- virtual void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
- virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
- virtual bool free(RID p_rid);
-
- virtual void set_scene_pass(uint64_t p_pass);
- virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw);
-
- void iteration();
- void initialize();
- void finalize();
- RasterizerSceneGLES3();
- ~RasterizerSceneGLES3();
-};
-
-#endif // RASTERIZERSCENEGLES3_H
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
deleted file mode 100644
index 0aee19784e..0000000000
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ /dev/null
@@ -1,8404 +0,0 @@
-/*************************************************************************/
-/* rasterizer_storage_gles3.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#include "rasterizer_storage_gles3.h"
-#include "core/engine.h"
-#include "core/project_settings.h"
-#include "rasterizer_canvas_gles3.h"
-#include "rasterizer_scene_gles3.h"
-
-/* TEXTURE API */
-
-#define _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
-#define _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
-#define _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
-#define _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
-
-#define _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
-#define _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
-#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
-#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
-
-#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
-#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
-#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
-
-#define _EXT_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
-#define _EXT_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
-#define _EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
-#define _EXT_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
-
-#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB
-#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB
-#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
-#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD
-#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
-#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
-#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
-#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
-#define _EXT_ETC1_RGB8_OES 0x8D64
-
-#define _EXT_SLUMINANCE_NV 0x8C46
-#define _EXT_SLUMINANCE_ALPHA_NV 0x8C44
-#define _EXT_SRGB8_NV 0x8C41
-#define _EXT_SLUMINANCE8_NV 0x8C47
-#define _EXT_SLUMINANCE8_ALPHA8_NV 0x8C45
-
-#define _EXT_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C
-#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D
-#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E
-#define _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F
-
-#define _EXT_ATC_RGB_AMD 0x8C92
-#define _EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
-#define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
-
-#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
-
-#define _GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
-#define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
-
-#define _EXT_COMPRESSED_R11_EAC 0x9270
-#define _EXT_COMPRESSED_SIGNED_R11_EAC 0x9271
-#define _EXT_COMPRESSED_RG11_EAC 0x9272
-#define _EXT_COMPRESSED_SIGNED_RG11_EAC 0x9273
-#define _EXT_COMPRESSED_RGB8_ETC2 0x9274
-#define _EXT_COMPRESSED_SRGB8_ETC2 0x9275
-#define _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
-#define _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
-#define _EXT_COMPRESSED_RGBA8_ETC2_EAC 0x9278
-#define _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
-
-#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
-#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
-#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
-#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
-
-#ifndef GLES_OVER_GL
-#define glClearDepth glClearDepthf
-#endif
-
-#ifdef __EMSCRIPTEN__
-#include
-
-void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) {
-
- /* clang-format off */
- EM_ASM({
- GLctx.getBufferSubData($0, $1, HEAPU8, $2, $3);
- }, target, offset, data, size);
- /* clang-format on */
-}
-#endif
-
-void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) {
-
-#ifdef GLES_OVER_GL
-
- for (int i = 0; i < levels; i++) {
- glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
- width = MAX(1, (width / 2));
- height = MAX(1, (height / 2));
- }
-
-#else
- glTexStorage2D(target, levels, internalformat, width, height);
-#endif
-}
-
-GLuint RasterizerStorageGLES3::system_fbo = 0;
-
-Ref RasterizerStorageGLES3::_get_gl_image_and_format(const Ref &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &r_srgb, bool p_force_decompress) const {
-
- r_compressed = false;
- r_gl_format = 0;
- r_real_format = p_format;
- Ref image = p_image;
- r_srgb = false;
-
- bool need_decompress = false;
-
- switch (p_format) {
-
- case Image::FORMAT_L8: {
-#ifdef GLES_OVER_GL
- r_gl_internal_format = GL_R8;
- r_gl_format = GL_RED;
- r_gl_type = GL_UNSIGNED_BYTE;
-#else
- r_gl_internal_format = GL_LUMINANCE;
- r_gl_format = GL_LUMINANCE;
- r_gl_type = GL_UNSIGNED_BYTE;
-#endif
- } break;
- case Image::FORMAT_LA8: {
-#ifdef GLES_OVER_GL
- r_gl_internal_format = GL_RG8;
- r_gl_format = GL_RG;
- r_gl_type = GL_UNSIGNED_BYTE;
-#else
- r_gl_internal_format = GL_LUMINANCE_ALPHA;
- r_gl_format = GL_LUMINANCE_ALPHA;
- r_gl_type = GL_UNSIGNED_BYTE;
-#endif
- } break;
- case Image::FORMAT_R8: {
-
- 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 = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8 : GL_RGB8;
- r_gl_format = GL_RGB;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_srgb = true;
-
- } break;
- case Image::FORMAT_RGBA8: {
-
- r_gl_format = GL_RGBA;
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_srgb = true;
-
- } 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_RGB5_A1;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1;
-
- } break;
- case Image::FORMAT_RF: {
-
- r_gl_internal_format = GL_R32F;
- r_gl_format = GL_RED;
- r_gl_type = GL_FLOAT;
-
- } break;
- case Image::FORMAT_RGF: {
-
- r_gl_internal_format = GL_RG32F;
- r_gl_format = GL_RG;
- r_gl_type = GL_FLOAT;
-
- } break;
- case Image::FORMAT_RGBF: {
-
- r_gl_internal_format = GL_RGB32F;
- r_gl_format = GL_RGB;
- r_gl_type = GL_FLOAT;
-
- } break;
- case Image::FORMAT_RGBAF: {
-
- r_gl_internal_format = GL_RGBA32F;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_FLOAT;
-
- } break;
- case Image::FORMAT_RH: {
- r_gl_internal_format = GL_R32F;
- r_gl_format = GL_RED;
- r_gl_type = GL_HALF_FLOAT;
- } break;
- case Image::FORMAT_RGH: {
- r_gl_internal_format = GL_RG32F;
- r_gl_format = GL_RG;
- r_gl_type = GL_HALF_FLOAT;
-
- } break;
- case Image::FORMAT_RGBH: {
- r_gl_internal_format = GL_RGB32F;
- r_gl_format = GL_RGB;
- r_gl_type = GL_HALF_FLOAT;
-
- } break;
- case Image::FORMAT_RGBAH: {
- r_gl_internal_format = GL_RGBA32F;
- 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;
- case Image::FORMAT_DXT1: {
-
- if (config.s3tc_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_DXT3: {
-
- if (config.s3tc_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_DXT5: {
-
- if (config.s3tc_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV : _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_RGTC_R: {
-
- if (config.rgtc_supported) {
-
- r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_RGTC_RG: {
-
- if (config.rgtc_supported) {
-
- r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_BPTC_RGBA: {
-
- if (config.bptc_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM : _EXT_COMPRESSED_RGBA_BPTC_UNORM;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_BPTC_RGBF: {
-
- if (config.bptc_supported) {
-
- r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
- r_gl_format = GL_RGB;
- r_gl_type = GL_FLOAT;
- r_compressed = true;
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_BPTC_RGBFU: {
- if (config.bptc_supported) {
-
- r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
- r_gl_format = GL_RGB;
- r_gl_type = GL_FLOAT;
- r_compressed = true;
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_PVRTC2: {
-
- if (config.pvrtc_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT : _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_PVRTC2A: {
-
- if (config.pvrtc_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT : _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_PVRTC4: {
-
- if (config.pvrtc_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT : _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_PVRTC4A: {
-
- if (config.pvrtc_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT : _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_ETC: {
-
- if (config.etc_supported) {
-
- r_gl_internal_format = _EXT_ETC1_RGB8_OES;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
-
- need_decompress = true;
- }
-
- } break;
- case Image::FORMAT_ETC2_R11: {
-
- if (config.etc2_supported) {
-
- r_gl_internal_format = _EXT_COMPRESSED_R11_EAC;
- r_gl_format = GL_RED;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_R11S: {
-
- if (config.etc2_supported) {
-
- r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC;
- r_gl_format = GL_RED;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RG11: {
-
- if (config.etc2_supported) {
-
- r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC;
- r_gl_format = GL_RG;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RG11S: {
- if (config.etc2_supported) {
-
- r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC;
- r_gl_format = GL_RG;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RGB8: {
-
- if (config.etc2_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB8_ETC2 : _EXT_COMPRESSED_RGB8_ETC2;
- r_gl_format = GL_RGB;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RGBA8: {
-
- if (config.etc2_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : _EXT_COMPRESSED_RGBA8_ETC2_EAC;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RGB8A1: {
-
- if (config.etc2_supported) {
-
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? _EXT_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- r_srgb = true;
-
- } else {
-
- need_decompress = true;
- }
- } break;
- default: {
-
- ERR_FAIL_V(Ref());
- }
- }
-
- if (need_decompress || p_force_decompress) {
-
- if (!image.is_null()) {
- image = image->duplicate();
- image->decompress();
- ERR_FAIL_COND_V(image->is_compressed(), image);
- image->convert(Image::FORMAT_RGBA8);
- }
-
- r_gl_format = GL_RGBA;
- r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = false;
- r_real_format = Image::FORMAT_RGBA8;
- r_srgb = true;
-
- return image;
- }
-
- return image;
-}
-
-static const GLenum _cube_side_enum[6] = {
-
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- GL_TEXTURE_CUBE_MAP_POSITIVE_X,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
-
-};
-
-RID RasterizerStorageGLES3::texture_create() {
-
- Texture *texture = memnew(Texture);
- ERR_FAIL_COND_V(!texture, RID());
- glGenTextures(1, &texture->tex_id);
- texture->active = false;
- texture->total_data_size = 0;
-
- return texture_owner.make_rid(texture);
-}
-
-void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VisualServer::TextureType p_type, uint32_t p_flags) {
-
- GLenum format;
- GLenum internal_format;
- GLenum type;
-
- bool compressed;
- bool srgb;
-
- if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
- p_flags &= ~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video
- }
-
-#ifndef GLES_OVER_GL
- switch (p_format) {
- case Image::FORMAT_RF:
- case Image::FORMAT_RGF:
- case Image::FORMAT_RGBF:
- case Image::FORMAT_RGBAF:
- case Image::FORMAT_RH:
- case Image::FORMAT_RGH:
- case Image::FORMAT_RGBH:
- case Image::FORMAT_RGBAH: {
- if (!config.texture_float_linear_supported) {
- // disable linear texture filtering when not supported for float format on some devices (issue #24295)
- p_flags &= ~VS::TEXTURE_FLAG_FILTER;
- }
- } break;
- default: {
- }
- }
-#endif
-
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!texture);
- texture->width = p_width;
- texture->height = p_height;
- texture->depth = p_depth_3d;
- texture->format = p_format;
- texture->flags = p_flags;
- texture->stored_cube_sides = 0;
-
- texture->type = p_type;
-
- switch (p_type) {
- case VS::TEXTURE_TYPE_2D: {
- texture->target = GL_TEXTURE_2D;
- texture->images.resize(1);
- } break;
- case VS::TEXTURE_TYPE_CUBEMAP: {
- texture->target = GL_TEXTURE_CUBE_MAP;
- texture->images.resize(6);
- } break;
- case VS::TEXTURE_TYPE_2D_ARRAY: {
- texture->target = GL_TEXTURE_2D_ARRAY;
- texture->images.resize(p_depth_3d);
- } break;
- case VS::TEXTURE_TYPE_3D: {
- texture->target = GL_TEXTURE_3D;
- texture->images.resize(p_depth_3d);
- } break;
- }
-
- texture->is_npot_repeat_mipmap = false;
-#ifdef JAVASCRIPT_ENABLED
- // WebGL 2.0 on browsers does not seem to properly support compressed non power-of-two (NPOT)
- // textures with repeat/mipmaps, even though NPOT textures should be supported as per the spec.
- // Force decompressing them to work it around on WebGL 2.0 at a performance cost (GH-33058).
- int po2_width = next_power_of_2(p_width);
- int po2_height = next_power_of_2(p_height);
- bool is_po2 = p_width == po2_width && p_height == po2_height;
-
- if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) {
- texture->is_npot_repeat_mipmap = true;
- }
-#endif // JAVASCRIPT_ENABLED
-
- Image::Format real_format;
- _get_gl_image_and_format(Ref(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap);
-
- texture->alloc_width = texture->width;
- texture->alloc_height = texture->height;
- texture->alloc_depth = texture->depth;
-
- texture->gl_format_cache = format;
- texture->gl_type_cache = type;
- texture->gl_internal_format_cache = internal_format;
- texture->compressed = compressed;
- texture->srgb = srgb;
- texture->data_size = 0;
- texture->mipmaps = 1;
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- if (p_type == VS::TEXTURE_TYPE_3D || p_type == VS::TEXTURE_TYPE_2D_ARRAY) {
-
- int width = p_width;
- int height = p_height;
- int depth = p_depth_3d;
-
- int mipmaps = 0;
-
- while (width > 0 || height > 0 || (p_type == VS::TEXTURE_TYPE_3D && depth > 0)) {
- width = MAX(1, width);
- height = MAX(1, height);
- depth = MAX(1, depth);
-
- glTexImage3D(texture->target, mipmaps, internal_format, width, height, depth, 0, format, type, NULL);
-
- width /= 2;
- height /= 2;
-
- if (p_type == VS::TEXTURE_TYPE_3D) {
- depth /= 2;
- }
-
- mipmaps++;
-
- if (!(p_flags & VS::TEXTURE_FLAG_MIPMAPS))
- break;
- }
-
- glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
-
- } else if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
- //prealloc if video
- glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, type, NULL);
- }
-
- texture->active = true;
-}
-
-void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref &p_image, int p_layer) {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND(!texture);
- ERR_FAIL_COND(!texture->active);
- ERR_FAIL_COND(texture->render_target);
- ERR_FAIL_COND(texture->format != p_image->get_format());
- ERR_FAIL_COND(p_image.is_null());
-
- GLenum type;
- GLenum format;
- GLenum internal_format;
- bool compressed;
- bool srgb;
-
- if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) {
- texture->images.write[p_layer] = p_image;
- }
-
- Image::Format real_format;
- Ref img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap);
-
- if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) {
-
- texture->alloc_height = MAX(1, texture->alloc_height / 2);
- texture->alloc_width = MAX(1, texture->alloc_width / 2);
-
- if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) {
-
- img->shrink_x2();
- } else if (img->get_format() <= Image::FORMAT_RGBA8) {
-
- img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR);
- }
- };
-
- GLenum blit_target = GL_TEXTURE_2D;
-
- switch (texture->type) {
- case VS::TEXTURE_TYPE_2D: {
- blit_target = GL_TEXTURE_2D;
- } break;
- case VS::TEXTURE_TYPE_CUBEMAP: {
- ERR_FAIL_INDEX(p_layer, 6);
- blit_target = _cube_side_enum[p_layer];
- } break;
- case VS::TEXTURE_TYPE_2D_ARRAY: {
- blit_target = GL_TEXTURE_2D_ARRAY;
- } break;
- case VS::TEXTURE_TYPE_3D: {
- blit_target = GL_TEXTURE_3D;
- } break;
- }
-
- texture->data_size = img->get_data().size();
- PoolVector::Read read = img->get_data().read();
- ERR_FAIL_COND(!read.ptr());
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- texture->ignore_mipmaps = compressed && !img->has_mipmaps();
-
- if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps)
- glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR);
- else {
- if (texture->flags & VS::TEXTURE_FLAG_FILTER) {
- glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- } else {
- glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- }
-
- if (config.srgb_decode_supported && srgb) {
-
- if (texture->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
-
- glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT);
- texture->using_srgb = true;
- } else {
- glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT);
- texture->using_srgb = false;
- }
- }
-
- if (texture->flags & VS::TEXTURE_FLAG_FILTER) {
-
- glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering
-
- } else {
-
- glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering
- }
-
- if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) {
-
- if (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
- } else {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- } else {
-
- //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
- glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
-
-//set swizle for older format compatibility
-#ifdef GLES_OVER_GL
- switch (texture->format) {
-
- case Image::FORMAT_L8: {
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE);
-
- } break;
- case Image::FORMAT_LA8: {
-
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN);
- } break;
- default: {
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
-
- } break;
- }
-#endif
- if (config.use_anisotropic_filter) {
-
- if (texture->flags & VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) {
-
- glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, config.anisotropic_level);
- } else {
- glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
- }
- }
-
- int mipmaps = ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1;
-
- int w = img->get_width();
- int h = img->get_height();
-
- int tsize = 0;
-
- for (int i = 0; i < mipmaps; i++) {
-
- int size, ofs;
- img->get_mipmap_offset_and_size(i, ofs, size);
-
- if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
-
- if (texture->compressed) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-
- int bw = w;
- int bh = h;
-
- glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
-
- } else {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
- glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]);
- } else {
- glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
- }
- }
- } else {
- if (texture->compressed) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-
- int bw = w;
- int bh = h;
-
- glCompressedTexSubImage3D(blit_target, i, 0, 0, p_layer, bw, bh, 1, internal_format, size, &read[ofs]);
- } else {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- glTexSubImage3D(blit_target, i, 0, 0, p_layer, w, h, 1, format, type, &read[ofs]);
- }
- }
- tsize += size;
-
- w = MAX(1, w >> 1);
- h = MAX(1, h >> 1);
- }
-
- // Handle array and 3D textures, as those set their data per layer.
- tsize *= MAX(texture->alloc_depth, 1);
-
- info.texture_mem -= texture->total_data_size;
- texture->total_data_size = tsize;
- info.texture_mem += texture->total_data_size;
-
- //printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem);
-
- texture->stored_cube_sides |= (1 << p_layer);
-
- if ((texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) && (texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != VS::TEXTURE_TYPE_CUBEMAP || texture->stored_cube_sides == (1 << 6) - 1)) {
- //generate mipmaps if they were requested and the image does not contain them
- glGenerateMipmap(texture->target);
- } else if (mipmaps > 1) {
- glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
- } else {
- glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, 0);
- }
-
- texture->mipmaps = mipmaps;
-
- //texture_set_flags(p_texture,texture->flags);
-}
-
-// Uploads pixel data to a sub-region of a texture, for the specified mipmap.
-// The texture pixels must have been allocated before, because most features seen in texture_set_data() make no sense in a partial update.
-// TODO If we want this to be usable without pre-filling pixels with a full image, we have to call glTexImage2D() with null data.
-void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND(!texture);
- ERR_FAIL_COND(!texture->active);
- ERR_FAIL_COND(texture->render_target);
- ERR_FAIL_COND(texture->format != p_image->get_format());
- ERR_FAIL_COND(p_image.is_null());
- ERR_FAIL_COND(src_w <= 0 || src_h <= 0);
- ERR_FAIL_COND(src_x < 0 || src_y < 0 || src_x + src_w > p_image->get_width() || src_y + src_h > p_image->get_height());
- ERR_FAIL_COND(dst_x < 0 || dst_y < 0 || dst_x + src_w > texture->alloc_width || dst_y + src_h > texture->alloc_height);
- ERR_FAIL_COND(p_dst_mip < 0 || p_dst_mip >= texture->mipmaps);
-
- GLenum type;
- GLenum format;
- GLenum internal_format;
- bool compressed;
- bool srgb;
-
- // Because OpenGL wants data as a dense array, we have to extract the sub-image if the source rect isn't the full image
- Ref p_sub_img = p_image;
- if (src_x > 0 || src_y > 0 || src_w != p_image->get_width() || src_h != p_image->get_height()) {
- p_sub_img = p_image->get_rect(Rect2(src_x, src_y, src_w, src_h));
- }
-
- Image::Format real_format;
- Ref img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap);
-
- GLenum blit_target = GL_TEXTURE_2D;
-
- switch (texture->type) {
- case VS::TEXTURE_TYPE_2D: {
- blit_target = GL_TEXTURE_2D;
- } break;
- case VS::TEXTURE_TYPE_CUBEMAP: {
- ERR_FAIL_INDEX(p_layer, 6);
- blit_target = _cube_side_enum[p_layer];
- } break;
- case VS::TEXTURE_TYPE_2D_ARRAY: {
- blit_target = GL_TEXTURE_2D_ARRAY;
- } break;
- case VS::TEXTURE_TYPE_3D: {
- blit_target = GL_TEXTURE_3D;
- } break;
- }
-
- PoolVector::Read read = img->get_data().read();
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- int src_data_size = img->get_data().size();
- int src_ofs = 0;
-
- if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
- if (texture->compressed) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glCompressedTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, internal_format, src_data_size, &read[src_ofs]);
-
- } else {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- // `format` has to match the internal_format used when the texture was created
- glTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, format, type, &read[src_ofs]);
- }
- } else {
- if (texture->compressed) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glCompressedTexSubImage3D(blit_target, p_dst_mip, dst_x, dst_y, p_layer, src_w, src_h, 1, format, src_data_size, &read[src_ofs]);
- } else {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- // `format` has to match the internal_format used when the texture was created
- glTexSubImage3D(blit_target, p_dst_mip, dst_x, dst_y, p_layer, src_w, src_h, 1, format, type, &read[src_ofs]);
- }
- }
-
- if (texture->flags & VS::TEXTURE_FLAG_FILTER) {
-
- glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering
-
- } else {
-
- glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering
- }
-}
-
-Ref RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) const {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND_V(!texture, Ref());
- ERR_FAIL_COND_V(!texture->active, Ref());
- ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref());
-
- if (texture->type == VS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && !texture->images[p_layer].is_null()) {
- return texture->images[p_layer];
- }
-
- // 3D textures and 2D texture arrays need special treatment, as the glGetTexImage reads **the whole**
- // texture to host-memory. 3D textures and 2D texture arrays are potentially very big, so reading
- // everything just to throw everything but one layer away is A Bad Idea.
- //
- // Unfortunately, to solve this, the copy shader has to read the data out via a shader and store it
- // in a temporary framebuffer. The data from the framebuffer can then be read using glReadPixels.
- if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY || texture->type == VS::TEXTURE_TYPE_3D) {
- // can't read a layer that doesn't exist
- ERR_FAIL_INDEX_V(p_layer, texture->alloc_depth, Ref());
-
- // get some information about the texture
- Image::Format real_format;
- GLenum gl_format;
- GLenum gl_internal_format;
- GLenum gl_type;
-
- bool compressed;
- bool srgb;
-
- _get_gl_image_and_format(
- Ref(),
- texture->format,
- texture->flags,
- real_format,
- gl_format,
- gl_internal_format,
- gl_type,
- compressed,
- srgb,
- texture->is_npot_repeat_mipmap);
-
- PoolVector data;
-
- // TODO need to decide between RgbaUnorm and RgbaFloat32 for output
- int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
-
- data.resize(data_size * 2); // add some more memory at the end, just in case for buggy drivers
- PoolVector::Write wb = data.write();
-
- // generate temporary resources
- GLuint tmp_fbo;
- glGenFramebuffers(1, &tmp_fbo);
-
- GLuint tmp_color_attachment;
- glGenTextures(1, &tmp_color_attachment);
-
- // now bring the OpenGL context into the correct state
- {
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fbo);
-
- // back color attachment with memory, then set properties
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, tmp_color_attachment);
- // TODO support HDR properly
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- // use the color texture as color attachment for this render pass
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_color_attachment, 0);
-
- // more GL state, wheeeey
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthFunc(GL_LEQUAL);
- glColorMask(1, 1, 1, 1);
-
- // use volume tex for reading
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- glViewport(0, 0, texture->alloc_width, texture->alloc_height);
-
- // set up copy shader for proper use
- shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb);
- shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, texture->type == VS::TEXTURE_TYPE_3D);
- shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, texture->type == VS::TEXTURE_TYPE_2D_ARRAY);
- shaders.copy.bind();
-
- float layer;
- if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY)
- layer = (float)p_layer;
- else
- // calculate the normalized z coordinate for the layer
- layer = (float)p_layer / (float)texture->alloc_depth;
-
- shaders.copy.set_uniform(CopyShaderGLES3::LAYER, layer);
-
- glBindVertexArray(resources.quadie_array);
- }
-
- // clear color attachment, then perform copy
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- // read the image into the host buffer
- glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]);
-
- // remove temp resources and unset some GL state
- {
- shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, false);
- shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, false);
- shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false);
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- glDeleteTextures(1, &tmp_color_attachment);
- glDeleteFramebuffers(1, &tmp_fbo);
- }
-
- wb.release();
-
- data.resize(data_size);
-
- Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data));
- if (!texture->compressed) {
- img->convert(real_format);
- }
-
- return Ref(img);
- }
-
-#ifdef GLES_OVER_GL
-
- Image::Format real_format;
- GLenum gl_format;
- GLenum gl_internal_format;
- GLenum gl_type;
- bool compressed;
- bool srgb;
- _get_gl_image_and_format(Ref(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb, false);
-
- PoolVector data;
-
- int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1);
-
- data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
- PoolVector::Write wb = data.write();
-
- glActiveTexture(GL_TEXTURE0);
-
- glBindTexture(texture->target, texture->tex_id);
-
- 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, real_format, i);
-
- if (texture->compressed) {
-
- glPixelStorei(GL_PACK_ALIGNMENT, 4);
- glGetCompressedTexImage(texture->target, i, &wb[ofs]);
-
- } else {
-
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
- glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]);
- }
- }
-
- Image::Format img_format;
-
- //convert special case RGB10_A2 to RGBA8 because it's not a supported image format
- if (texture->gl_internal_format_cache == GL_RGB10_A2) {
-
- img_format = Image::FORMAT_RGBA8;
-
- uint32_t *ptr = (uint32_t *)wb.ptr();
- uint32_t num_pixels = data_size / 4;
-
- for (uint32_t ofs = 0; ofs < num_pixels; ofs++) {
- uint32_t px = ptr[ofs];
- uint32_t a = px >> 30 & 0xFF;
-
- ptr[ofs] = (px >> 2 & 0xFF) |
- (px >> 12 & 0xFF) << 8 |
- (px >> 22 & 0xFF) << 16 |
- (a | a << 2 | a << 4 | a << 6) << 24;
- }
- } else {
- img_format = real_format;
- }
-
- wb.release();
-
- data.resize(data_size);
-
- Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, img_format, data));
-
- return Ref(img);
-#else
-
- Image::Format real_format;
- GLenum gl_format;
- GLenum gl_internal_format;
- GLenum gl_type;
- bool compressed;
- bool srgb;
- _get_gl_image_and_format(Ref(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb, texture->is_npot_repeat_mipmap);
-
- PoolVector data;
-
- int 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
- PoolVector::Write wb = data.write();
-
- GLuint temp_framebuffer;
- glGenFramebuffers(1, &temp_framebuffer);
-
- GLuint temp_color_texture;
- glGenTextures(1, &temp_color_texture);
-
- glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer);
-
- glBindTexture(GL_TEXTURE_2D, temp_color_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0);
-
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthFunc(GL_LEQUAL);
- glColorMask(1, 1, 1, 1);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture->tex_id);
-
- glViewport(0, 0, texture->alloc_width, texture->alloc_height);
-
- shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb);
- shaders.copy.bind();
-
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- glBindVertexArray(resources.quadie_array);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindVertexArray(0);
-
- glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]);
-
- shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false);
-
- glDeleteTextures(1, &temp_color_texture);
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glDeleteFramebuffers(1, &temp_framebuffer);
-
- wb.release();
-
- data.resize(data_size);
-
- Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data));
- if (!texture->compressed) {
- img->convert(real_format);
- }
-
- return Ref(img);
-#endif
-}
-
-void RasterizerStorageGLES3::texture_set_flags(RID p_texture, uint32_t p_flags) {
-
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!texture);
- if (texture->render_target) {
-
- p_flags &= VS::TEXTURE_FLAG_FILTER; //can change only filter
- }
-
- bool had_mipmaps = texture->flags & VS::TEXTURE_FLAG_MIPMAPS;
-
- texture->flags = p_flags;
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) {
-
- if (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
- } else {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- } else {
- //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
- glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
-
- if (config.use_anisotropic_filter) {
-
- if (texture->flags & VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) {
-
- glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, config.anisotropic_level);
- } else {
- glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
- }
- }
-
- if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) {
- if (!had_mipmaps && texture->mipmaps == 1) {
- glGenerateMipmap(texture->target);
- }
- glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR);
-
- } else {
- if (texture->flags & VS::TEXTURE_FLAG_FILTER) {
- glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- } else {
- glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- }
-
- if (config.srgb_decode_supported && texture->srgb) {
-
- if (texture->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
-
- glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT);
- texture->using_srgb = true;
- } else {
- glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _SKIP_DECODE_EXT);
- texture->using_srgb = false;
- }
- }
-
- if (texture->flags & VS::TEXTURE_FLAG_FILTER) {
-
- glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering
-
- } else {
-
- glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering
- }
-}
-uint32_t RasterizerStorageGLES3::texture_get_flags(RID p_texture) const {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->flags;
-}
-Image::Format RasterizerStorageGLES3::texture_get_format(RID p_texture) const {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND_V(!texture, Image::FORMAT_L8);
-
- return texture->format;
-}
-
-VisualServer::TextureType RasterizerStorageGLES3::texture_get_type(RID p_texture) const {
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND_V(!texture, VS::TEXTURE_TYPE_2D);
-
- return texture->type;
-}
-uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->tex_id;
-}
-void RasterizerStorageGLES3::texture_bind(RID p_texture, uint32_t p_texture_no) {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND(!texture);
-
- glActiveTexture(GL_TEXTURE0 + p_texture_no);
- glBindTexture(texture->target, texture->tex_id);
-}
-uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->width;
-}
-uint32_t RasterizerStorageGLES3::texture_get_height(RID p_texture) const {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->height;
-}
-
-uint32_t RasterizerStorageGLES3::texture_get_depth(RID p_texture) const {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->depth;
-}
-
-void RasterizerStorageGLES3::texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth) {
-
- Texture *texture = texture_owner.getornull(p_texture);
-
- ERR_FAIL_COND(!texture);
- ERR_FAIL_COND(texture->render_target);
-
- ERR_FAIL_COND(p_width <= 0 || p_width > 16384);
- ERR_FAIL_COND(p_height <= 0 || p_height > 16384);
- //real texture size is in alloc width and height
- texture->width = p_width;
- texture->height = p_height;
-}
-
-void RasterizerStorageGLES3::texture_set_path(RID p_texture, const String &p_path) {
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->path = p_path;
-}
-
-String RasterizerStorageGLES3::texture_get_path(RID p_texture) const {
-
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND_V(!texture, String());
- return texture->path;
-}
-void RasterizerStorageGLES3::texture_debug_usage(List *r_info) {
-
- List textures;
- texture_owner.get_owned_list(&textures);
-
- for (List::Element *E = textures.front(); E; E = E->next()) {
-
- Texture *t = texture_owner.getornull(E->get());
- if (!t)
- continue;
- VS::TextureInfo tinfo;
- tinfo.path = t->path;
- tinfo.format = t->format;
- tinfo.width = t->alloc_width;
- tinfo.height = t->alloc_height;
- tinfo.depth = t->alloc_depth;
- tinfo.bytes = t->total_data_size;
- r_info->push_back(tinfo);
- }
-}
-
-void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable) {
-
- config.shrink_textures_x2 = p_enable;
-}
-
-void RasterizerStorageGLES3::textures_keep_original(bool p_enable) {
-
- config.keep_original_textures = p_enable;
-}
-
-void RasterizerStorageGLES3::texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) {
-
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->detect_3d = p_callback;
- texture->detect_3d_ud = p_userdata;
-}
-
-void RasterizerStorageGLES3::texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->detect_srgb = p_callback;
- texture->detect_srgb_ud = p_userdata;
-}
-
-void RasterizerStorageGLES3::texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->detect_normal = p_callback;
- texture->detect_normal_ud = p_userdata;
-}
-
-RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_resolution) const {
-
- Texture *texture = texture_owner.getornull(p_source);
- ERR_FAIL_COND_V(!texture, RID());
- ERR_FAIL_COND_V(texture->type != VS::TEXTURE_TYPE_CUBEMAP, RID());
-
- bool use_float = config.framebuffer_half_float_supported;
-
- if (p_resolution < 0) {
- p_resolution = texture->width;
- }
-
- glBindVertexArray(0);
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_BLEND);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) {
-
- glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT);
- texture->using_srgb = true;
-#ifdef TOOLS_ENABLED
- if (!(texture->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
- texture->flags |= VS::TEXTURE_FLAG_CONVERT_TO_LINEAR;
- //notify that texture must be set to linear beforehand, so it works in other platforms when exported
- }
-#endif
- }
-
- glActiveTexture(GL_TEXTURE1);
- GLuint new_cubemap;
- glGenTextures(1, &new_cubemap);
- glBindTexture(GL_TEXTURE_CUBE_MAP, new_cubemap);
-
- GLuint tmp_fb;
-
- glGenFramebuffers(1, &tmp_fb);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
-
- int size = p_resolution;
-
- int lod = 0;
-
- shaders.cubemap_filter.bind();
-
- int mipmaps = 6;
-
- int mm_level = mipmaps;
-
- GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2;
- GLenum format = GL_RGBA;
- GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV;
-
- while (mm_level) {
-
- for (int i = 0; i < 6; i++) {
- glTexImage2D(_cube_side_enum[i], lod, internal_format, size, size, 0, format, type, NULL);
- }
-
- lod++;
- mm_level--;
-
- if (size > 1)
- size >>= 1;
- }
-
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, lod - 1);
-
- lod = 0;
- mm_level = mipmaps;
-
- size = p_resolution;
-
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false);
-
- while (mm_level) {
-
- for (int i = 0; i < 6; i++) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], new_cubemap, lod);
-
- glViewport(0, 0, size, size);
- glBindVertexArray(resources.quadie_array);
-
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::FACE_ID, i);
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, lod / float(mipmaps - 1));
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindVertexArray(0);
-#ifdef DEBUG_ENABLED
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
-#endif
- }
-
- if (size > 1)
- size >>= 1;
- lod++;
- mm_level--;
- }
-
- //restore ranges
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, lod - 1);
-
- glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- glDeleteFramebuffers(1, &tmp_fb);
-
- Texture *ctex = memnew(Texture);
-
- ctex->type = VS::TEXTURE_TYPE_CUBEMAP;
- ctex->flags = VS::TEXTURE_FLAG_MIPMAPS | VS::TEXTURE_FLAG_FILTER;
- ctex->width = p_resolution;
- ctex->height = p_resolution;
- ctex->alloc_width = p_resolution;
- ctex->alloc_height = p_resolution;
- ctex->format = use_float ? Image::FORMAT_RGBAH : Image::FORMAT_RGBA8;
- ctex->target = GL_TEXTURE_CUBE_MAP;
- ctex->gl_format_cache = format;
- ctex->gl_internal_format_cache = internal_format;
- ctex->gl_type_cache = type;
- ctex->data_size = 0;
- ctex->compressed = false;
- ctex->srgb = false;
- ctex->total_data_size = 0;
- ctex->ignore_mipmaps = false;
- ctex->mipmaps = mipmaps;
- ctex->active = true;
- ctex->tex_id = new_cubemap;
- ctex->stored_cube_sides = (1 << 6) - 1;
- ctex->render_target = NULL;
-
- return texture_owner.make_rid(ctex);
-}
-
-Size2 RasterizerStorageGLES3::texture_size_with_proxy(RID p_texture) const {
-
- const Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND_V(!texture, Size2());
- if (texture->proxy) {
- return Size2(texture->proxy->width, texture->proxy->height);
- } else {
- return Size2(texture->width, texture->height);
- }
-}
-
-void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) {
-
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!texture);
-
- if (texture->proxy) {
- texture->proxy->proxy_owners.erase(texture);
- texture->proxy = NULL;
- }
-
- if (p_proxy.is_valid()) {
- Texture *proxy = texture_owner.getornull(p_proxy);
- ERR_FAIL_COND(!proxy);
- ERR_FAIL_COND(proxy == texture);
- proxy->proxy_owners.insert(texture);
- texture->proxy = proxy;
- }
-}
-
-void RasterizerStorageGLES3::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
-
- Texture *texture = texture_owner.getornull(p_texture);
- ERR_FAIL_COND(!texture);
- texture->redraw_if_visible = p_enable;
-}
-
-RID RasterizerStorageGLES3::sky_create() {
-
- Sky *sky = memnew(Sky);
- sky->radiance = 0;
- sky->irradiance = 0;
- return sky_owner.make_rid(sky);
-}
-
-void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size) {
-
- Sky *sky = sky_owner.getornull(p_sky);
- ERR_FAIL_COND(!sky);
-
- if (sky->panorama.is_valid()) {
- sky->panorama = RID();
- glDeleteTextures(1, &sky->radiance);
- glDeleteTextures(1, &sky->irradiance);
- sky->radiance = 0;
- sky->irradiance = 0;
- }
-
- sky->panorama = p_panorama;
- if (!sky->panorama.is_valid()) {
- return; //cleared
- }
-
- Texture *texture = texture_owner.getornull(sky->panorama);
- if (!texture) {
- sky->panorama = RID();
- ERR_FAIL_COND(!texture);
- }
-
- texture = texture->get_ptr(); //resolve for proxies
-
- glBindVertexArray(0);
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_BLEND);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
- glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
-#ifdef GLES_OVER_GL
- glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, int(Math::floor(Math::log(float(texture->width)) / Math::log(2.0f))));
- glGenerateMipmap(texture->target);
-#else
- glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, 0);
-#endif
- // Need Mipmaps regardless of whether they are set in import by user
- glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_REPEAT);
-#ifdef GLES_OVER_GL
- glTexParameterf(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
-#else
- glTexParameterf(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-#endif
- glTexParameterf(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) {
-
- glTexParameteri(texture->target, _TEXTURE_SRGB_DECODE_EXT, _DECODE_EXT);
- texture->using_srgb = true;
-#ifdef TOOLS_ENABLED
- if (!(texture->flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) {
- texture->flags |= VS::TEXTURE_FLAG_CONVERT_TO_LINEAR;
- //notify that texture must be set to linear beforehand, so it works in other platforms when exported
- }
-#endif
- }
-
- {
- //Irradiance map
- glActiveTexture(GL_TEXTURE1);
- glGenTextures(1, &sky->irradiance);
- glBindTexture(GL_TEXTURE_2D, sky->irradiance);
-
- GLuint tmp_fb;
-
- glGenFramebuffers(1, &tmp_fb);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
-
- int size = 32;
-
- bool use_float = config.framebuffer_half_float_supported;
-
- GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2;
- GLenum format = GL_RGBA;
- GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV;
-
- glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
- glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->irradiance, 0);
-
- int irradiance_size = GLOBAL_GET("rendering/quality/reflections/irradiance_max_size");
- int upscale_size = MIN(int(previous_power_of_2(irradiance_size)), p_radiance_size);
-
- GLuint tmp_fb2;
- GLuint tmp_tex;
- {
- //generate another one for rendering, as can't read and write from a single texarray it seems
- glGenFramebuffers(1, &tmp_fb2);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
- glGenTextures(1, &tmp_tex);
- glBindTexture(GL_TEXTURE_2D, tmp_tex);
- glTexImage2D(GL_TEXTURE_2D, 0, internal_format, upscale_size, 2.0 * upscale_size, 0, format, type, NULL);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-#ifdef DEBUG_ENABLED
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
-#endif
- }
-
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::COMPUTE_IRRADIANCE, true);
- shaders.cubemap_filter.bind();
-
- // Very large Panoramas require way too much effort to compute irradiance so use a mipmap
- // level that corresponds to a panorama of 1024x512
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, MAX(Math::floor(Math::log(float(texture->width)) / Math::log(2.0f)) - 10.0f, 0.0f));
-
- // Compute Irradiance for a large texture, specified by radiance size and then pull out a low mipmap corresponding to 32x32
- for (int i = 0; i < 2; i++) {
- glViewport(0, i * upscale_size, upscale_size, upscale_size);
- glBindVertexArray(resources.quadie_array);
-
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindVertexArray(0);
- }
- glGenerateMipmap(GL_TEXTURE_2D);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, tmp_tex);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
-
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::COMPUTE_IRRADIANCE, false);
-
- shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, true);
- shaders.copy.bind();
- shaders.copy.set_uniform(CopyShaderGLES3::MIP_LEVEL, MAX(Math::floor(Math::log(float(upscale_size)) / Math::log(2.0f)) - 5.0f, 0.0f)); // Mip level that corresponds to a 32x32 texture
-
- glViewport(0, 0, size, size * 2.0);
- glBindVertexArray(resources.quadie_array);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindVertexArray(0);
-
- shaders.copy.set_conditional(CopyShaderGLES3::USE_LOD, false);
-
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
- glDeleteFramebuffers(1, &tmp_fb);
- glDeleteFramebuffers(1, &tmp_fb2);
- glDeleteTextures(1, &tmp_tex);
- }
-
- // Now compute radiance
-
- glActiveTexture(GL_TEXTURE1);
- glGenTextures(1, &sky->radiance);
-
- if (config.use_texture_array_environment) {
-
- //texture3D
- glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance);
-
- GLuint tmp_fb;
-
- glGenFramebuffers(1, &tmp_fb);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
-
- int size = p_radiance_size;
-
- int array_level = 6;
-
- bool use_float = config.framebuffer_half_float_supported;
-
- GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2;
- GLenum format = GL_RGBA;
- GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV;
-
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internal_format, size, size * 2, array_level, 0, format, type, NULL);
-
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- GLuint tmp_fb2;
- GLuint tmp_tex;
- {
- //generate another one for rendering, as can't read and write from a single texarray it seems
- glGenFramebuffers(1, &tmp_fb2);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
- glGenTextures(1, &tmp_tex);
- glBindTexture(GL_TEXTURE_2D, tmp_tex);
- glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-#ifdef DEBUG_ENABLED
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
-#endif
- }
-
- for (int j = 0; j < array_level; j++) {
-
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
-
-#ifdef GLES_OVER_GL
- if (j < 3) {
-#else
- if (j == 0) {
-#endif
-
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, false);
- shaders.cubemap_filter.bind();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(texture->width / 4));
- } else {
-
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, true);
- shaders.cubemap_filter.bind();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance);
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_ARRAY_INDEX, j - 1); //read from previous to ensure better blur
- }
-
- for (int i = 0; i < 2; i++) {
- glViewport(0, i * size, size, size);
- glBindVertexArray(resources.quadie_array);
-
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0);
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, j / float(array_level - 1));
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindVertexArray(0);
- }
-
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tmp_fb);
- glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, sky->radiance, 0, j);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, tmp_fb2);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glBlitFramebuffer(0, 0, size, size * 2, 0, 0, size, size * 2, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- }
-
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID_ARRAY, false);
-
- //restore ranges
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D_ARRAY, sky->radiance);
-
- glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
-
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- glDeleteFramebuffers(1, &tmp_fb);
- glDeleteFramebuffers(1, &tmp_fb2);
- glDeleteTextures(1, &tmp_tex);
-
- } else {
- //regular single texture with mipmaps
- glBindTexture(GL_TEXTURE_2D, sky->radiance);
-
- GLuint tmp_fb;
-
- glGenFramebuffers(1, &tmp_fb);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
-
- int size = p_radiance_size;
-
- int lod = 0;
-
- int mipmaps = 6;
-
- int mm_level = mipmaps;
-
- bool use_float = config.framebuffer_half_float_supported;
-
- GLenum internal_format = use_float ? GL_RGBA16F : GL_RGB10_A2;
- GLenum format = GL_RGBA;
- GLenum type = use_float ? GL_HALF_FLOAT : GL_UNSIGNED_INT_2_10_10_10_REV;
-
- glTexStorage2DCustom(GL_TEXTURE_2D, mipmaps, internal_format, size, size * 2.0, format, type);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- GLuint tmp_fb2;
- GLuint tmp_tex;
- {
- // Need a temporary framebuffer for rendering so we can read from previous iterations
- glGenFramebuffers(1, &tmp_fb2);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
- glGenTextures(1, &tmp_tex);
- glBindTexture(GL_TEXTURE_2D, tmp_tex);
- glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-#ifdef DEBUG_ENABLED
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
-#endif
- }
-
- lod = 0;
- mm_level = mipmaps;
-
- size = p_radiance_size;
-
- while (mm_level) {
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->radiance, lod);
-
-#ifdef DEBUG_ENABLED
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
-#endif
- glBindTexture(GL_TEXTURE_2D, tmp_tex);
- glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size * 2, 0, format, type, NULL);
- glBindFramebuffer(GL_FRAMEBUFFER, tmp_fb2);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_tex, 0);
-#ifdef GLES_OVER_GL
- if (lod < 3) {
-#else
- if (lod == 0) {
-#endif
-
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID, false);
- shaders.cubemap_filter.bind();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_RESOLUTION, float(texture->width / 4));
- } else {
-
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_DUAL_PARABOLOID, true);
- shaders.cubemap_filter.bind();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, sky->radiance);
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::SOURCE_MIP_LEVEL, float(lod - 1)); //read from previous to ensure better blur
- }
-
- for (int i = 0; i < 2; i++) {
- glViewport(0, i * size, size, size);
- glBindVertexArray(resources.quadie_array);
-
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::Z_FLIP, i > 0);
- shaders.cubemap_filter.set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, lod / float(mipmaps - 1));
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindVertexArray(0);
- }
-
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tmp_fb);
- glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, sky->radiance, 0, lod);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, tmp_fb2);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glBlitFramebuffer(0, 0, size, size * 2, 0, 0, size, size * 2, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-
- if (size > 1)
- size >>= 1;
- lod++;
- mm_level--;
- }
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false);
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_SOURCE_PANORAMA, false);
-
- //restore ranges
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, lod - 1);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- glDeleteFramebuffers(1, &tmp_fb);
- glDeleteFramebuffers(1, &tmp_fb2);
- glDeleteTextures(1, &tmp_tex);
- }
-}
-
-/* SHADER API */
-
-RID RasterizerStorageGLES3::shader_create() {
-
- Shader *shader = memnew(Shader);
- shader->mode = VS::SHADER_SPATIAL;
- shader->shader = &scene->state.scene_shader;
- RID rid = shader_owner.make_rid(shader);
- _shader_make_dirty(shader);
- shader->self = rid;
-
- return rid;
-}
-
-void RasterizerStorageGLES3::_shader_make_dirty(Shader *p_shader) {
-
- if (p_shader->dirty_list.in_list())
- return;
-
- _shader_dirty_list.add(&p_shader->dirty_list);
-}
-
-void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String &p_code) {
-
- Shader *shader = shader_owner.getornull(p_shader);
- ERR_FAIL_COND(!shader);
-
- shader->code = p_code;
-
- String mode_string = ShaderLanguage::get_shader_type(p_code);
- VS::ShaderMode mode;
-
- if (mode_string == "canvas_item")
- mode = VS::SHADER_CANVAS_ITEM;
- else if (mode_string == "particles")
- mode = VS::SHADER_PARTICLES;
- else
- mode = VS::SHADER_SPATIAL;
-
- if (shader->custom_code_id && mode != shader->mode) {
-
- shader->shader->free_custom_shader(shader->custom_code_id);
- shader->custom_code_id = 0;
- }
-
- shader->mode = mode;
-
- ShaderGLES3 *shaders[VS::SHADER_MAX] = {
- &scene->state.scene_shader,
- &canvas->state.canvas_shader,
- &this->shaders.particles,
-
- };
-
- shader->shader = shaders[mode];
-
- if (shader->custom_code_id == 0) {
- shader->custom_code_id = shader->shader->create_custom_shader();
- }
-
- _shader_make_dirty(shader);
-}
-String RasterizerStorageGLES3::shader_get_code(RID p_shader) const {
-
- const Shader *shader = shader_owner.getornull(p_shader);
- ERR_FAIL_COND_V(!shader, String());
-
- return shader->code;
-}
-
-void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
-
- _shader_dirty_list.remove(&p_shader->dirty_list);
-
- p_shader->valid = false;
- p_shader->ubo_size = 0;
-
- p_shader->uniforms.clear();
-
- if (p_shader->code == String()) {
- return; //just invalid, but no error
- }
-
- ShaderCompilerGLES3::GeneratedCode gen_code;
- ShaderCompilerGLES3::IdentifierActions *actions = NULL;
-
- switch (p_shader->mode) {
- case VS::SHADER_CANVAS_ITEM: {
-
- p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL;
- p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX;
- p_shader->canvas_item.uses_screen_texture = false;
- p_shader->canvas_item.uses_screen_uv = false;
- p_shader->canvas_item.uses_time = false;
-
- shaders.actions_canvas.render_mode_values["blend_add"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
- shaders.actions_canvas.render_mode_values["blend_mix"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
- shaders.actions_canvas.render_mode_values["blend_sub"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
- shaders.actions_canvas.render_mode_values["blend_mul"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
- shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
- shaders.actions_canvas.render_mode_values["blend_disabled"] = Pair(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_DISABLED);
-
- shaders.actions_canvas.render_mode_values["unshaded"] = Pair(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
- shaders.actions_canvas.render_mode_values["light_only"] = Pair(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
-
- shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
- shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
- shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture;
- shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time;
-
- actions = &shaders.actions_canvas;
- actions->uniforms = &p_shader->uniforms;
-
- } break;
-
- case VS::SHADER_SPATIAL: {
-
- p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX;
- p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE;
- p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK;
- p_shader->spatial.uses_alpha = false;
- p_shader->spatial.uses_alpha_scissor = false;
- p_shader->spatial.uses_discard = false;
- p_shader->spatial.unshaded = false;
- p_shader->spatial.no_depth_test = false;
- p_shader->spatial.uses_sss = false;
- p_shader->spatial.uses_time = false;
- p_shader->spatial.uses_vertex_lighting = false;
- p_shader->spatial.uses_screen_texture = false;
- p_shader->spatial.uses_depth_texture = false;
- p_shader->spatial.uses_vertex = false;
- p_shader->spatial.writes_modelview_or_projection = false;
- p_shader->spatial.uses_world_coordinates = false;
-
- shaders.actions_scene.render_mode_values["blend_add"] = Pair(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD);
- shaders.actions_scene.render_mode_values["blend_mix"] = Pair(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX);
- shaders.actions_scene.render_mode_values["blend_sub"] = Pair(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_SUB);
- shaders.actions_scene.render_mode_values["blend_mul"] = Pair(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MUL);
-
- shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_OPAQUE);
- shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALWAYS);
- shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_NEVER);
- shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS);
-
- shaders.actions_scene.render_mode_values["cull_front"] = Pair(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_FRONT);
- shaders.actions_scene.render_mode_values["cull_back"] = Pair(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_BACK);
- shaders.actions_scene.render_mode_values["cull_disabled"] = Pair(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_DISABLED);
-
- shaders.actions_scene.render_mode_flags["unshaded"] = &p_shader->spatial.unshaded;
- shaders.actions_scene.render_mode_flags["depth_test_disable"] = &p_shader->spatial.no_depth_test;
-
- shaders.actions_scene.render_mode_flags["vertex_lighting"] = &p_shader->spatial.uses_vertex_lighting;
-
- shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates;
-
- shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha;
- shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor;
-
- shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss;
- shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard;
- shaders.actions_scene.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->spatial.uses_screen_texture;
- shaders.actions_scene.usage_flag_pointers["DEPTH_TEXTURE"] = &p_shader->spatial.uses_depth_texture;
- shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;
-
- shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
- shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
- shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex;
-
- actions = &shaders.actions_scene;
- actions->uniforms = &p_shader->uniforms;
-
- } break;
- case VS::SHADER_PARTICLES: {
-
- actions = &shaders.actions_particles;
- actions->uniforms = &p_shader->uniforms;
- } break;
- case VS::SHADER_MAX:
- break; // Can't happen, but silences warning
- }
-
- Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code);
- if (err != OK) {
- return;
- }
-
- p_shader->shader->set_custom_shader_code(p_shader->custom_code_id, gen_code.vertex, gen_code.vertex_global, gen_code.fragment, gen_code.light, gen_code.fragment_global, gen_code.uniforms, gen_code.texture_uniforms, gen_code.defines);
-
- p_shader->ubo_size = gen_code.uniform_total_size;
- p_shader->ubo_offsets = gen_code.uniform_offsets;
- p_shader->texture_count = gen_code.texture_uniforms.size();
- p_shader->texture_hints = gen_code.texture_hints;
- p_shader->texture_types = gen_code.texture_types;
-
- p_shader->uses_vertex_time = gen_code.uses_vertex_time;
- p_shader->uses_fragment_time = gen_code.uses_fragment_time;
-
- //all materials using this shader will have to be invalidated, unfortunately
-
- for (SelfList *E = p_shader->materials.first(); E; E = E->next()) {
-
- _material_make_dirty(E->self());
- }
-
- p_shader->valid = true;
- p_shader->version++;
-}
-
-void RasterizerStorageGLES3::update_dirty_shaders() {
-
- while (_shader_dirty_list.first()) {
- _update_shader(_shader_dirty_list.first()->self());
- }
-}
-
-void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List *p_param_list) const {
-
- Shader *shader = shader_owner.getornull(p_shader);
- ERR_FAIL_COND(!shader);
-
- if (shader->dirty_list.in_list())
- _update_shader(shader); // ok should be not anymore dirty
-
- Map order;
-
- for (Map::Element *E = shader->uniforms.front(); E; E = E->next()) {
-
- if (E->get().texture_order >= 0) {
- order[E->get().texture_order + 100000] = E->key();
- } else {
- order[E->get().order] = E->key();
- }
- }
-
- for (Map::Element *E = order.front(); E; E = E->next()) {
-
- PropertyInfo pi;
- ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[E->get()];
- pi.name = E->get();
- switch (u.type) {
- case ShaderLanguage::TYPE_VOID: pi.type = Variant::NIL; break;
- case ShaderLanguage::TYPE_BOOL: pi.type = Variant::BOOL; break;
- case ShaderLanguage::TYPE_BVEC2:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y";
- break;
- case ShaderLanguage::TYPE_BVEC3:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y,z";
- break;
- case ShaderLanguage::TYPE_BVEC4:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y,z,w";
- break;
- case ShaderLanguage::TYPE_UINT:
- case ShaderLanguage::TYPE_INT: {
- pi.type = Variant::INT;
- if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
- pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_IVEC4:
- case ShaderLanguage::TYPE_UVEC2:
- case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_UVEC4: {
-
- pi.type = Variant::POOL_INT_ARRAY;
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
- pi.type = Variant::REAL;
- if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
- pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC2: pi.type = Variant::VECTOR2; break;
- case ShaderLanguage::TYPE_VEC3: pi.type = Variant::VECTOR3; break;
- case ShaderLanguage::TYPE_VEC4: {
- if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- pi.type = Variant::COLOR;
- } else {
- pi.type = Variant::PLANE;
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: pi.type = Variant::TRANSFORM2D; break;
- case ShaderLanguage::TYPE_MAT3: pi.type = Variant::BASIS; break;
- case ShaderLanguage::TYPE_MAT4: pi.type = Variant::TRANSFORM; break;
- case ShaderLanguage::TYPE_SAMPLER2D:
- case ShaderLanguage::TYPE_ISAMPLER2D:
- case ShaderLanguage::TYPE_USAMPLER2D: {
-
- pi.type = Variant::OBJECT;
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "Texture2D";
- } break;
- case ShaderLanguage::TYPE_SAMPLER2DARRAY:
- case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
- case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
-
- pi.type = Variant::OBJECT;
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "TextureArray";
- } break;
- case ShaderLanguage::TYPE_SAMPLER3D:
- case ShaderLanguage::TYPE_ISAMPLER3D:
- case ShaderLanguage::TYPE_USAMPLER3D: {
- pi.type = Variant::OBJECT;
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "Texture3D";
- } break;
- case ShaderLanguage::TYPE_SAMPLERCUBE: {
-
- pi.type = Variant::OBJECT;
- pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "CubeMap";
- } break;
- };
-
- p_param_list->push_back(pi);
- }
-}
-
-void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {
-
- Shader *shader = shader_owner.getornull(p_shader);
- ERR_FAIL_COND(!shader);
- ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture));
-
- if (p_texture.is_valid())
- shader->default_textures[p_name] = p_texture;
- else
- shader->default_textures.erase(p_name);
-
- _shader_make_dirty(shader);
-}
-RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const {
-
- const Shader *shader = shader_owner.getornull(p_shader);
- ERR_FAIL_COND_V(!shader, RID());
-
- const Map::Element *E = shader->default_textures.find(p_name);
- if (!E)
- return RID();
- return E->get();
-}
-
-/* COMMON MATERIAL API */
-
-void RasterizerStorageGLES3::_material_make_dirty(Material *p_material) const {
-
- if (p_material->dirty_list.in_list())
- return;
-
- _material_dirty_list.add(&p_material->dirty_list);
-}
-
-RID RasterizerStorageGLES3::material_create() {
-
- Material *material = memnew(Material);
-
- return material_owner.make_rid(material);
-}
-
-void RasterizerStorageGLES3::material_set_shader(RID p_material, RID p_shader) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- Shader *shader = shader_owner.getornull(p_shader);
-
- if (material->shader) {
- //if shader, remove from previous shader material list
- material->shader->materials.remove(&material->list);
- }
- material->shader = shader;
-
- if (shader) {
- shader->materials.add(&material->list);
- }
-
- _material_make_dirty(material);
-}
-
-RID RasterizerStorageGLES3::material_get_shader(RID p_material) const {
-
- const Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND_V(!material, RID());
-
- if (material->shader)
- return material->shader->self;
-
- return RID();
-}
-
-void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- if (p_value.get_type() == Variant::NIL)
- material->params.erase(p_param);
- else
- material->params[p_param] = p_value;
-
- _material_make_dirty(material);
-}
-Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName &p_param) const {
-
- const Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND_V(!material, Variant());
-
- if (material->params.has(p_param))
- return material->params[p_param];
-
- return material_get_param_default(p_material, p_param);
-}
-
-Variant RasterizerStorageGLES3::material_get_param_default(RID p_material, const StringName &p_param) const {
- const Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND_V(!material, Variant());
-
- if (material->shader) {
- if (material->shader->uniforms.has(p_param)) {
- ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param];
- Vector default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
- }
- }
- return Variant();
-}
-
-void RasterizerStorageGLES3::material_set_line_width(RID p_material, float p_width) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- material->line_width = p_width;
-}
-
-void RasterizerStorageGLES3::material_set_next_pass(RID p_material, RID p_next_material) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- material->next_pass = p_next_material;
-}
-
-bool RasterizerStorageGLES3::material_is_animated(RID p_material) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND_V(!material, false);
- if (material->dirty_list.in_list()) {
- _update_material(material);
- }
-
- bool animated = material->is_animated_cache;
- if (!animated && material->next_pass.is_valid()) {
- animated = material_is_animated(material->next_pass);
- }
- return animated;
-}
-bool RasterizerStorageGLES3::material_casts_shadows(RID p_material) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND_V(!material, false);
- if (material->dirty_list.in_list()) {
- _update_material(material);
- }
-
- bool casts_shadows = material->can_cast_shadow_cache;
-
- if (!casts_shadows && material->next_pass.is_valid()) {
- casts_shadows = material_casts_shadows(material->next_pass);
- }
-
- return casts_shadows;
-}
-
-void RasterizerStorageGLES3::material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- Map::Element *E = material->instance_owners.find(p_instance);
- if (E) {
- E->get()++;
- } else {
- material->instance_owners[p_instance] = 1;
- }
-}
-
-void RasterizerStorageGLES3::material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- Map::Element *E = material->instance_owners.find(p_instance);
- ERR_FAIL_COND(!E);
- E->get()--;
-
- if (E->get() == 0) {
- material->instance_owners.erase(E);
- }
-}
-
-void RasterizerStorageGLES3::material_set_render_priority(RID p_material, int priority) {
-
- ERR_FAIL_COND(priority < VS::MATERIAL_RENDER_PRIORITY_MIN);
- ERR_FAIL_COND(priority > VS::MATERIAL_RENDER_PRIORITY_MAX);
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- material->render_priority = priority;
-}
-
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant &value, uint8_t *data, bool p_linear_color) {
- switch (type) {
- case ShaderLanguage::TYPE_BOOL: {
-
- bool v = value;
-
- GLuint *gui = (GLuint *)data;
- *gui = v ? GL_TRUE : GL_FALSE;
- } break;
- case ShaderLanguage::TYPE_BVEC2: {
-
- int v = value;
- GLuint *gui = (GLuint *)data;
- gui[0] = (v & 1) ? GL_TRUE : GL_FALSE;
- gui[1] = (v & 2) ? GL_TRUE : GL_FALSE;
-
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
-
- int v = value;
- GLuint *gui = (GLuint *)data;
- gui[0] = (v & 1) ? GL_TRUE : GL_FALSE;
- gui[1] = (v & 2) ? GL_TRUE : GL_FALSE;
- gui[2] = (v & 4) ? GL_TRUE : GL_FALSE;
-
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
-
- int v = value;
- GLuint *gui = (GLuint *)data;
- gui[0] = (v & 1) ? GL_TRUE : GL_FALSE;
- gui[1] = (v & 2) ? GL_TRUE : GL_FALSE;
- gui[2] = (v & 4) ? GL_TRUE : GL_FALSE;
- gui[3] = (v & 8) ? GL_TRUE : GL_FALSE;
-
- } break;
- case ShaderLanguage::TYPE_INT: {
-
- int v = value;
- GLint *gui = (GLint *)data;
- gui[0] = v;
-
- } break;
- case ShaderLanguage::TYPE_IVEC2: {
-
- PoolVector iv = value;
- int s = iv.size();
- GLint *gui = (GLint *)data;
-
- PoolVector::Read r = iv.read();
-
- for (int i = 0; i < 2; i++) {
- if (i < s)
- gui[i] = r[i];
- else
- gui[i] = 0;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC3: {
-
- PoolVector iv = value;
- int s = iv.size();
- GLint *gui = (GLint *)data;
-
- PoolVector::Read r = iv.read();
-
- for (int i = 0; i < 3; i++) {
- if (i < s)
- gui[i] = r[i];
- else
- gui[i] = 0;
- }
- } break;
- case ShaderLanguage::TYPE_IVEC4: {
-
- PoolVector iv = value;
- int s = iv.size();
- GLint *gui = (GLint *)data;
-
- PoolVector::Read r = iv.read();
-
- for (int i = 0; i < 4; i++) {
- if (i < s)
- gui[i] = r[i];
- else
- gui[i] = 0;
- }
- } break;
- case ShaderLanguage::TYPE_UINT: {
-
- int v = value;
- GLuint *gui = (GLuint *)data;
- gui[0] = v;
-
- } break;
- case ShaderLanguage::TYPE_UVEC2: {
-
- PoolVector iv = value;
- int s = iv.size();
- GLuint *gui = (GLuint *)data;
-
- PoolVector::Read r = iv.read();
-
- for (int i = 0; i < 2; i++) {
- if (i < s)
- gui[i] = r[i];
- else
- gui[i] = 0;
- }
- } break;
- case ShaderLanguage::TYPE_UVEC3: {
- PoolVector iv = value;
- int s = iv.size();
- GLuint *gui = (GLuint *)data;
-
- PoolVector::Read r = iv.read();
-
- for (int i = 0; i < 3; i++) {
- if (i < s)
- gui[i] = r[i];
- else
- gui[i] = 0;
- }
-
- } break;
- case ShaderLanguage::TYPE_UVEC4: {
- PoolVector iv = value;
- int s = iv.size();
- GLuint *gui = (GLuint *)data;
-
- PoolVector::Read r = iv.read();
-
- for (int i = 0; i < 4; i++) {
- if (i < s)
- gui[i] = r[i];
- else
- gui[i] = 0;
- }
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
- float v = value;
- GLfloat *gui = (GLfloat *)data;
- gui[0] = v;
-
- } break;
- case ShaderLanguage::TYPE_VEC2: {
- Vector2 v = value;
- GLfloat *gui = (GLfloat *)data;
- gui[0] = v.x;
- gui[1] = v.y;
-
- } break;
- case ShaderLanguage::TYPE_VEC3: {
- Vector3 v = value;
- GLfloat *gui = (GLfloat *)data;
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
-
- } break;
- case ShaderLanguage::TYPE_VEC4: {
-
- GLfloat *gui = (GLfloat *)data;
-
- if (value.get_type() == Variant::COLOR) {
- Color v = value;
-
- if (p_linear_color) {
- v = v.to_linear();
- }
-
- gui[0] = v.r;
- gui[1] = v.g;
- gui[2] = v.b;
- gui[3] = v.a;
- } else if (value.get_type() == Variant::RECT2) {
- Rect2 v = value;
-
- gui[0] = v.position.x;
- gui[1] = v.position.y;
- gui[2] = v.size.x;
- gui[3] = v.size.y;
- } else if (value.get_type() == Variant::QUAT) {
- Quat v = value;
-
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
- gui[3] = v.w;
- } else {
- Plane v = value;
-
- gui[0] = v.normal.x;
- gui[1] = v.normal.y;
- gui[2] = v.normal.z;
- gui[3] = v.d;
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- Transform2D v = value;
- GLfloat *gui = (GLfloat *)data;
-
- //in std140 members of mat2 are treated as vec4s
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[0][1];
- gui[2] = 0;
- gui[3] = 0;
- gui[4] = v.elements[1][0];
- gui[5] = v.elements[1][1];
- gui[6] = 0;
- gui[7] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT3: {
-
- Basis v = value;
- GLfloat *gui = (GLfloat *)data;
-
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[1][0];
- gui[2] = v.elements[2][0];
- gui[3] = 0;
- gui[4] = v.elements[0][1];
- gui[5] = v.elements[1][1];
- gui[6] = v.elements[2][1];
- gui[7] = 0;
- gui[8] = v.elements[0][2];
- gui[9] = v.elements[1][2];
- gui[10] = v.elements[2][2];
- gui[11] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT4: {
-
- Transform v = value;
- GLfloat *gui = (GLfloat *)data;
-
- gui[0] = v.basis.elements[0][0];
- gui[1] = v.basis.elements[1][0];
- gui[2] = v.basis.elements[2][0];
- gui[3] = 0;
- gui[4] = v.basis.elements[0][1];
- gui[5] = v.basis.elements[1][1];
- gui[6] = v.basis.elements[2][1];
- gui[7] = 0;
- gui[8] = v.basis.elements[0][2];
- gui[9] = v.basis.elements[1][2];
- gui[10] = v.basis.elements[2][2];
- gui[11] = 0;
- gui[12] = v.origin.x;
- gui[13] = v.origin.y;
- gui[14] = v.origin.z;
- gui[15] = 1;
- } break;
- default: {
- }
- }
-}
-
-_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector &value, uint8_t *data) {
-
- switch (type) {
- case ShaderLanguage::TYPE_BOOL: {
-
- GLuint *gui = (GLuint *)data;
- *gui = value[0].boolean ? GL_TRUE : GL_FALSE;
- } break;
- case ShaderLanguage::TYPE_BVEC2: {
-
- GLuint *gui = (GLuint *)data;
- gui[0] = value[0].boolean ? GL_TRUE : GL_FALSE;
- gui[1] = value[1].boolean ? GL_TRUE : GL_FALSE;
-
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
-
- GLuint *gui = (GLuint *)data;
- gui[0] = value[0].boolean ? GL_TRUE : GL_FALSE;
- gui[1] = value[1].boolean ? GL_TRUE : GL_FALSE;
- gui[2] = value[2].boolean ? GL_TRUE : GL_FALSE;
-
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
-
- GLuint *gui = (GLuint *)data;
- gui[0] = value[0].boolean ? GL_TRUE : GL_FALSE;
- gui[1] = value[1].boolean ? GL_TRUE : GL_FALSE;
- gui[2] = value[2].boolean ? GL_TRUE : GL_FALSE;
- gui[3] = value[3].boolean ? GL_TRUE : GL_FALSE;
-
- } break;
- case ShaderLanguage::TYPE_INT: {
-
- GLint *gui = (GLint *)data;
- gui[0] = value[0].sint;
-
- } break;
- case ShaderLanguage::TYPE_IVEC2: {
-
- GLint *gui = (GLint *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC3: {
-
- GLint *gui = (GLint *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC4: {
-
- GLint *gui = (GLint *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_UINT: {
-
- GLuint *gui = (GLuint *)data;
- gui[0] = value[0].uint;
-
- } break;
- case ShaderLanguage::TYPE_UVEC2: {
-
- GLint *gui = (GLint *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].uint;
- }
- } break;
- case ShaderLanguage::TYPE_UVEC3: {
- GLint *gui = (GLint *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].uint;
- }
-
- } break;
- case ShaderLanguage::TYPE_UVEC4: {
- GLint *gui = (GLint *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].uint;
- }
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
-
- GLfloat *gui = (GLfloat *)data;
- gui[0] = value[0].real;
-
- } break;
- case ShaderLanguage::TYPE_VEC2: {
-
- GLfloat *gui = (GLfloat *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].real;
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC3: {
-
- GLfloat *gui = (GLfloat *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].real;
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC4: {
-
- GLfloat *gui = (GLfloat *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].real;
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- GLfloat *gui = (GLfloat *)data;
-
- //in std140 members of mat2 are treated as vec4s
- gui[0] = value[0].real;
- gui[1] = value[1].real;
- gui[2] = 0;
- gui[3] = 0;
- gui[4] = value[2].real;
- gui[5] = value[3].real;
- gui[6] = 0;
- gui[7] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT3: {
-
- GLfloat *gui = (GLfloat *)data;
-
- gui[0] = value[0].real;
- gui[1] = value[1].real;
- gui[2] = value[2].real;
- gui[3] = 0;
- gui[4] = value[3].real;
- gui[5] = value[4].real;
- gui[6] = value[5].real;
- gui[7] = 0;
- gui[8] = value[6].real;
- gui[9] = value[7].real;
- gui[10] = value[8].real;
- gui[11] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT4: {
-
- GLfloat *gui = (GLfloat *)data;
-
- for (int i = 0; i < 16; i++) {
- gui[i] = value[i].real;
- }
- } break;
- default: {
- }
- }
-}
-
-_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) {
-
- switch (type) {
-
- case ShaderLanguage::TYPE_BOOL:
- case ShaderLanguage::TYPE_INT:
- case ShaderLanguage::TYPE_UINT:
- case ShaderLanguage::TYPE_FLOAT: {
- zeromem(data, 4);
- } break;
- case ShaderLanguage::TYPE_BVEC2:
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_UVEC2:
- case ShaderLanguage::TYPE_VEC2: {
- zeromem(data, 8);
- } break;
- case ShaderLanguage::TYPE_BVEC3:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_VEC3: {
- zeromem(data, 12);
- } break;
- case ShaderLanguage::TYPE_BVEC4:
- case ShaderLanguage::TYPE_IVEC4:
- case ShaderLanguage::TYPE_UVEC4:
- case ShaderLanguage::TYPE_VEC4: {
-
- zeromem(data, 16);
- } break;
- case ShaderLanguage::TYPE_MAT2: {
-
- zeromem(data, 32);
- } break;
- case ShaderLanguage::TYPE_MAT3: {
-
- zeromem(data, 48);
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- zeromem(data, 64);
- } break;
-
- default: {
- }
- }
-}
-
-void RasterizerStorageGLES3::_update_material(Material *material) {
-
- if (material->dirty_list.in_list())
- _material_dirty_list.remove(&material->dirty_list);
-
- if (material->shader && material->shader->dirty_list.in_list()) {
- _update_shader(material->shader);
- }
-
- if (material->shader && !material->shader->valid)
- return;
-
- //update caches
-
- {
- bool can_cast_shadow = false;
- bool is_animated = false;
-
- if (material->shader && material->shader->mode == VS::SHADER_SPATIAL) {
-
- if (material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
- (!material->shader->spatial.uses_alpha || material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
- can_cast_shadow = true;
- }
-
- if (material->shader->spatial.uses_discard && material->shader->uses_fragment_time) {
- is_animated = true;
- }
-
- if (material->shader->spatial.uses_vertex && material->shader->uses_vertex_time) {
- is_animated = true;
- }
-
- if (can_cast_shadow != material->can_cast_shadow_cache || is_animated != material->is_animated_cache) {
- material->can_cast_shadow_cache = can_cast_shadow;
- material->is_animated_cache = is_animated;
-
- for (Map::Element *E = material->geometry_owners.front(); E; E = E->next()) {
- E->key()->material_changed_notify();
- }
-
- for (Map::Element *E = material->instance_owners.front(); E; E = E->next()) {
- E->key()->base_changed(false, true);
- }
- }
- }
- }
-
- //clear ubo if it needs to be cleared
- if (material->ubo_size) {
-
- if (!material->shader || material->shader->ubo_size != material->ubo_size) {
- //by by ubo
- glDeleteBuffers(1, &material->ubo_id);
- material->ubo_id = 0;
- material->ubo_size = 0;
- }
- }
-
- //create ubo if it needs to be created
- if (material->ubo_size == 0 && material->shader && material->shader->ubo_size) {
-
- glGenBuffers(1, &material->ubo_id);
- glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id);
- glBufferData(GL_UNIFORM_BUFFER, material->shader->ubo_size, NULL, GL_STATIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
- material->ubo_size = material->shader->ubo_size;
- }
-
- //fill up the UBO if it needs to be filled
- if (material->shader && material->ubo_size) {
- uint8_t *local_ubo = (uint8_t *)alloca(material->ubo_size);
-
- for (Map::Element *E = material->shader->uniforms.front(); E; E = E->next()) {
-
- if (E->get().order < 0)
- continue; // texture, does not go here
-
- //regular uniform
- uint8_t *data = &local_ubo[material->shader->ubo_offsets[E->get().order]];
-
- Map::Element *V = material->params.find(E->key());
-
- if (V) {
- //user provided
- _fill_std140_variant_ubo_value(E->get().type, V->get(), data, material->shader->mode == VS::SHADER_SPATIAL);
-
- } else if (E->get().default_value.size()) {
- //default value
- _fill_std140_ubo_value(E->get().type, E->get().default_value, data);
- //value=E->get().default_value;
- } else {
- //zero because it was not provided
- if (E->get().type == ShaderLanguage::TYPE_VEC4 && E->get().hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- //colors must be set as black, with alpha as 1.0
- _fill_std140_variant_ubo_value(E->get().type, Color(0, 0, 0, 1), data, material->shader->mode == VS::SHADER_SPATIAL);
- } else {
- //else just zero it out
- _fill_std140_ubo_empty(E->get().type, data);
- }
- }
- }
-
- glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id);
- glBufferData(GL_UNIFORM_BUFFER, material->ubo_size, local_ubo, GL_STATIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
- }
-
- //set up the texture array, for easy access when it needs to be drawn
- if (material->shader && material->shader->texture_count) {
-
- material->texture_is_3d.resize(material->shader->texture_count);
- material->textures.resize(material->shader->texture_count);
-
- for (Map::Element *E = material->shader->uniforms.front(); E; E = E->next()) {
-
- if (E->get().texture_order < 0)
- continue; // not a texture, does not go here
-
- RID texture;
-
- switch (E->get().type) {
- case ShaderLanguage::TYPE_SAMPLER3D:
- case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
- material->texture_is_3d.write[E->get().texture_order] = true;
- } break;
- default: {
- material->texture_is_3d.write[E->get().texture_order] = false;
- } break;
- }
-
- Map::Element *V = material->params.find(E->key());
- if (V) {
- texture = V->get();
- }
-
- if (!texture.is_valid()) {
- Map::Element *W = material->shader->default_textures.find(E->key());
- if (W) {
- texture = W->get();
- }
- }
-
- material->textures.write[E->get().texture_order] = texture;
- }
-
- } else {
- material->textures.clear();
- material->texture_is_3d.clear();
- }
-}
-
-void RasterizerStorageGLES3::_material_add_geometry(RID p_material, Geometry *p_geometry) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- Map::Element *I = material->geometry_owners.find(p_geometry);
-
- if (I) {
- I->get()++;
- } else {
- material->geometry_owners[p_geometry] = 1;
- }
-}
-
-void RasterizerStorageGLES3::_material_remove_geometry(RID p_material, Geometry *p_geometry) {
-
- Material *material = material_owner.getornull(p_material);
- ERR_FAIL_COND(!material);
-
- Map::Element *I = material->geometry_owners.find(p_geometry);
- ERR_FAIL_COND(!I);
-
- I->get()--;
- if (I->get() == 0) {
- material->geometry_owners.erase(I);
- }
-}
-
-void RasterizerStorageGLES3::update_dirty_materials() {
-
- while (_material_dirty_list.first()) {
-
- Material *material = _material_dirty_list.first()->self();
-
- _update_material(material);
- }
-}
-
-/* MESH API */
-
-RID RasterizerStorageGLES3::mesh_create() {
-
- Mesh *mesh = memnew(Mesh);
-
- return mesh_owner.make_rid(mesh);
-}
-
-void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector &p_array, int p_vertex_count, const PoolVector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector > &p_blend_shapes, const Vector &p_bone_aabbs) {
-
- PoolVector array = p_array;
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- ERR_FAIL_COND(!(p_format & VS::ARRAY_FORMAT_VERTEX));
-
- //must have index and bones, both.
- {
- uint32_t bones_weight = VS::ARRAY_FORMAT_BONES | VS::ARRAY_FORMAT_WEIGHTS;
- ERR_FAIL_COND_MSG((p_format & bones_weight) && (p_format & bones_weight) != bones_weight, "Array must have both bones and weights in format or none.");
- }
-
- //bool has_morph = p_blend_shapes.size();
-
- Surface::Attrib attribs[VS::ARRAY_MAX];
-
- int stride = 0;
-
- for (int i = 0; i < VS::ARRAY_MAX; i++) {
-
- attribs[i].index = i;
-
- if (!(p_format & (1 << i))) {
- attribs[i].enabled = false;
- attribs[i].integer = false;
- continue;
- }
-
- attribs[i].enabled = true;
- attribs[i].offset = stride;
- attribs[i].integer = false;
-
- switch (i) {
-
- case VS::ARRAY_VERTEX: {
-
- if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
- attribs[i].size = 2;
- } else {
- attribs[i].size = (p_format & VS::ARRAY_COMPRESS_VERTEX) ? 4 : 3;
- }
-
- if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
- attribs[i].type = GL_HALF_FLOAT;
- stride += attribs[i].size * 2;
- } else {
- attribs[i].type = GL_FLOAT;
- stride += attribs[i].size * 4;
- }
-
- attribs[i].normalized = GL_FALSE;
-
- } break;
- case VS::ARRAY_NORMAL: {
-
- attribs[i].size = 3;
-
- if (p_format & VS::ARRAY_COMPRESS_NORMAL) {
- attribs[i].type = GL_BYTE;
- stride += 4; //pad extra byte
- attribs[i].normalized = GL_TRUE;
- } else {
- attribs[i].type = GL_FLOAT;
- stride += 12;
- attribs[i].normalized = GL_FALSE;
- }
-
- } break;
- case VS::ARRAY_TANGENT: {
-
- attribs[i].size = 4;
-
- if (p_format & VS::ARRAY_COMPRESS_TANGENT) {
- attribs[i].type = GL_BYTE;
- stride += 4;
- attribs[i].normalized = GL_TRUE;
- } else {
- attribs[i].type = GL_FLOAT;
- stride += 16;
- attribs[i].normalized = GL_FALSE;
- }
-
- } break;
- case VS::ARRAY_COLOR: {
-
- attribs[i].size = 4;
-
- if (p_format & VS::ARRAY_COMPRESS_COLOR) {
- attribs[i].type = GL_UNSIGNED_BYTE;
- stride += 4;
- attribs[i].normalized = GL_TRUE;
- } else {
- attribs[i].type = GL_FLOAT;
- stride += 16;
- attribs[i].normalized = GL_FALSE;
- }
-
- } break;
- case VS::ARRAY_TEX_UV: {
-
- attribs[i].size = 2;
-
- if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
- attribs[i].type = GL_HALF_FLOAT;
- stride += 4;
- } else {
- attribs[i].type = GL_FLOAT;
- stride += 8;
- }
-
- attribs[i].normalized = GL_FALSE;
-
- } break;
- case VS::ARRAY_TEX_UV2: {
-
- attribs[i].size = 2;
-
- if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
- attribs[i].type = GL_HALF_FLOAT;
- stride += 4;
- } else {
- attribs[i].type = GL_FLOAT;
- stride += 8;
- }
- attribs[i].normalized = GL_FALSE;
-
- } break;
- case VS::ARRAY_BONES: {
-
- attribs[i].size = 4;
-
- if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) {
- attribs[i].type = GL_UNSIGNED_SHORT;
- stride += 8;
- } else {
- attribs[i].type = GL_UNSIGNED_BYTE;
- stride += 4;
- }
-
- attribs[i].normalized = GL_FALSE;
- attribs[i].integer = true;
-
- } break;
- case VS::ARRAY_WEIGHTS: {
-
- attribs[i].size = 4;
-
- if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) {
-
- attribs[i].type = GL_UNSIGNED_SHORT;
- stride += 8;
- attribs[i].normalized = GL_TRUE;
- } else {
- attribs[i].type = GL_FLOAT;
- stride += 16;
- attribs[i].normalized = GL_FALSE;
- }
-
- } break;
- case VS::ARRAY_INDEX: {
-
- attribs[i].size = 1;
-
- if (p_vertex_count >= (1 << 16)) {
- attribs[i].type = GL_UNSIGNED_INT;
- attribs[i].stride = 4;
- } else {
- attribs[i].type = GL_UNSIGNED_SHORT;
- attribs[i].stride = 2;
- }
-
- attribs[i].normalized = GL_FALSE;
-
- } break;
- }
- }
-
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
- attribs[i].stride = stride;
- }
-
- //validate sizes
-
- int array_size = stride * p_vertex_count;
- int index_array_size = 0;
- if (array.size() != array_size && array.size() + p_vertex_count * 2 == array_size) {
- //old format, convert
- array = PoolVector();
-
- array.resize(p_array.size() + p_vertex_count * 2);
-
- PoolVector::Write w = array.write();
- PoolVector::Read r = p_array.read();
-
- uint16_t *w16 = (uint16_t *)w.ptr();
- const uint16_t *r16 = (uint16_t *)r.ptr();
-
- uint16_t one = Math::make_half_float(1);
-
- for (int i = 0; i < p_vertex_count; i++) {
-
- *w16++ = *r16++;
- *w16++ = *r16++;
- *w16++ = *r16++;
- *w16++ = one;
- for (int j = 0; j < (stride / 2) - 4; j++) {
- *w16++ = *r16++;
- }
- }
- }
-
- ERR_FAIL_COND(array.size() != array_size);
-
- if (p_format & VS::ARRAY_FORMAT_INDEX) {
-
- index_array_size = attribs[VS::ARRAY_INDEX].stride * p_index_count;
- }
-
- ERR_FAIL_COND(p_index_array.size() != index_array_size);
-
- ERR_FAIL_COND(p_blend_shapes.size() != mesh->blend_shape_count);
-
- for (int i = 0; i < p_blend_shapes.size(); i++) {
- ERR_FAIL_COND(p_blend_shapes[i].size() != array_size);
- }
-
- //ok all valid, create stuff
-
- Surface *surface = memnew(Surface);
-
- surface->active = true;
- surface->array_len = p_vertex_count;
- surface->index_array_len = p_index_count;
- surface->array_byte_size = array.size();
- surface->index_array_byte_size = p_index_array.size();
- surface->primitive = p_primitive;
- surface->mesh = mesh;
- surface->format = p_format;
- surface->skeleton_bone_aabb = p_bone_aabbs;
- surface->skeleton_bone_used.resize(surface->skeleton_bone_aabb.size());
- surface->aabb = p_aabb;
- surface->max_bone = p_bone_aabbs.size();
- surface->total_data_size += surface->array_byte_size + surface->index_array_byte_size;
-
- for (int i = 0; i < surface->skeleton_bone_used.size(); i++) {
- if (surface->skeleton_bone_aabb[i].size.x < 0 || surface->skeleton_bone_aabb[i].size.y < 0 || surface->skeleton_bone_aabb[i].size.z < 0) {
- surface->skeleton_bone_used.write[i] = false;
- } else {
- surface->skeleton_bone_used.write[i] = true;
- }
- }
-
- for (int i = 0; i < VS::ARRAY_MAX; i++) {
- surface->attribs[i] = attribs[i];
- }
-
- {
-
- PoolVector::Read vr = array.read();
-
- glGenBuffers(1, &surface->vertex_id);
- glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
- glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), (p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- if (p_format & VS::ARRAY_FORMAT_INDEX) {
-
- PoolVector::Read ir = p_index_array.read();
-
- glGenBuffers(1, &surface->index_id);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_array_size, ir.ptr(), GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
- }
-
- //generate arrays for faster state switching
-
- for (int ai = 0; ai < 2; ai++) {
-
- if (ai == 0) {
- //for normal draw
- glGenVertexArrays(1, &surface->array_id);
- glBindVertexArray(surface->array_id);
- glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
- } else if (ai == 1) {
- //for instancing draw (can be changed and no one cares)
- glGenVertexArrays(1, &surface->instancing_array_id);
- glBindVertexArray(surface->instancing_array_id);
- glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
- }
-
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
-
- if (!attribs[i].enabled)
- continue;
-
- if (attribs[i].integer) {
- glVertexAttribIPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset));
- } else {
- glVertexAttribPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset));
- }
- glEnableVertexAttribArray(attribs[i].index);
- }
-
- if (surface->index_id) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
- }
-
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
-
-#ifdef DEBUG_ENABLED
-
- if (config.generate_wireframes && p_primitive == VS::PRIMITIVE_TRIANGLES) {
- //generate wireframes, this is used mostly by editor
- PoolVector wf_indices;
- int index_count;
-
- if (p_format & VS::ARRAY_FORMAT_INDEX) {
-
- index_count = p_index_count * 2;
- wf_indices.resize(index_count);
-
- PoolVector::Read ir = p_index_array.read();
- PoolVector::Write wr = wf_indices.write();
-
- if (p_vertex_count < (1 << 16)) {
- //read 16 bit indices
- const uint16_t *src_idx = (const uint16_t *)ir.ptr();
- for (int i = 0; i + 5 < index_count; i += 6) {
-
- wr[i + 0] = src_idx[i / 2];
- wr[i + 1] = src_idx[i / 2 + 1];
- wr[i + 2] = src_idx[i / 2 + 1];
- wr[i + 3] = src_idx[i / 2 + 2];
- wr[i + 4] = src_idx[i / 2 + 2];
- wr[i + 5] = src_idx[i / 2];
- }
-
- } else {
-
- //read 16 bit indices
- const uint32_t *src_idx = (const uint32_t *)ir.ptr();
- for (int i = 0; i + 5 < index_count; i += 6) {
-
- wr[i + 0] = src_idx[i / 2];
- wr[i + 1] = src_idx[i / 2 + 1];
- wr[i + 2] = src_idx[i / 2 + 1];
- wr[i + 3] = src_idx[i / 2 + 2];
- wr[i + 4] = src_idx[i / 2 + 2];
- wr[i + 5] = src_idx[i / 2];
- }
- }
-
- } else {
-
- index_count = p_vertex_count * 2;
- wf_indices.resize(index_count);
- PoolVector::Write wr = wf_indices.write();
- for (int i = 0; i + 5 < index_count; i += 6) {
-
- wr[i + 0] = i / 2;
- wr[i + 1] = i / 2 + 1;
- wr[i + 2] = i / 2 + 1;
- wr[i + 3] = i / 2 + 2;
- wr[i + 4] = i / 2 + 2;
- wr[i + 5] = i / 2;
- }
- }
- {
- PoolVector::Read ir = wf_indices.read();
-
- glGenBuffers(1, &surface->index_wireframe_id);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_wireframe_id);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_count * sizeof(uint32_t), ir.ptr(), GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
-
- surface->index_wireframe_len = index_count;
- }
-
- for (int ai = 0; ai < 2; ai++) {
-
- if (ai == 0) {
- //for normal draw
- glGenVertexArrays(1, &surface->array_wireframe_id);
- glBindVertexArray(surface->array_wireframe_id);
- glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
- } else if (ai == 1) {
- //for instancing draw (can be changed and no one cares)
- glGenVertexArrays(1, &surface->instancing_array_wireframe_id);
- glBindVertexArray(surface->instancing_array_wireframe_id);
- glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
- }
-
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
-
- if (!attribs[i].enabled)
- continue;
-
- if (attribs[i].integer) {
- glVertexAttribIPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset));
- } else {
- glVertexAttribPointer(attribs[i].index, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset));
- }
- glEnableVertexAttribArray(attribs[i].index);
- }
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_wireframe_id);
-
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- }
-
-#endif
- }
-
- {
-
- //blend shapes
-
- for (int i = 0; i < p_blend_shapes.size(); i++) {
-
- Surface::BlendShape mt;
-
- PoolVector::Read vr = p_blend_shapes[i].read();
-
- surface->total_data_size += array_size;
-
- glGenBuffers(1, &mt.vertex_id);
- glBindBuffer(GL_ARRAY_BUFFER, mt.vertex_id);
- glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), GL_STATIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- glGenVertexArrays(1, &mt.array_id);
- glBindVertexArray(mt.array_id);
- glBindBuffer(GL_ARRAY_BUFFER, mt.vertex_id);
-
- for (int j = 0; j < VS::ARRAY_MAX - 1; j++) {
-
- if (!attribs[j].enabled)
- continue;
-
- if (attribs[j].integer) {
- glVertexAttribIPointer(attribs[j].index, attribs[j].size, attribs[j].type, attribs[j].stride, CAST_INT_TO_UCHAR_PTR(attribs[j].offset));
- } else {
- glVertexAttribPointer(attribs[j].index, attribs[j].size, attribs[j].type, attribs[j].normalized, attribs[j].stride, CAST_INT_TO_UCHAR_PTR(attribs[j].offset));
- }
- glEnableVertexAttribArray(attribs[j].index);
- }
-
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- surface->blend_shapes.push_back(mt);
- }
- }
-
- mesh->surfaces.push_back(surface);
- mesh->instance_change_notify(true, true);
-
- info.vertex_mem += surface->total_data_size;
-}
-
-void RasterizerStorageGLES3::mesh_set_blend_shape_count(RID p_mesh, int p_amount) {
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- ERR_FAIL_COND(mesh->surfaces.size() != 0);
- ERR_FAIL_COND(p_amount < 0);
-
- mesh->blend_shape_count = p_amount;
- mesh->instance_change_notify(true, false);
-}
-int RasterizerStorageGLES3::mesh_get_blend_shape_count(RID p_mesh) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, 0);
-
- return mesh->blend_shape_count;
-}
-
-void RasterizerStorageGLES3::mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) {
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- mesh->blend_shape_mode = p_mode;
-}
-VS::BlendShapeMode RasterizerStorageGLES3::mesh_get_blend_shape_mode(RID p_mesh) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, VS::BLEND_SHAPE_MODE_NORMALIZED);
-
- return mesh->blend_shape_mode;
-}
-
-void RasterizerStorageGLES3::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector &p_data) {
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_INDEX(p_surface, mesh->surfaces.size());
-
- int total_size = p_data.size();
- ERR_FAIL_COND(p_offset + total_size > mesh->surfaces[p_surface]->array_byte_size);
-
- PoolVector::Read r = p_data.read();
-
- glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->vertex_id);
- glBufferSubData(GL_ARRAY_BUFFER, p_offset, total_size, r.ptr());
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-}
-
-void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_INDEX(p_surface, mesh->surfaces.size());
-
- if (mesh->surfaces[p_surface]->material == p_material)
- return;
-
- if (mesh->surfaces[p_surface]->material.is_valid()) {
- _material_remove_geometry(mesh->surfaces[p_surface]->material, mesh->surfaces[p_surface]);
- }
-
- mesh->surfaces[p_surface]->material = p_material;
-
- if (mesh->surfaces[p_surface]->material.is_valid()) {
- _material_add_geometry(mesh->surfaces[p_surface]->material, mesh->surfaces[p_surface]);
- }
-
- mesh->instance_change_notify(false, true);
-}
-RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, RID());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RID());
-
- return mesh->surfaces[p_surface]->material;
-}
-
-int RasterizerStorageGLES3::mesh_surface_get_array_len(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, 0);
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0);
-
- return mesh->surfaces[p_surface]->array_len;
-}
-int RasterizerStorageGLES3::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, 0);
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0);
-
- return mesh->surfaces[p_surface]->index_array_len;
-}
-
-PoolVector RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, PoolVector());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), PoolVector());
-
- Surface *surface = mesh->surfaces[p_surface];
-
- PoolVector ret;
- ret.resize(surface->array_byte_size);
- glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id);
-
-#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
- {
- PoolVector::Write w = ret.write();
- glGetBufferSubData(GL_ARRAY_BUFFER, 0, surface->array_byte_size, w.ptr());
- }
-#else
- void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, PoolVector());
- {
- PoolVector::Write w = ret.write();
- copymem(w.ptr(), data, surface->array_byte_size);
- }
- glUnmapBuffer(GL_ARRAY_BUFFER);
-#endif
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- return ret;
-}
-
-PoolVector RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh, int p_surface) const {
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, PoolVector());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), PoolVector());
-
- Surface *surface = mesh->surfaces[p_surface];
-
- PoolVector ret;
- ret.resize(surface->index_array_byte_size);
-
- if (surface->index_array_byte_size > 0) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
-
-#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
- {
- PoolVector::Write w = ret.write();
- glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr());
- }
-#else
- void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, PoolVector());
- {
- PoolVector::Write w = ret.write();
- copymem(w.ptr(), data, surface->index_array_byte_size);
- }
- glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-#endif
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
-
- return ret;
-}
-
-uint32_t RasterizerStorageGLES3::mesh_surface_get_format(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
-
- ERR_FAIL_COND_V(!mesh, 0);
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0);
-
- return mesh->surfaces[p_surface]->format;
-}
-
-VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, VS::PRIMITIVE_MAX);
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_MAX);
-
- return mesh->surfaces[p_surface]->primitive;
-}
-
-AABB RasterizerStorageGLES3::mesh_surface_get_aabb(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), AABB());
-
- return mesh->surfaces[p_surface]->aabb;
-}
-Vector > RasterizerStorageGLES3::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, Vector >());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Vector >());
-
- Vector > bsarr;
-
- for (int i = 0; i < mesh->surfaces[p_surface]->blend_shapes.size(); i++) {
-
- PoolVector ret;
- ret.resize(mesh->surfaces[p_surface]->array_byte_size);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id);
-
-#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
- {
- PoolVector::Write w = ret.write();
- glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, w.ptr());
- }
-#else
- void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT);
- ERR_FAIL_COND_V(!data, Vector >());
- {
- PoolVector::Write w = ret.write();
- copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size);
- }
- glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-#endif
-
- bsarr.push_back(ret);
- }
-
- return bsarr;
-}
-
-Vector RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, Vector());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Vector());
-
- return mesh->surfaces[p_surface]->skeleton_bone_aabb;
-}
-
-void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface) {
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_INDEX(p_surface, mesh->surfaces.size());
-
- Surface *surface = mesh->surfaces[p_surface];
-
- if (surface->material.is_valid()) {
- _material_remove_geometry(surface->material, mesh->surfaces[p_surface]);
- }
-
- glDeleteBuffers(1, &surface->vertex_id);
- if (surface->index_id) {
- glDeleteBuffers(1, &surface->index_id);
- }
-
- glDeleteVertexArrays(1, &surface->array_id);
- glDeleteVertexArrays(1, &surface->instancing_array_id);
-
- for (int i = 0; i < surface->blend_shapes.size(); i++) {
-
- glDeleteBuffers(1, &surface->blend_shapes[i].vertex_id);
- glDeleteVertexArrays(1, &surface->blend_shapes[i].array_id);
- }
-
- if (surface->index_wireframe_id) {
- glDeleteBuffers(1, &surface->index_wireframe_id);
- glDeleteVertexArrays(1, &surface->array_wireframe_id);
- glDeleteVertexArrays(1, &surface->instancing_array_wireframe_id);
- }
-
- info.vertex_mem -= surface->total_data_size;
-
- memdelete(surface);
-
- mesh->surfaces.remove(p_surface);
-
- mesh->instance_change_notify(true, true);
-}
-
-int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, 0);
- return mesh->surfaces.size();
-}
-
-void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- mesh->custom_aabb = p_aabb;
- mesh->instance_change_notify(true, false);
-}
-
-AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const {
-
- const Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
-
- return mesh->custom_aabb;
-}
-
-AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
-
- if (mesh->custom_aabb != AABB()) {
- return mesh->custom_aabb;
- }
-
- Skeleton *sk = NULL;
- if (p_skeleton.is_valid()) {
- sk = skeleton_owner.getornull(p_skeleton);
- }
-
- AABB aabb;
-
- if (sk && sk->size != 0) {
-
- for (int i = 0; i < mesh->surfaces.size(); i++) {
-
- AABB laabb;
- if ((mesh->surfaces[i]->format & VS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->skeleton_bone_aabb.size()) {
-
- int bs = mesh->surfaces[i]->skeleton_bone_aabb.size();
- const AABB *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr();
- const bool *skused = mesh->surfaces[i]->skeleton_bone_used.ptr();
-
- int sbs = sk->size;
- ERR_CONTINUE(bs > sbs);
- const float *texture = sk->skel_texture.ptr();
-
- bool first = true;
- if (sk->use_2d) {
- for (int j = 0; j < bs; j++) {
-
- if (!skused[j])
- continue;
-
- int base_ofs = ((j / 256) * 256) * 2 * 4 + (j % 256) * 4;
-
- Transform mtx;
-
- mtx.basis[0].x = texture[base_ofs + 0];
- mtx.basis[0].y = texture[base_ofs + 1];
- mtx.origin.x = texture[base_ofs + 3];
- base_ofs += 256 * 4;
- mtx.basis[1].x = texture[base_ofs + 0];
- mtx.basis[1].y = texture[base_ofs + 1];
- mtx.origin.y = texture[base_ofs + 3];
-
- AABB baabb = mtx.xform(skbones[j]);
-
- if (first) {
- laabb = baabb;
- first = false;
- } else {
- laabb.merge_with(baabb);
- }
- }
- } else {
- for (int j = 0; j < bs; j++) {
-
- if (!skused[j])
- continue;
-
- int base_ofs = ((j / 256) * 256) * 3 * 4 + (j % 256) * 4;
-
- Transform mtx;
-
- mtx.basis[0].x = texture[base_ofs + 0];
- mtx.basis[0].y = texture[base_ofs + 1];
- mtx.basis[0].z = texture[base_ofs + 2];
- mtx.origin.x = texture[base_ofs + 3];
- base_ofs += 256 * 4;
- mtx.basis[1].x = texture[base_ofs + 0];
- mtx.basis[1].y = texture[base_ofs + 1];
- mtx.basis[1].z = texture[base_ofs + 2];
- mtx.origin.y = texture[base_ofs + 3];
- base_ofs += 256 * 4;
- mtx.basis[2].x = texture[base_ofs + 0];
- mtx.basis[2].y = texture[base_ofs + 1];
- mtx.basis[2].z = texture[base_ofs + 2];
- mtx.origin.z = texture[base_ofs + 3];
-
- AABB baabb = mtx.xform(skbones[j]);
- if (first) {
- laabb = baabb;
- first = false;
- } else {
- laabb.merge_with(baabb);
- }
- }
- }
-
- } else {
-
- laabb = mesh->surfaces[i]->aabb;
- }
-
- if (i == 0)
- aabb = laabb;
- else
- aabb.merge_with(laabb);
- }
- } else {
-
- for (int i = 0; i < mesh->surfaces.size(); i++) {
-
- if (i == 0)
- aabb = mesh->surfaces[i]->aabb;
- else
- aabb.merge_with(mesh->surfaces[i]->aabb);
- }
- }
-
- return aabb;
-}
-void RasterizerStorageGLES3::mesh_clear(RID p_mesh) {
-
- Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- while (mesh->surfaces.size()) {
- mesh_remove_surface(p_mesh, 0);
- }
-}
-
-void RasterizerStorageGLES3::mesh_render_blend_shapes(Surface *s, const float *p_weights) {
-
- glBindVertexArray(s->array_id);
-
- BlendShapeShaderGLES3::Conditionals cond[VS::ARRAY_MAX - 1] = {
- BlendShapeShaderGLES3::ENABLE_NORMAL, //will be ignored
- BlendShapeShaderGLES3::ENABLE_NORMAL,
- BlendShapeShaderGLES3::ENABLE_TANGENT,
- BlendShapeShaderGLES3::ENABLE_COLOR,
- BlendShapeShaderGLES3::ENABLE_UV,
- BlendShapeShaderGLES3::ENABLE_UV2,
- BlendShapeShaderGLES3::ENABLE_SKELETON,
- BlendShapeShaderGLES3::ENABLE_SKELETON,
- };
-
- int stride = 0;
-
- if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
- stride = 2 * 4;
- } else {
- stride = 3 * 4;
- }
-
- static const int sizes[VS::ARRAY_MAX - 1] = {
- 3 * 4,
- 3 * 4,
- 4 * 4,
- 4 * 4,
- 2 * 4,
- 2 * 4,
- 4 * 4,
- 4 * 4
- };
-
- for (int i = 1; i < VS::ARRAY_MAX - 1; i++) {
- shaders.blend_shapes.set_conditional(cond[i], s->format & (1 << i)); //enable conditional for format
- if (s->format & (1 << i)) {
- stride += sizes[i];
- }
- }
-
- //copy all first
- float base_weight = 1.0;
-
- int mtc = s->blend_shapes.size();
-
- if (s->mesh->blend_shape_mode == VS::BLEND_SHAPE_MODE_NORMALIZED) {
-
- for (int i = 0; i < mtc; i++) {
- base_weight -= p_weights[i];
- }
- }
-
- shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND, false); //first pass does not blend
- shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::USE_2D_VERTEX, s->format & VS::ARRAY_FLAG_USE_2D_VERTICES); //use 2D vertices if needed
-
- shaders.blend_shapes.bind();
-
- shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT, base_weight);
- glEnable(GL_RASTERIZER_DISCARD);
-
- glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[0]);
- glBeginTransformFeedback(GL_POINTS);
- glDrawArrays(GL_POINTS, 0, s->array_len);
- glEndTransformFeedback();
-
- shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND, true); //first pass does not blend
- shaders.blend_shapes.bind();
-
- for (int ti = 0; ti < mtc; ti++) {
- float weight = p_weights[ti];
-
- if (weight < 0.00001) //not bother with this one
- continue;
-
- glBindVertexArray(s->blend_shapes[ti].array_id);
- glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]);
- glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[1]);
-
- shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT, weight);
-
- int ofs = 0;
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
-
- if (s->format & (1 << i)) {
- glEnableVertexAttribArray(i + 8);
- switch (i) {
-
- case VS::ARRAY_VERTEX: {
- if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
- glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 2 * 4;
- } else {
- glVertexAttribPointer(i + 8, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 3 * 4;
- }
- } break;
- case VS::ARRAY_NORMAL: {
- glVertexAttribPointer(i + 8, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 3 * 4;
- } break;
- case VS::ARRAY_TANGENT: {
- glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 4 * 4;
-
- } break;
- case VS::ARRAY_COLOR: {
- glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 4 * 4;
-
- } break;
- case VS::ARRAY_TEX_UV: {
- glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 2 * 4;
-
- } break;
- case VS::ARRAY_TEX_UV2: {
- glVertexAttribPointer(i + 8, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 2 * 4;
-
- } break;
- case VS::ARRAY_BONES: {
- glVertexAttribIPointer(i + 8, 4, GL_UNSIGNED_INT, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 4 * 4;
-
- } break;
- case VS::ARRAY_WEIGHTS: {
- glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 4 * 4;
-
- } break;
- }
-
- } else {
- glDisableVertexAttribArray(i + 8);
- }
- }
-
- glBeginTransformFeedback(GL_POINTS);
- glDrawArrays(GL_POINTS, 0, s->array_len);
- glEndTransformFeedback();
-
- SWAP(resources.transform_feedback_buffers[0], resources.transform_feedback_buffers[1]);
- }
-
- glDisable(GL_RASTERIZER_DISCARD);
- glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
-
- glBindVertexArray(resources.transform_feedback_array);
- glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]);
-
- int ofs = 0;
- for (int i = 0; i < VS::ARRAY_MAX - 1; i++) {
-
- if (s->format & (1 << i)) {
- glEnableVertexAttribArray(i);
- switch (i) {
-
- case VS::ARRAY_VERTEX: {
- if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
- glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 2 * 4;
- } else {
- glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 3 * 4;
- }
- } break;
- case VS::ARRAY_NORMAL: {
- glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 3 * 4;
- } break;
- case VS::ARRAY_TANGENT: {
- glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 4 * 4;
-
- } break;
- case VS::ARRAY_COLOR: {
- glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 4 * 4;
-
- } break;
- case VS::ARRAY_TEX_UV: {
- glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 2 * 4;
-
- } break;
- case VS::ARRAY_TEX_UV2: {
- glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 2 * 4;
-
- } break;
- case VS::ARRAY_BONES: {
- glVertexAttribIPointer(i, 4, GL_UNSIGNED_INT, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 4 * 4;
-
- } break;
- case VS::ARRAY_WEIGHTS: {
- glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(ofs));
- ofs += 4 * 4;
-
- } break;
- }
-
- } else {
- glDisableVertexAttribArray(i);
- }
- }
-
- if (s->index_array_len) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id);
- }
-}
-
-/* MULTIMESH API */
-
-RID RasterizerStorageGLES3::multimesh_create() {
-
- MultiMesh *multimesh = memnew(MultiMesh);
- return multimesh_owner.make_rid(multimesh);
-}
-
-void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data_format) {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND(!multimesh);
-
- if (multimesh->size == p_instances && multimesh->transform_format == p_transform_format && multimesh->color_format == p_color_format && multimesh->custom_data_format == p_data_format)
- return;
-
- if (multimesh->buffer) {
- glDeleteBuffers(1, &multimesh->buffer);
- multimesh->data.resize(0);
- multimesh->buffer = 0;
- }
-
- multimesh->size = p_instances;
- multimesh->transform_format = p_transform_format;
- multimesh->color_format = p_color_format;
- multimesh->custom_data_format = p_data_format;
-
- if (multimesh->size) {
-
- if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) {
- multimesh->xform_floats = 8;
- } else {
- multimesh->xform_floats = 12;
- }
-
- if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
- multimesh->color_floats = 1;
- } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
- multimesh->color_floats = 4;
- } else {
- multimesh->color_floats = 0;
- }
-
- if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
- multimesh->custom_data_floats = 1;
- } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
- multimesh->custom_data_floats = 4;
- } else {
- multimesh->custom_data_floats = 0;
- }
-
- int format_floats = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
-
- multimesh->data.resize(format_floats * p_instances);
-
- float *dataptr = multimesh->data.ptrw();
-
- for (int i = 0; i < p_instances * format_floats; i += format_floats) {
-
- int color_from = 0;
- int custom_data_from = 0;
-
- if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) {
- dataptr[i + 0] = 1.0;
- dataptr[i + 1] = 0.0;
- dataptr[i + 2] = 0.0;
- dataptr[i + 3] = 0.0;
- dataptr[i + 4] = 0.0;
- dataptr[i + 5] = 1.0;
- dataptr[i + 6] = 0.0;
- dataptr[i + 7] = 0.0;
- color_from = 8;
- custom_data_from = 8;
- } else {
- dataptr[i + 0] = 1.0;
- dataptr[i + 1] = 0.0;
- dataptr[i + 2] = 0.0;
- dataptr[i + 3] = 0.0;
- dataptr[i + 4] = 0.0;
- dataptr[i + 5] = 1.0;
- dataptr[i + 6] = 0.0;
- dataptr[i + 7] = 0.0;
- dataptr[i + 8] = 0.0;
- dataptr[i + 9] = 0.0;
- dataptr[i + 10] = 1.0;
- dataptr[i + 11] = 0.0;
- color_from = 12;
- custom_data_from = 12;
- }
-
- if (multimesh->color_format == VS::MULTIMESH_COLOR_NONE) {
- //none
- } else if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
-
- union {
- uint32_t colu;
- float colf;
- } cu;
-
- cu.colu = 0xFFFFFFFF;
- dataptr[i + color_from + 0] = cu.colf;
- custom_data_from = color_from + 1;
-
- } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
- dataptr[i + color_from + 0] = 1.0;
- dataptr[i + color_from + 1] = 1.0;
- dataptr[i + color_from + 2] = 1.0;
- dataptr[i + color_from + 3] = 1.0;
- custom_data_from = color_from + 4;
- }
-
- if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE) {
- //none
- } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
-
- union {
- uint32_t colu;
- float colf;
- } cu;
-
- cu.colu = 0;
- dataptr[i + custom_data_from + 0] = cu.colf;
-
- } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
- dataptr[i + custom_data_from + 0] = 0.0;
- dataptr[i + custom_data_from + 1] = 0.0;
- dataptr[i + custom_data_from + 2] = 0.0;
- dataptr[i + custom_data_from + 3] = 0.0;
- }
- }
-
- glGenBuffers(1, &multimesh->buffer);
- glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
- glBufferData(GL_ARRAY_BUFFER, multimesh->data.size() * sizeof(float), NULL, GL_STATIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
-
- multimesh->dirty_data = true;
- multimesh->dirty_aabb = true;
-
- if (!multimesh->update_list.in_list()) {
- multimesh_update_list.add(&multimesh->update_list);
- }
-}
-
-int RasterizerStorageGLES3::multimesh_get_instance_count(RID p_multimesh) const {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, 0);
-
- return multimesh->size;
-}
-
-void RasterizerStorageGLES3::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND(!multimesh);
-
- if (multimesh->mesh.is_valid()) {
- Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
- if (mesh) {
- mesh->multimeshes.remove(&multimesh->mesh_list);
- }
- }
-
- multimesh->mesh = p_mesh;
-
- if (multimesh->mesh.is_valid()) {
- Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
- if (mesh) {
- mesh->multimeshes.add(&multimesh->mesh_list);
- }
- }
-
- multimesh->dirty_aabb = true;
-
- if (!multimesh->update_list.in_list()) {
- multimesh_update_list.add(&multimesh->update_list);
- }
-}
-
-void RasterizerStorageGLES3::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->size);
- ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D);
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- float *dataptr = &multimesh->data.write[stride * p_index];
-
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
- dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
- dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
- dataptr[11] = p_transform.origin.z;
-
- multimesh->dirty_data = true;
- multimesh->dirty_aabb = true;
-
- if (!multimesh->update_list.in_list()) {
- multimesh_update_list.add(&multimesh->update_list);
- }
-}
-
-void RasterizerStorageGLES3::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->size);
- ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D);
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- float *dataptr = &multimesh->data.write[stride * p_index];
-
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
- dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
- dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
-
- multimesh->dirty_data = true;
- multimesh->dirty_aabb = true;
-
- if (!multimesh->update_list.in_list()) {
- multimesh_update_list.add(&multimesh->update_list);
- }
-}
-void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->size);
- ERR_FAIL_COND(multimesh->color_format == VS::MULTIMESH_COLOR_NONE);
- ERR_FAIL_INDEX(multimesh->color_format, VS::MULTIMESH_COLOR_MAX);
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats];
-
- if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
-
- uint8_t *data8 = (uint8_t *)dataptr;
- data8[0] = CLAMP(p_color.r * 255.0, 0, 255);
- data8[1] = CLAMP(p_color.g * 255.0, 0, 255);
- data8[2] = CLAMP(p_color.b * 255.0, 0, 255);
- data8[3] = CLAMP(p_color.a * 255.0, 0, 255);
-
- } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
- }
-
- multimesh->dirty_data = true;
- multimesh->dirty_aabb = true;
-
- if (!multimesh->update_list.in_list()) {
- multimesh_update_list.add(&multimesh->update_list);
- }
-}
-
-void RasterizerStorageGLES3::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_custom_data) {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->size);
- ERR_FAIL_COND(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE);
- ERR_FAIL_INDEX(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX);
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
-
- if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
-
- uint8_t *data8 = (uint8_t *)dataptr;
- data8[0] = CLAMP(p_custom_data.r * 255.0, 0, 255);
- data8[1] = CLAMP(p_custom_data.g * 255.0, 0, 255);
- data8[2] = CLAMP(p_custom_data.b * 255.0, 0, 255);
- data8[3] = CLAMP(p_custom_data.a * 255.0, 0, 255);
-
- } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
- dataptr[0] = p_custom_data.r;
- dataptr[1] = p_custom_data.g;
- dataptr[2] = p_custom_data.b;
- dataptr[3] = p_custom_data.a;
- }
-
- multimesh->dirty_data = true;
- multimesh->dirty_aabb = true;
-
- if (!multimesh->update_list.in_list()) {
- multimesh_update_list.add(&multimesh->update_list);
- }
-}
-RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, RID());
-
- return multimesh->mesh;
-}
-
-Transform RasterizerStorageGLES3::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform());
- ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform());
- ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D, Transform());
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- float *dataptr = &multimesh->data.write[stride * p_index];
-
- Transform xform;
-
- xform.basis.elements[0][0] = dataptr[0];
- xform.basis.elements[0][1] = dataptr[1];
- xform.basis.elements[0][2] = dataptr[2];
- xform.origin.x = dataptr[3];
- xform.basis.elements[1][0] = dataptr[4];
- xform.basis.elements[1][1] = dataptr[5];
- xform.basis.elements[1][2] = dataptr[6];
- xform.origin.y = dataptr[7];
- xform.basis.elements[2][0] = dataptr[8];
- xform.basis.elements[2][1] = dataptr[9];
- xform.basis.elements[2][2] = dataptr[10];
- xform.origin.z = dataptr[11];
-
- return xform;
-}
-Transform2D RasterizerStorageGLES3::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform2D());
- ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform2D());
- ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D, Transform2D());
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- float *dataptr = &multimesh->data.write[stride * p_index];
-
- Transform2D xform;
-
- xform.elements[0][0] = dataptr[0];
- xform.elements[1][0] = dataptr[1];
- xform.elements[2][0] = dataptr[3];
- xform.elements[0][1] = dataptr[4];
- xform.elements[1][1] = dataptr[5];
- xform.elements[2][1] = dataptr[7];
-
- return xform;
-}
-
-Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Color());
- ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
- ERR_FAIL_COND_V(multimesh->color_format == VS::MULTIMESH_COLOR_NONE, Color());
- ERR_FAIL_INDEX_V(multimesh->color_format, VS::MULTIMESH_COLOR_MAX, Color());
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats];
-
- if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) {
- union {
- uint32_t colu;
- float colf;
- } cu;
-
- cu.colf = dataptr[0];
-
- return Color::hex(BSWAP32(cu.colu));
-
- } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
- Color c;
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
-
- return c;
- }
-
- return Color();
-}
-
-Color RasterizerStorageGLES3::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Color());
- ERR_FAIL_INDEX_V(p_index, multimesh->size, Color());
- ERR_FAIL_COND_V(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE, Color());
- ERR_FAIL_INDEX_V(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX, Color());
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats];
-
- if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) {
- union {
- uint32_t colu;
- float colf;
- } cu;
-
- cu.colf = dataptr[0];
-
- return Color::hex(BSWAP32(cu.colu));
-
- } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
- Color c;
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
-
- return c;
- }
-
- return Color();
-}
-
-void RasterizerStorageGLES3::multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector &p_array) {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(!multimesh->data.ptr());
-
- int dsize = multimesh->data.size();
-
- ERR_FAIL_COND(dsize != p_array.size());
-
- PoolVector::Read r = p_array.read();
- copymem(multimesh->data.ptrw(), r.ptr(), dsize * sizeof(float));
-
- multimesh->dirty_data = true;
- multimesh->dirty_aabb = true;
-
- if (!multimesh->update_list.in_list()) {
- multimesh_update_list.add(&multimesh->update_list);
- }
-}
-
-void RasterizerStorageGLES3::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND(!multimesh);
-
- multimesh->visible_instances = p_visible;
-}
-int RasterizerStorageGLES3::multimesh_get_visible_instances(RID p_multimesh) const {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, -1);
-
- return multimesh->visible_instances;
-}
-
-AABB RasterizerStorageGLES3::multimesh_get_aabb(RID p_multimesh) const {
-
- MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, AABB());
-
- const_cast(this)->update_dirty_multimeshes(); //update pending AABBs
-
- return multimesh->aabb;
-}
-
-void RasterizerStorageGLES3::update_dirty_multimeshes() {
-
- while (multimesh_update_list.first()) {
-
- MultiMesh *multimesh = multimesh_update_list.first()->self();
-
- if (multimesh->size && multimesh->dirty_data) {
-
- glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
- glBufferSubData(GL_ARRAY_BUFFER, 0, multimesh->data.size() * sizeof(float), multimesh->data.ptr());
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
-
- if (multimesh->size && multimesh->dirty_aabb) {
-
- AABB mesh_aabb;
-
- if (multimesh->mesh.is_valid()) {
- mesh_aabb = mesh_get_aabb(multimesh->mesh, RID());
- } else {
- mesh_aabb.size += Vector3(0.001, 0.001, 0.001);
- }
-
- int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats;
- int count = multimesh->data.size();
- float *data = multimesh->data.ptrw();
-
- AABB aabb;
-
- if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) {
-
- for (int i = 0; i < count; i += stride) {
-
- float *dataptr = &data[i];
- Transform xform;
- xform.basis[0][0] = dataptr[0];
- xform.basis[0][1] = dataptr[1];
- xform.origin[0] = dataptr[3];
- xform.basis[1][0] = dataptr[4];
- xform.basis[1][1] = dataptr[5];
- xform.origin[1] = dataptr[7];
-
- AABB laabb = xform.xform(mesh_aabb);
- if (i == 0)
- aabb = laabb;
- else
- aabb.merge_with(laabb);
- }
- } else {
-
- for (int i = 0; i < count; i += stride) {
-
- float *dataptr = &data[i];
- Transform xform;
-
- xform.basis.elements[0][0] = dataptr[0];
- xform.basis.elements[0][1] = dataptr[1];
- xform.basis.elements[0][2] = dataptr[2];
- xform.origin.x = dataptr[3];
- xform.basis.elements[1][0] = dataptr[4];
- xform.basis.elements[1][1] = dataptr[5];
- xform.basis.elements[1][2] = dataptr[6];
- xform.origin.y = dataptr[7];
- xform.basis.elements[2][0] = dataptr[8];
- xform.basis.elements[2][1] = dataptr[9];
- xform.basis.elements[2][2] = dataptr[10];
- xform.origin.z = dataptr[11];
-
- AABB laabb = xform.xform(mesh_aabb);
- if (i == 0)
- aabb = laabb;
- else
- aabb.merge_with(laabb);
- }
- }
-
- multimesh->aabb = aabb;
- }
- multimesh->dirty_aabb = false;
- multimesh->dirty_data = false;
-
- multimesh->instance_change_notify(true, false);
-
- multimesh_update_list.remove(multimesh_update_list.first());
- }
-}
-
-/* IMMEDIATE API */
-
-RID RasterizerStorageGLES3::immediate_create() {
-
- Immediate *im = memnew(Immediate);
- return immediate_owner.make_rid(im);
-}
-
-void RasterizerStorageGLES3::immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, RID p_texture) {
-
- ERR_FAIL_INDEX(p_primitive, (int)VS::PRIMITIVE_MAX);
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(im->building);
-
- Immediate::Chunk ic;
- ic.texture = p_texture;
- ic.primitive = p_primitive;
- im->chunks.push_back(ic);
- im->mask = 0;
- im->building = true;
-}
-void RasterizerStorageGLES3::immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(!im->building);
-
- Immediate::Chunk *c = &im->chunks.back()->get();
-
- if (c->vertices.empty() && im->chunks.size() == 1) {
-
- im->aabb.position = p_vertex;
- im->aabb.size = Vector3();
- } else {
- im->aabb.expand_to(p_vertex);
- }
-
- if (im->mask & VS::ARRAY_FORMAT_NORMAL)
- c->normals.push_back(chunk_normal);
- if (im->mask & VS::ARRAY_FORMAT_TANGENT)
- c->tangents.push_back(chunk_tangent);
- if (im->mask & VS::ARRAY_FORMAT_COLOR)
- c->colors.push_back(chunk_color);
- if (im->mask & VS::ARRAY_FORMAT_TEX_UV)
- c->uvs.push_back(chunk_uv);
- if (im->mask & VS::ARRAY_FORMAT_TEX_UV2)
- c->uvs2.push_back(chunk_uv2);
- im->mask |= VS::ARRAY_FORMAT_VERTEX;
- c->vertices.push_back(p_vertex);
-}
-
-void RasterizerStorageGLES3::immediate_normal(RID p_immediate, const Vector3 &p_normal) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(!im->building);
-
- im->mask |= VS::ARRAY_FORMAT_NORMAL;
- chunk_normal = p_normal;
-}
-void RasterizerStorageGLES3::immediate_tangent(RID p_immediate, const Plane &p_tangent) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(!im->building);
-
- im->mask |= VS::ARRAY_FORMAT_TANGENT;
- chunk_tangent = p_tangent;
-}
-void RasterizerStorageGLES3::immediate_color(RID p_immediate, const Color &p_color) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(!im->building);
-
- im->mask |= VS::ARRAY_FORMAT_COLOR;
- chunk_color = p_color;
-}
-void RasterizerStorageGLES3::immediate_uv(RID p_immediate, const Vector2 &tex_uv) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(!im->building);
-
- im->mask |= VS::ARRAY_FORMAT_TEX_UV;
- chunk_uv = tex_uv;
-}
-void RasterizerStorageGLES3::immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(!im->building);
-
- im->mask |= VS::ARRAY_FORMAT_TEX_UV2;
- chunk_uv2 = tex_uv;
-}
-
-void RasterizerStorageGLES3::immediate_end(RID p_immediate) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(!im->building);
-
- im->building = false;
-
- im->instance_change_notify(true, false);
-}
-void RasterizerStorageGLES3::immediate_clear(RID p_immediate) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- ERR_FAIL_COND(im->building);
-
- im->chunks.clear();
- im->instance_change_notify(true, false);
-}
-
-AABB RasterizerStorageGLES3::immediate_get_aabb(RID p_immediate) const {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND_V(!im, AABB());
- return im->aabb;
-}
-
-void RasterizerStorageGLES3::immediate_set_material(RID p_immediate, RID p_material) {
-
- Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND(!im);
- im->material = p_material;
- im->instance_change_notify(false, true);
-}
-
-RID RasterizerStorageGLES3::immediate_get_material(RID p_immediate) const {
-
- const Immediate *im = immediate_owner.getornull(p_immediate);
- ERR_FAIL_COND_V(!im, RID());
- return im->material;
-}
-
-/* SKELETON API */
-
-RID RasterizerStorageGLES3::skeleton_create() {
-
- Skeleton *skeleton = memnew(Skeleton);
-
- glGenTextures(1, &skeleton->texture);
-
- return skeleton_owner.make_rid(skeleton);
-}
-
-void RasterizerStorageGLES3::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_COND(p_bones < 0);
-
- if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton)
- return;
-
- skeleton->size = p_bones;
- skeleton->use_2d = p_2d_skeleton;
-
- int height = p_bones / 256;
- if (p_bones % 256)
- height++;
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, skeleton->texture);
-
- if (skeleton->use_2d) {
- skeleton->skel_texture.resize(256 * height * 2 * 4);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, height * 2, 0, GL_RGBA, GL_FLOAT, NULL);
- } else {
- skeleton->skel_texture.resize(256 * height * 3 * 4);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, height * 3, 0, GL_RGBA, GL_FLOAT, NULL);
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- if (!skeleton->update_list.in_list()) {
- skeleton_update_list.add(&skeleton->update_list);
- }
-}
-int RasterizerStorageGLES3::skeleton_get_bone_count(RID p_skeleton) const {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
- ERR_FAIL_COND_V(!skeleton, 0);
-
- return skeleton->size;
-}
-
-void RasterizerStorageGLES3::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
-
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX(p_bone, skeleton->size);
- ERR_FAIL_COND(skeleton->use_2d);
-
- float *texture = skeleton->skel_texture.ptrw();
-
- int base_ofs = ((p_bone / 256) * 256) * 3 * 4 + (p_bone % 256) * 4;
-
- texture[base_ofs + 0] = p_transform.basis[0].x;
- texture[base_ofs + 1] = p_transform.basis[0].y;
- texture[base_ofs + 2] = p_transform.basis[0].z;
- texture[base_ofs + 3] = p_transform.origin.x;
- base_ofs += 256 * 4;
- texture[base_ofs + 0] = p_transform.basis[1].x;
- texture[base_ofs + 1] = p_transform.basis[1].y;
- texture[base_ofs + 2] = p_transform.basis[1].z;
- texture[base_ofs + 3] = p_transform.origin.y;
- base_ofs += 256 * 4;
- texture[base_ofs + 0] = p_transform.basis[2].x;
- texture[base_ofs + 1] = p_transform.basis[2].y;
- texture[base_ofs + 2] = p_transform.basis[2].z;
- texture[base_ofs + 3] = p_transform.origin.z;
-
- if (!skeleton->update_list.in_list()) {
- skeleton_update_list.add(&skeleton->update_list);
- }
-}
-
-Transform RasterizerStorageGLES3::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
-
- ERR_FAIL_COND_V(!skeleton, Transform());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform());
- ERR_FAIL_COND_V(skeleton->use_2d, Transform());
-
- const float *texture = skeleton->skel_texture.ptr();
-
- Transform ret;
-
- int base_ofs = ((p_bone / 256) * 256) * 3 * 4 + (p_bone % 256) * 4;
-
- ret.basis[0].x = texture[base_ofs + 0];
- ret.basis[0].y = texture[base_ofs + 1];
- ret.basis[0].z = texture[base_ofs + 2];
- ret.origin.x = texture[base_ofs + 3];
- base_ofs += 256 * 4;
- ret.basis[1].x = texture[base_ofs + 0];
- ret.basis[1].y = texture[base_ofs + 1];
- ret.basis[1].z = texture[base_ofs + 2];
- ret.origin.y = texture[base_ofs + 3];
- base_ofs += 256 * 4;
- ret.basis[2].x = texture[base_ofs + 0];
- ret.basis[2].y = texture[base_ofs + 1];
- ret.basis[2].z = texture[base_ofs + 2];
- ret.origin.z = texture[base_ofs + 3];
-
- return ret;
-}
-void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
-
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX(p_bone, skeleton->size);
- ERR_FAIL_COND(!skeleton->use_2d);
-
- float *texture = skeleton->skel_texture.ptrw();
-
- int base_ofs = ((p_bone / 256) * 256) * 2 * 4 + (p_bone % 256) * 4;
-
- texture[base_ofs + 0] = p_transform[0][0];
- texture[base_ofs + 1] = p_transform[1][0];
- texture[base_ofs + 2] = 0;
- texture[base_ofs + 3] = p_transform[2][0];
- base_ofs += 256 * 4;
- texture[base_ofs + 0] = p_transform[0][1];
- texture[base_ofs + 1] = p_transform[1][1];
- texture[base_ofs + 2] = 0;
- texture[base_ofs + 3] = p_transform[2][1];
-
- if (!skeleton->update_list.in_list()) {
- skeleton_update_list.add(&skeleton->update_list);
- }
-}
-Transform2D RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
-
- ERR_FAIL_COND_V(!skeleton, Transform2D());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
- ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
-
- const float *texture = skeleton->skel_texture.ptr();
-
- Transform2D ret;
-
- int base_ofs = ((p_bone / 256) * 256) * 2 * 4 + (p_bone % 256) * 4;
-
- ret[0][0] = texture[base_ofs + 0];
- ret[1][0] = texture[base_ofs + 1];
- ret[2][0] = texture[base_ofs + 3];
- base_ofs += 256 * 4;
- ret[0][1] = texture[base_ofs + 0];
- ret[1][1] = texture[base_ofs + 1];
- ret[2][1] = texture[base_ofs + 3];
-
- return ret;
-}
-
-void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
-
- ERR_FAIL_COND(!skeleton->use_2d);
-
- skeleton->base_transform_2d = p_base_transform;
-}
-
-void RasterizerStorageGLES3::update_dirty_skeletons() {
-
- glActiveTexture(GL_TEXTURE0);
-
- while (skeleton_update_list.first()) {
-
- Skeleton *skeleton = skeleton_update_list.first()->self();
- if (skeleton->size) {
-
- int height = skeleton->size / 256;
- if (skeleton->size % 256)
- height++;
-
- glBindTexture(GL_TEXTURE_2D, skeleton->texture);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, height * (skeleton->use_2d ? 2 : 3), GL_RGBA, GL_FLOAT, skeleton->skel_texture.ptr());
- }
-
- for (Set::Element *E = skeleton->instances.front(); E; E = E->next()) {
- E->get()->base_changed(true, false);
- }
-
- skeleton_update_list.remove(skeleton_update_list.first());
- }
-}
-
-/* Light API */
-
-RID RasterizerStorageGLES3::light_create(VS::LightType p_type) {
-
- Light *light = memnew(Light);
- light->type = p_type;
-
- light->param[VS::LIGHT_PARAM_ENERGY] = 1.0;
- light->param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
- light->param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
- light->param[VS::LIGHT_PARAM_RANGE] = 1.0;
- light->param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
- light->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45;
- light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
- light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
- light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
- light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
- light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
- light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
-
- light->color = Color(1, 1, 1, 1);
- light->shadow = false;
- light->negative = false;
- light->cull_mask = 0xFFFFFFFF;
- light->directional_shadow_mode = VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
- light->omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
- light->omni_shadow_detail = VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL;
- light->directional_blend_splits = false;
- light->directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
- light->reverse_cull = false;
- light->use_gi = true;
- light->version = 0;
-
- return light_owner.make_rid(light);
-}
-
-void RasterizerStorageGLES3::light_set_color(RID p_light, const Color &p_color) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->color = p_color;
-}
-void RasterizerStorageGLES3::light_set_param(RID p_light, VS::LightParam p_param, float p_value) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
- ERR_FAIL_INDEX(p_param, VS::LIGHT_PARAM_MAX);
-
- switch (p_param) {
- case VS::LIGHT_PARAM_RANGE:
- case VS::LIGHT_PARAM_SPOT_ANGLE:
- case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
- case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
- case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
- case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
- case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
- case VS::LIGHT_PARAM_SHADOW_BIAS: {
-
- light->version++;
- light->instance_change_notify(true, false);
- } break;
- default: {
- }
- }
-
- light->param[p_param] = p_value;
-}
-void RasterizerStorageGLES3::light_set_shadow(RID p_light, bool p_enabled) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
- light->shadow = p_enabled;
-
- light->version++;
- light->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::light_set_shadow_color(RID p_light, const Color &p_color) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
- light->shadow_color = p_color;
-}
-
-void RasterizerStorageGLES3::light_set_projector(RID p_light, RID p_texture) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->projector = p_texture;
-}
-
-void RasterizerStorageGLES3::light_set_negative(RID p_light, bool p_enable) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->negative = p_enable;
-}
-void RasterizerStorageGLES3::light_set_cull_mask(RID p_light, uint32_t p_mask) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->cull_mask = p_mask;
-
- light->version++;
- light->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->reverse_cull = p_enabled;
-
- light->version++;
- light->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::light_set_use_gi(RID p_light, bool p_enabled) {
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->use_gi = p_enabled;
-
- light->version++;
- light->instance_change_notify(true, false);
-}
-void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->omni_shadow_mode = p_mode;
-
- light->version++;
- light->instance_change_notify(true, false);
-}
-
-VS::LightOmniShadowMode RasterizerStorageGLES3::light_omni_get_shadow_mode(RID p_light) {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI_SHADOW_CUBE);
-
- return light->omni_shadow_mode;
-}
-
-void RasterizerStorageGLES3::light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->omni_shadow_detail = p_detail;
- light->version++;
- light->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_shadow_mode = p_mode;
- light->version++;
- light->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::light_directional_set_blend_splits(RID p_light, bool p_enable) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_blend_splits = p_enable;
- light->version++;
- light->instance_change_notify(true, false);
-}
-
-bool RasterizerStorageGLES3::light_directional_get_blend_splits(RID p_light) const {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, false);
-
- return light->directional_blend_splits;
-}
-
-VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
-
- return light->directional_shadow_mode;
-}
-
-void RasterizerStorageGLES3::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {
-
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_range_mode = p_range_mode;
-}
-
-VS::LightDirectionalShadowDepthRangeMode RasterizerStorageGLES3::light_directional_get_shadow_depth_range_mode(RID p_light) const {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
-
- return light->directional_range_mode;
-}
-
-VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
-
- return light->type;
-}
-
-float RasterizerStorageGLES3::light_get_param(RID p_light, VS::LightParam p_param) {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
-
- return light->param[p_param];
-}
-
-Color RasterizerStorageGLES3::light_get_color(RID p_light) {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, Color());
-
- return light->color;
-}
-
-bool RasterizerStorageGLES3::light_get_use_gi(RID p_light) {
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, false);
-
- return light->use_gi;
-}
-
-bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
-
- return light->shadow;
-}
-
-uint64_t RasterizerStorageGLES3::light_get_version(RID p_light) const {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->version;
-}
-
-AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
-
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, AABB());
-
- switch (light->type) {
-
- case VS::LIGHT_SPOT: {
-
- float len = light->param[VS::LIGHT_PARAM_RANGE];
- float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len;
- return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
- };
- case VS::LIGHT_OMNI: {
-
- float r = light->param[VS::LIGHT_PARAM_RANGE];
- return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
- };
- case VS::LIGHT_DIRECTIONAL: {
-
- return AABB();
- };
- }
-
- ERR_FAIL_V(AABB());
-}
-
-/* PROBE API */
-
-RID RasterizerStorageGLES3::reflection_probe_create() {
-
- ReflectionProbe *reflection_probe = memnew(ReflectionProbe);
-
- reflection_probe->intensity = 1.0;
- reflection_probe->interior_ambient = Color();
- reflection_probe->interior_ambient_energy = 1.0;
- reflection_probe->interior_ambient_probe_contrib = 0.0;
-
- reflection_probe->max_distance = 0;
- reflection_probe->extents = Vector3(1, 1, 1);
- reflection_probe->origin_offset = Vector3(0, 0, 0);
- reflection_probe->interior = false;
- reflection_probe->box_projection = false;
- reflection_probe->enable_shadows = false;
- reflection_probe->cull_mask = (1 << 20) - 1;
- reflection_probe->update_mode = VS::REFLECTION_PROBE_UPDATE_ONCE;
-
- return reflection_probe_owner.make_rid(reflection_probe);
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->update_mode = p_mode;
- reflection_probe->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->intensity = p_intensity;
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->interior_ambient = p_ambient;
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->interior_ambient_energy = p_energy;
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->interior_ambient_probe_contrib = p_contrib;
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->max_distance = p_distance;
- reflection_probe->instance_change_notify(true, false);
-}
-void RasterizerStorageGLES3::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->extents = p_extents;
- reflection_probe->instance_change_notify(true, false);
-}
-void RasterizerStorageGLES3::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->origin_offset = p_offset;
- reflection_probe->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->interior = p_enable;
- reflection_probe->instance_change_notify(true, false);
-}
-void RasterizerStorageGLES3::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->box_projection = p_enable;
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->enable_shadows = p_enable;
- reflection_probe->instance_change_notify(true, false);
-}
-void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
-
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->cull_mask = p_layers;
- reflection_probe->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
-}
-
-AABB RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, AABB());
-
- AABB aabb;
- aabb.position = -reflection_probe->extents;
- aabb.size = reflection_probe->extents * 2.0;
-
- return aabb;
-}
-VS::ReflectionProbeUpdateMode RasterizerStorageGLES3::reflection_probe_get_update_mode(RID p_probe) const {
-
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS);
-
- return reflection_probe->update_mode;
-}
-
-uint32_t RasterizerStorageGLES3::reflection_probe_get_cull_mask(RID p_probe) const {
-
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->cull_mask;
-}
-
-Vector3 RasterizerStorageGLES3::reflection_probe_get_extents(RID p_probe) const {
-
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Vector3());
-
- return reflection_probe->extents;
-}
-Vector3 RasterizerStorageGLES3::reflection_probe_get_origin_offset(RID p_probe) const {
-
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Vector3());
-
- return reflection_probe->origin_offset;
-}
-
-bool RasterizerStorageGLES3::reflection_probe_renders_shadows(RID p_probe) const {
-
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, false);
-
- return reflection_probe->enable_shadows;
-}
-
-float RasterizerStorageGLES3::reflection_probe_get_origin_max_distance(RID p_probe) const {
-
- const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->max_distance;
-}
-
-RID RasterizerStorageGLES3::gi_probe_create() {
-
- GIProbe *gip = memnew(GIProbe);
-
- gip->bounds = AABB(Vector3(), Vector3(1, 1, 1));
- gip->dynamic_range = 1.0;
- gip->energy = 1.0;
- gip->propagation = 1.0;
- gip->bias = 0.4;
- gip->normal_bias = 0.4;
- gip->interior = false;
- gip->compress = false;
- gip->version = 1;
- gip->cell_size = 1.0;
-
- return gi_probe_owner.make_rid(gip);
-}
-
-void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->bounds = p_bounds;
- gip->version++;
- gip->instance_change_notify(true, false);
-}
-AABB RasterizerStorageGLES3::gi_probe_get_bounds(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, AABB());
-
- return gip->bounds;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_cell_size(RID p_probe, float p_size) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->cell_size = p_size;
- gip->version++;
- gip->instance_change_notify(true, false);
-}
-
-float RasterizerStorageGLES3::gi_probe_get_cell_size(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, 0);
-
- return gip->cell_size;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->to_cell = p_xform;
-}
-
-Transform RasterizerStorageGLES3::gi_probe_get_to_cell_xform(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, Transform());
-
- return gip->to_cell;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_dynamic_data(RID p_probe, const PoolVector &p_data) {
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->dynamic_data = p_data;
- gip->version++;
- gip->instance_change_notify(true, false);
-}
-PoolVector RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, PoolVector());
-
- return gip->dynamic_data;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe, int p_range) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->dynamic_range = p_range;
-}
-int RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, 0);
-
- return gip->dynamic_range;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_energy(RID p_probe, float p_range) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->energy = p_range;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_bias(RID p_probe, float p_range) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->bias = p_range;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_normal_bias(RID p_probe, float p_range) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->normal_bias = p_range;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_propagation(RID p_probe, float p_range) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->propagation = p_range;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_interior(RID p_probe, bool p_enable) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->interior = p_enable;
-}
-
-bool RasterizerStorageGLES3::gi_probe_is_interior(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, false);
-
- return gip->interior;
-}
-
-void RasterizerStorageGLES3::gi_probe_set_compress(RID p_probe, bool p_enable) {
-
- GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND(!gip);
-
- gip->compress = p_enable;
-}
-
-bool RasterizerStorageGLES3::gi_probe_is_compressed(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, false);
-
- return gip->compress;
-}
-float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, 0);
-
- return gip->energy;
-}
-
-float RasterizerStorageGLES3::gi_probe_get_bias(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, 0);
-
- return gip->bias;
-}
-
-float RasterizerStorageGLES3::gi_probe_get_normal_bias(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, 0);
-
- return gip->normal_bias;
-}
-
-float RasterizerStorageGLES3::gi_probe_get_propagation(RID p_probe) const {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, 0);
-
- return gip->propagation;
-}
-
-uint32_t RasterizerStorageGLES3::gi_probe_get_version(RID p_probe) {
-
- const GIProbe *gip = gi_probe_owner.getornull(p_probe);
- ERR_FAIL_COND_V(!gip, 0);
-
- return gip->version;
-}
-
-RasterizerStorage::GIProbeCompression RasterizerStorageGLES3::gi_probe_get_dynamic_data_get_preferred_compression() const {
- if (config.s3tc_supported) {
- return GI_PROBE_S3TC;
- } else {
- return GI_PROBE_UNCOMPRESSED;
- }
-}
-
-RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) {
-
- GIProbeData *gipd = memnew(GIProbeData);
-
- gipd->width = p_width;
- gipd->height = p_height;
- gipd->depth = p_depth;
- gipd->compression = p_compression;
-
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &gipd->tex_id);
- glBindTexture(GL_TEXTURE_3D, gipd->tex_id);
-
- int level = 0;
- int min_size = 1;
-
- if (gipd->compression == GI_PROBE_S3TC) {
- min_size = 4;
- }
-
- while (true) {
-
- if (gipd->compression == GI_PROBE_S3TC) {
- int size = p_width * p_height * p_depth;
- glCompressedTexImage3D(GL_TEXTURE_3D, level, _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT, p_width, p_height, p_depth, 0, size, NULL);
- } else {
- glTexImage3D(GL_TEXTURE_3D, level, GL_RGBA8, p_width, p_height, p_depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
-
- if (p_width <= min_size || p_height <= min_size || p_depth <= min_size)
- break;
- p_width >>= 1;
- p_height >>= 1;
- p_depth >>= 1;
- level++;
- }
-
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, level);
-
- gipd->levels = level + 1;
-
- return gi_probe_data_owner.make_rid(gipd);
-}
-
-void RasterizerStorageGLES3::gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) {
-
- GIProbeData *gipd = gi_probe_data_owner.getornull(p_gi_probe_data);
- ERR_FAIL_COND(!gipd);
- /*
- Vector data;
- data.resize((gipd->width>>p_mipmap)*(gipd->height>>p_mipmap)*(gipd->depth>>p_mipmap)*4);
-
- for(int i=0;i<(gipd->width>>p_mipmap);i++) {
- for(int j=0;j<(gipd->height>>p_mipmap);j++) {
- for(int k=0;k<(gipd->depth>>p_mipmap);k++) {
-
- int ofs = (k*(gipd->height>>p_mipmap)*(gipd->width>>p_mipmap)) + j *(gipd->width>>p_mipmap) + i;
- ofs*=4;
- data[ofs+0]=i*0xFF/(gipd->width>>p_mipmap);
- data[ofs+1]=j*0xFF/(gipd->height>>p_mipmap);
- data[ofs+2]=k*0xFF/(gipd->depth>>p_mipmap);
- data[ofs+3]=0xFF;
- }
- }
- }
-*/
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_3D, gipd->tex_id);
- if (gipd->compression == GI_PROBE_S3TC) {
- int size = (gipd->width >> p_mipmap) * (gipd->height >> p_mipmap) * p_slice_count;
- glCompressedTexSubImage3D(GL_TEXTURE_3D, p_mipmap, 0, 0, p_depth_slice, gipd->width >> p_mipmap, gipd->height >> p_mipmap, p_slice_count, _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT, size, p_data);
- } else {
- glTexSubImage3D(GL_TEXTURE_3D, p_mipmap, 0, 0, p_depth_slice, gipd->width >> p_mipmap, gipd->height >> p_mipmap, p_slice_count, GL_RGBA, GL_UNSIGNED_BYTE, p_data);
- }
- //glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,p_data);
- //glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr());
-}
-/////////////////////////////
-
-RID RasterizerStorageGLES3::lightmap_capture_create() {
-
- LightmapCapture *capture = memnew(LightmapCapture);
- return lightmap_capture_data_owner.make_rid(capture);
-}
-
-void RasterizerStorageGLES3::lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {
-
- LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND(!capture);
- capture->bounds = p_bounds;
- capture->instance_change_notify(true, false);
-}
-AABB RasterizerStorageGLES3::lightmap_capture_get_bounds(RID p_capture) const {
-
- const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND_V(!capture, AABB());
- return capture->bounds;
-}
-void RasterizerStorageGLES3::lightmap_capture_set_octree(RID p_capture, const PoolVector &p_octree) {
-
- LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND(!capture);
-
- ERR_FAIL_COND(p_octree.size() == 0 || (p_octree.size() % sizeof(LightmapCaptureOctree)) != 0);
-
- capture->octree.resize(p_octree.size() / sizeof(LightmapCaptureOctree));
- if (p_octree.size()) {
- PoolVector::Write w = capture->octree.write();
- PoolVector::Read r = p_octree.read();
- copymem(w.ptr(), r.ptr(), p_octree.size());
- }
- capture->instance_change_notify(true, false);
-}
-PoolVector RasterizerStorageGLES3::lightmap_capture_get_octree(RID p_capture) const {
-
- const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND_V(!capture, PoolVector());
-
- if (capture->octree.size() == 0)
- return PoolVector();
-
- PoolVector ret;
- ret.resize(capture->octree.size() * sizeof(LightmapCaptureOctree));
- {
- PoolVector::Read r = capture->octree.read();
- PoolVector::Write w = ret.write();
- copymem(w.ptr(), r.ptr(), ret.size());
- }
-
- return ret;
-}
-
-void RasterizerStorageGLES3::lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {
- LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND(!capture);
- capture->cell_xform = p_xform;
-}
-
-Transform RasterizerStorageGLES3::lightmap_capture_get_octree_cell_transform(RID p_capture) const {
- const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND_V(!capture, Transform());
- return capture->cell_xform;
-}
-
-void RasterizerStorageGLES3::lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) {
- LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND(!capture);
- capture->cell_subdiv = p_subdiv;
-}
-
-int RasterizerStorageGLES3::lightmap_capture_get_octree_cell_subdiv(RID p_capture) const {
- const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND_V(!capture, 0);
- return capture->cell_subdiv;
-}
-
-void RasterizerStorageGLES3::lightmap_capture_set_energy(RID p_capture, float p_energy) {
-
- LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND(!capture);
- capture->energy = p_energy;
-}
-
-float RasterizerStorageGLES3::lightmap_capture_get_energy(RID p_capture) const {
-
- const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND_V(!capture, 0);
- return capture->energy;
-}
-
-const PoolVector *RasterizerStorageGLES3::lightmap_capture_get_octree_ptr(RID p_capture) const {
- const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture);
- ERR_FAIL_COND_V(!capture, NULL);
- return &capture->octree;
-}
-
-///////
-
-RID RasterizerStorageGLES3::particles_create() {
-
- Particles *particles = memnew(Particles);
-
- return particles_owner.make_rid(particles);
-}
-
-void RasterizerStorageGLES3::particles_set_emitting(RID p_particles, bool p_emitting) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->emitting = p_emitting;
-}
-
-bool RasterizerStorageGLES3::particles_get_emitting(RID p_particles) {
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND_V(!particles, false);
-
- return particles->emitting;
-}
-
-void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->amount = p_amount;
-
- int floats = p_amount * 24;
- float *data = memnew_arr(float, floats);
-
- for (int i = 0; i < floats; i++) {
- data[i] = 0;
- }
-
- for (int i = 0; i < 2; i++) {
-
- glBindVertexArray(particles->particle_vaos[i]);
-
- glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[i]);
- glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_STATIC_DRAW);
-
- for (int j = 0; j < 6; j++) {
- glEnableVertexAttribArray(j);
- glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16));
- }
- }
-
- if (particles->histories_enabled) {
-
- for (int i = 0; i < 2; i++) {
- glBindVertexArray(particles->particle_vao_histories[i]);
-
- glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[i]);
- glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_COPY);
-
- for (int j = 0; j < 6; j++) {
- glEnableVertexAttribArray(j);
- glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16));
- }
- particles->particle_valid_histories[i] = false;
- }
- }
-
- glBindVertexArray(0);
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
-
- memdelete_arr(data);
-}
-
-void RasterizerStorageGLES3::particles_set_lifetime(RID p_particles, float p_lifetime) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
- particles->lifetime = p_lifetime;
-}
-
-void RasterizerStorageGLES3::particles_set_one_shot(RID p_particles, bool p_one_shot) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
- particles->one_shot = p_one_shot;
-}
-
-void RasterizerStorageGLES3::particles_set_pre_process_time(RID p_particles, float p_time) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
- particles->pre_process_time = p_time;
-}
-void RasterizerStorageGLES3::particles_set_explosiveness_ratio(RID p_particles, float p_ratio) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
- particles->explosiveness = p_ratio;
-}
-void RasterizerStorageGLES3::particles_set_randomness_ratio(RID p_particles, float p_ratio) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
- particles->randomness = p_ratio;
-}
-
-void RasterizerStorageGLES3::_particles_update_histories(Particles *particles) {
-
- bool needs_histories = particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH;
-
- if (needs_histories == particles->histories_enabled)
- return;
-
- particles->histories_enabled = needs_histories;
-
- int floats = particles->amount * 24;
-
- if (!needs_histories) {
-
- glDeleteBuffers(2, particles->particle_buffer_histories);
- glDeleteVertexArrays(2, particles->particle_vao_histories);
-
- } else {
-
- glGenBuffers(2, particles->particle_buffer_histories);
- glGenVertexArrays(2, particles->particle_vao_histories);
-
- for (int i = 0; i < 2; i++) {
- glBindVertexArray(particles->particle_vao_histories[i]);
-
- glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[i]);
- glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), NULL, GL_DYNAMIC_COPY);
-
- for (int j = 0; j < 6; j++) {
- glEnableVertexAttribArray(j);
- glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, CAST_INT_TO_UCHAR_PTR(j * 16));
- }
-
- particles->particle_valid_histories[i] = false;
- }
- }
-
- particles->clear = true;
-}
-
-void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
- particles->custom_aabb = p_aabb;
- _particles_update_histories(particles);
- particles->instance_change_notify(true, false);
-}
-
-void RasterizerStorageGLES3::particles_set_speed_scale(RID p_particles, float p_scale) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->speed_scale = p_scale;
-}
-void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->use_local_coords = p_enable;
-}
-
-void RasterizerStorageGLES3::particles_set_fixed_fps(RID p_particles, int p_fps) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->fixed_fps = p_fps;
-}
-
-void RasterizerStorageGLES3::particles_set_fractional_delta(RID p_particles, bool p_enable) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->fractional_delta = p_enable;
-}
-
-void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->process_material = p_material;
-}
-
-void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->draw_order = p_order;
- _particles_update_histories(particles);
-}
-
-void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_passes) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->draw_passes.resize(p_passes);
-}
-
-void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
- particles->draw_passes.write[p_pass] = p_mesh;
-}
-
-void RasterizerStorageGLES3::particles_restart(RID p_particles) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->restart_request = true;
-}
-
-void RasterizerStorageGLES3::particles_request_process(RID p_particles) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- if (!particles->particle_element.in_list()) {
- particle_update_list.add(&particles->particle_element);
- }
-}
-
-AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
-
- const Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND_V(!particles, AABB());
-
- const float *data;
- glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]);
-
-#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
- PoolVector vector;
- vector.resize(particles->amount * 16 * 6);
- {
- PoolVector::Write w = vector.write();
- glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, w.ptr());
- }
- PoolVector::Read r = vector.read();
- data = reinterpret_cast(r.ptr());
-#else
- data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT);
-#endif
- AABB aabb;
-
- Transform inv = particles->emission_transform.affine_inverse();
-
- for (int i = 0; i < particles->amount; i++) {
- int ofs = i * 24;
- Vector3 pos = Vector3(data[ofs + 15], data[ofs + 19], data[ofs + 23]);
- if (!particles->use_local_coords) {
- pos = inv.xform(pos);
- }
- if (i == 0)
- aabb.position = pos;
- else
- aabb.expand_to(pos);
- }
-
-#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
- r.release();
- vector = PoolVector();
-#else
- glUnmapBuffer(GL_ARRAY_BUFFER);
-#endif
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- float longest_axis = 0;
- for (int i = 0; i < particles->draw_passes.size(); i++) {
- if (particles->draw_passes[i].is_valid()) {
- AABB maabb = mesh_get_aabb(particles->draw_passes[i], RID());
- longest_axis = MAX(maabb.get_longest_axis_size(), longest_axis);
- }
- }
-
- aabb.grow_by(longest_axis);
-
- return aabb;
-}
-
-AABB RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const {
-
- const Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND_V(!particles, AABB());
-
- return particles->custom_aabb;
-}
-
-void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, const Transform &p_transform) {
-
- Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->emission_transform = p_transform;
-}
-
-int RasterizerStorageGLES3::particles_get_draw_passes(RID p_particles) const {
-
- const Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND_V(!particles, 0);
-
- return particles->draw_passes.size();
-}
-
-RID RasterizerStorageGLES3::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
-
- const Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND_V(!particles, RID());
- ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
-
- return particles->draw_passes[p_pass];
-}
-
-void RasterizerStorageGLES3::_particles_process(Particles *p_particles, float p_delta) {
-
- float new_phase = Math::fmod((float)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, (float)1.0);
-
- 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;
- shaders.particles.set_uniform(ParticlesShaderGLES3::EMITTING, false);
- }
- p_particles->cycle_number++;
- }
-
- shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE, new_phase);
- shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE, p_particles->phase);
- p_particles->phase = new_phase;
-
- shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, p_delta * p_particles->speed_scale);
- shaders.particles.set_uniform(ParticlesShaderGLES3::CLEAR, p_particles->clear);
- glUniform1ui(shaders.particles.get_uniform_location(ParticlesShaderGLES3::RANDOM_SEED), p_particles->random_seed);
-
- if (p_particles->use_local_coords)
- shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, Transform());
- else
- shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, p_particles->emission_transform);
-
- glUniform1ui(shaders.particles.get_uniform(ParticlesShaderGLES3::CYCLE), p_particles->cycle_number);
-
- p_particles->clear = false;
-
- glBindVertexArray(p_particles->particle_vaos[0]);
-
- glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, p_particles->particle_buffers[1]);
-
- // GLint size = 0;
- // glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
-
- glBeginTransformFeedback(GL_POINTS);
- glDrawArrays(GL_POINTS, 0, p_particles->amount);
- glEndTransformFeedback();
-
- SWAP(p_particles->particle_buffers[0], p_particles->particle_buffers[1]);
- SWAP(p_particles->particle_vaos[0], p_particles->particle_vaos[1]);
-
- glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
- glBindVertexArray(0);
- /* //debug particles :D
- glBindBuffer(GL_ARRAY_BUFFER, p_particles->particle_buffers[0]);
-
- float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, p_particles->amount * 16 * 6, GL_MAP_READ_BIT);
- for (int i = 0; i < p_particles->amount; i++) {
- int ofs = i * 24;
- print_line(itos(i) + ":");
- print_line("\tColor: " + Color(data[ofs + 0], data[ofs + 1], data[ofs + 2], data[ofs + 3]));
- print_line("\tVelocity: " + Vector3(data[ofs + 4], data[ofs + 5], data[ofs + 6]));
- print_line("\tActive: " + itos(data[ofs + 7]));
- print_line("\tCustom: " + Color(data[ofs + 8], data[ofs + 9], data[ofs + 10], data[ofs + 11]));
- print_line("\tXF X: " + Color(data[ofs + 12], data[ofs + 13], data[ofs + 14], data[ofs + 15]));
- print_line("\tXF Y: " + Color(data[ofs + 16], data[ofs + 17], data[ofs + 18], data[ofs + 19]));
- print_line("\tXF Z: " + Color(data[ofs + 20], data[ofs + 21], data[ofs + 22], data[ofs + 23]));
- }
-
- glUnmapBuffer(GL_ARRAY_BUFFER);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- //*/
-}
-
-void RasterizerStorageGLES3::update_particles() {
-
- glEnable(GL_RASTERIZER_DISCARD);
-
- while (particle_update_list.first()) {
-
- //use transform feedback to process particles
-
- Particles *particles = particle_update_list.first()->self();
-
- if (particles->restart_request) {
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
- particles->particle_valid_histories[0] = false;
- particles->particle_valid_histories[1] = false;
- particles->restart_request = false;
- }
-
- if (particles->inactive && !particles->emitting) {
-
- particle_update_list.remove(particle_update_list.first());
- continue;
- }
-
- if (particles->emitting) {
- if (particles->inactive) {
- //restart system from scratch
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
- particles->particle_valid_histories[0] = false;
- particles->particle_valid_histories[1] = false;
- }
- particles->inactive = false;
- particles->inactive_time = 0;
- } else {
- particles->inactive_time += particles->speed_scale * frame.delta;
- if (particles->inactive_time > particles->lifetime * 1.2) {
- particles->inactive = true;
- particle_update_list.remove(particle_update_list.first());
- continue;
- }
- }
-
- Material *material = material_owner.getornull(particles->process_material);
- if (!material || !material->shader || material->shader->mode != VS::SHADER_PARTICLES) {
-
- shaders.particles.set_custom_shader(0);
- } else {
- shaders.particles.set_custom_shader(material->shader->custom_code_id);
-
- if (material->ubo_id) {
-
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, material->ubo_id);
- }
-
- int tc = material->textures.size();
- RID *textures = material->textures.ptrw();
- ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = material->shader->texture_hints.ptrw();
-
- for (int i = 0; i < tc; i++) {
-
- glActiveTexture(GL_TEXTURE0 + i);
-
- GLenum target;
- GLuint tex;
-
- RasterizerStorageGLES3::Texture *t = texture_owner.getornull(textures[i]);
-
- if (!t) {
- //check hints
- target = GL_TEXTURE_2D;
-
- switch (texture_hints[i]) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
- tex = resources.black_tex;
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
- tex = resources.aniso_tex;
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- tex = resources.normal_tex;
- } break;
- default: {
- tex = resources.white_tex;
- } break;
- }
- } else {
-
- t = t->get_ptr(); //resolve for proxies
- target = t->target;
- tex = t->tex_id;
- }
-
- glBindTexture(target, tex);
- }
- }
-
- shaders.particles.set_conditional(ParticlesShaderGLES3::USE_FRACTIONAL_DELTA, particles->fractional_delta);
-
- shaders.particles.bind();
-
- shaders.particles.set_uniform(ParticlesShaderGLES3::TOTAL_PARTICLES, particles->amount);
- shaders.particles.set_uniform(ParticlesShaderGLES3::TIME, frame.time[0]);
- shaders.particles.set_uniform(ParticlesShaderGLES3::EXPLOSIVENESS, particles->explosiveness);
- shaders.particles.set_uniform(ParticlesShaderGLES3::LIFETIME, particles->lifetime);
- shaders.particles.set_uniform(ParticlesShaderGLES3::ATTRACTOR_COUNT, 0);
- shaders.particles.set_uniform(ParticlesShaderGLES3::EMITTING, particles->emitting);
- shaders.particles.set_uniform(ParticlesShaderGLES3::RANDOMNESS, particles->randomness);
-
- bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
-
- if (particles->clear && particles->pre_process_time > 0.0) {
-
- float frame_time;
- if (particles->fixed_fps > 0)
- frame_time = 1.0 / particles->fixed_fps;
- else
- frame_time = 1.0 / 30.0;
-
- float todo = particles->pre_process_time;
-
- while (todo >= 0) {
- _particles_process(particles, frame_time);
- todo -= frame_time;
- }
- }
-
- if (particles->fixed_fps > 0) {
- float frame_time;
- float decr;
- if (zero_time_scale) {
- frame_time = 0.0;
- decr = 1.0 / particles->fixed_fps;
- } else {
- frame_time = 1.0 / particles->fixed_fps;
- decr = frame_time;
- }
- float delta = frame.delta;
- if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
- delta = 0.1;
- } else if (delta <= 0.0) { //unlikely but..
- delta = 0.001;
- }
- float todo = particles->frame_remainder + delta;
-
- while (todo >= frame_time) {
- _particles_process(particles, frame_time);
- todo -= decr;
- }
-
- particles->frame_remainder = todo;
-
- } else {
- if (zero_time_scale)
- _particles_process(particles, 0.0);
- else
- _particles_process(particles, frame.delta);
- }
-
- particle_update_list.remove(particle_update_list.first());
-
- if (particles->histories_enabled) {
-
- SWAP(particles->particle_buffer_histories[0], particles->particle_buffer_histories[1]);
- SWAP(particles->particle_vao_histories[0], particles->particle_vao_histories[1]);
- SWAP(particles->particle_valid_histories[0], particles->particle_valid_histories[1]);
-
- //copy
- glBindBuffer(GL_COPY_READ_BUFFER, particles->particle_buffers[0]);
- glBindBuffer(GL_COPY_WRITE_BUFFER, particles->particle_buffer_histories[0]);
- glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, particles->amount * 24 * sizeof(float));
-
- particles->particle_valid_histories[0] = true;
- }
-
- particles->instance_change_notify(true, false); //make sure shadows are updated
- }
-
- glDisable(GL_RASTERIZER_DISCARD);
-}
-
-bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const {
-
- const Particles *particles = particles_owner.getornull(p_particles);
- ERR_FAIL_COND_V(!particles, false);
- return !particles->emitting && particles->inactive;
-}
-
-////////
-
-void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
- ERR_FAIL_COND(!skeleton);
-
- skeleton->instances.insert(p_instance);
-}
-
-void RasterizerStorageGLES3::instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
- ERR_FAIL_COND(!skeleton);
-
- skeleton->instances.erase(p_instance);
-}
-
-void RasterizerStorageGLES3::instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {
-
- Instantiable *inst = NULL;
- switch (p_instance->base_type) {
- case VS::INSTANCE_MESH: {
- inst = mesh_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_MULTIMESH: {
- inst = multimesh_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_IMMEDIATE: {
- inst = immediate_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_PARTICLES: {
- inst = particles_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_REFLECTION_PROBE: {
- inst = reflection_probe_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_LIGHT: {
- inst = light_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_GI_PROBE: {
- inst = gi_probe_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_LIGHTMAP_CAPTURE: {
- inst = lightmap_capture_data_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- default: {
- ERR_FAIL();
- }
- }
-
- inst->instance_list.add(&p_instance->dependency_item);
-}
-
-void RasterizerStorageGLES3::instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {
-
- Instantiable *inst = NULL;
-
- switch (p_instance->base_type) {
- case VS::INSTANCE_MESH: {
- inst = mesh_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_MULTIMESH: {
- inst = multimesh_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_IMMEDIATE: {
- inst = immediate_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_PARTICLES: {
- inst = particles_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_REFLECTION_PROBE: {
- inst = reflection_probe_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_LIGHT: {
- inst = light_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_GI_PROBE: {
- inst = gi_probe_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- case VS::INSTANCE_LIGHTMAP_CAPTURE: {
- inst = lightmap_capture_data_owner.getornull(p_base);
- ERR_FAIL_COND(!inst);
- } break;
- default: {
- ERR_FAIL();
- }
- }
-
- inst->instance_list.remove(&p_instance->dependency_item);
-}
-
-/* RENDER TARGET */
-
-void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
-
- if (rt->fbo) {
- glDeleteFramebuffers(1, &rt->fbo);
- glDeleteTextures(1, &rt->color);
- rt->fbo = 0;
- }
-
- if (rt->buffers.active) {
- glDeleteFramebuffers(1, &rt->buffers.fbo);
- glDeleteRenderbuffers(1, &rt->buffers.depth);
- glDeleteRenderbuffers(1, &rt->buffers.diffuse);
- if (rt->buffers.effects_active) {
- glDeleteRenderbuffers(1, &rt->buffers.specular);
- glDeleteRenderbuffers(1, &rt->buffers.normal_rough);
- glDeleteRenderbuffers(1, &rt->buffers.sss);
- glDeleteFramebuffers(1, &rt->buffers.effect_fbo);
- glDeleteTextures(1, &rt->buffers.effect);
- }
-
- rt->buffers.effects_active = false;
- rt->buffers.active = false;
- }
-
- if (rt->depth) {
- glDeleteTextures(1, &rt->depth);
- rt->depth = 0;
- }
-
- if (rt->effects.ssao.blur_fbo[0]) {
- glDeleteFramebuffers(1, &rt->effects.ssao.blur_fbo[0]);
- glDeleteTextures(1, &rt->effects.ssao.blur_red[0]);
- glDeleteFramebuffers(1, &rt->effects.ssao.blur_fbo[1]);
- glDeleteTextures(1, &rt->effects.ssao.blur_red[1]);
- for (int i = 0; i < rt->effects.ssao.depth_mipmap_fbos.size(); i++) {
- glDeleteFramebuffers(1, &rt->effects.ssao.depth_mipmap_fbos[i]);
- }
-
- rt->effects.ssao.depth_mipmap_fbos.clear();
-
- glDeleteTextures(1, &rt->effects.ssao.linear_depth);
-
- rt->effects.ssao.blur_fbo[0] = 0;
- rt->effects.ssao.blur_fbo[1] = 0;
- }
-
- if (rt->exposure.fbo) {
- glDeleteFramebuffers(1, &rt->exposure.fbo);
- glDeleteTextures(1, &rt->exposure.color);
- rt->exposure.fbo = 0;
- }
-
- if (rt->external.fbo != 0) {
- // free this
- glDeleteFramebuffers(1, &rt->external.fbo);
-
- // clean up our texture
- Texture *t = texture_owner.getornull(rt->external.texture);
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->width = 0;
- t->height = 0;
- t->active = false;
- texture_owner.free(rt->external.texture);
- memdelete(t);
-
- rt->external.fbo = 0;
- }
-
- Texture *tex = texture_owner.getornull(rt->texture);
- tex->alloc_height = 0;
- tex->alloc_width = 0;
- tex->width = 0;
- tex->height = 0;
- tex->active = false;
-
- for (int i = 0; i < 2; i++) {
- if (rt->effects.mip_maps[i].color) {
- for (int j = 0; j < rt->effects.mip_maps[i].sizes.size(); j++) {
- glDeleteFramebuffers(1, &rt->effects.mip_maps[i].sizes[j].fbo);
- }
-
- glDeleteTextures(1, &rt->effects.mip_maps[i].color);
- rt->effects.mip_maps[i].sizes.clear();
- rt->effects.mip_maps[i].levels = 0;
- rt->effects.mip_maps[i].color = 0;
- }
- }
-
- /*
- if (rt->effects.screen_space_depth) {
- glDeleteTextures(1,&rt->effects.screen_space_depth);
- rt->effects.screen_space_depth=0;
-
- }
-*/
-}
-
-void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
-
- if (rt->width <= 0 || rt->height <= 0)
- return;
-
- GLuint color_internal_format;
- GLuint color_format;
- GLuint color_type;
- Image::Format image_format;
-
- bool hdr = rt->flags[RENDER_TARGET_HDR] && config.framebuffer_half_float_supported;
- //hdr = false;
-
- if (!hdr || rt->flags[RENDER_TARGET_NO_3D]) {
-
- if (rt->flags[RENDER_TARGET_NO_3D_EFFECTS] && !rt->flags[RENDER_TARGET_TRANSPARENT]) {
- //if this is not used, linear colorspace looks pretty bad
- //this is the default mode used for mobile
- color_internal_format = GL_RGB10_A2;
- color_format = GL_RGBA;
- color_type = GL_UNSIGNED_INT_2_10_10_10_REV;
- image_format = Image::FORMAT_RGBA8;
- } else {
-
- color_internal_format = GL_RGBA8;
- color_format = GL_RGBA;
- color_type = GL_UNSIGNED_BYTE;
- image_format = Image::FORMAT_RGBA8;
- }
- } else {
- color_internal_format = GL_RGBA16F;
- color_format = GL_RGBA;
- color_type = GL_HALF_FLOAT;
- image_format = Image::FORMAT_RGBAH;
- }
-
- {
- /* FRONT FBO */
-
- glActiveTexture(GL_TEXTURE0);
-
- glGenFramebuffers(1, &rt->fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
-
- glGenTextures(1, &rt->depth);
- glBindTexture(GL_TEXTURE_2D, rt->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->width, rt->height, 0,
- GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_TEXTURE_2D, rt->depth, 0);
-
- glGenTextures(1, &rt->color);
- glBindTexture(GL_TEXTURE_2D, rt->color);
-
- glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- printf("framebuffer fail, status: %x\n", status);
- }
-
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
-
- Texture *tex = texture_owner.getornull(rt->texture);
- tex->format = image_format;
- tex->gl_format_cache = color_format;
- tex->gl_type_cache = color_type;
- tex->gl_internal_format_cache = color_internal_format;
- tex->tex_id = rt->color;
- tex->width = rt->width;
- tex->alloc_width = rt->width;
- tex->height = rt->height;
- tex->alloc_height = rt->height;
- tex->active = true;
-
- texture_set_flags(rt->texture, tex->flags);
- }
-
- /* BACK FBO */
-
- if (!rt->flags[RENDER_TARGET_NO_3D] && (!rt->flags[RENDER_TARGET_NO_3D_EFFECTS] || rt->msaa != VS::VIEWPORT_MSAA_DISABLED)) {
-
- rt->buffers.active = true;
-
- static const int msaa_value[] = { 0, 2, 4, 8, 16, 4, 16 }; // MSAA_EXT_nX is a GLES2 temporary hack ignored in GLES3 for now...
- int msaa = msaa_value[rt->msaa];
-
- int max_samples = 0;
- glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
- if (msaa > max_samples) {
- WARN_PRINT("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples));
- msaa = max_samples;
- }
-
- //regular fbo
- glGenFramebuffers(1, &rt->buffers.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo);
-
- glGenRenderbuffers(1, &rt->buffers.depth);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.depth);
- if (msaa == 0)
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rt->width, rt->height);
- else
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT24, rt->width, rt->height);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->buffers.depth);
-
- glGenRenderbuffers(1, &rt->buffers.diffuse);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.diffuse);
-
- if (msaa == 0)
- glRenderbufferStorage(GL_RENDERBUFFER, color_internal_format, rt->width, rt->height);
- else
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->buffers.diffuse);
-
- if (!rt->flags[RENDER_TARGET_NO_3D_EFFECTS]) {
-
- rt->buffers.effects_active = true;
- glGenRenderbuffers(1, &rt->buffers.specular);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.specular);
-
- if (msaa == 0)
- glRenderbufferStorage(GL_RENDERBUFFER, color_internal_format, rt->width, rt->height);
- else
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rt->buffers.specular);
-
- glGenRenderbuffers(1, &rt->buffers.normal_rough);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.normal_rough);
-
- if (msaa == 0)
- glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, rt->width, rt->height);
- else
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGBA8, rt->width, rt->height);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, rt->buffers.normal_rough);
-
- glGenRenderbuffers(1, &rt->buffers.sss);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.sss);
-
- if (msaa == 0)
- glRenderbufferStorage(GL_RENDERBUFFER, GL_R8, rt->width, rt->height);
- else
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_R8, rt->width, rt->height);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_RENDERBUFFER, rt->buffers.sss);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- printf("err status: %x\n", status);
- _render_target_clear(rt);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
-
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
-
- // effect resolver
-
- glGenFramebuffers(1, &rt->buffers.effect_fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.effect_fbo);
-
- glGenTextures(1, &rt->buffers.effect);
- glBindTexture(GL_TEXTURE_2D, rt->buffers.effect);
- glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0,
- color_format, color_type, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, rt->buffers.effect, 0);
-
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- printf("err status: %x\n", status);
- _render_target_clear(rt);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
-
- ///////////////// ssao
-
- //AO strength textures
- for (int i = 0; i < 2; i++) {
-
- glGenFramebuffers(1, &rt->effects.ssao.blur_fbo[i]);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->effects.ssao.blur_fbo[i]);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_TEXTURE_2D, rt->depth, 0);
-
- glGenTextures(1, &rt->effects.ssao.blur_red[i]);
- glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.blur_red[i]);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, rt->width, rt->height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.blur_red[i], 0);
-
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- _render_target_clear(rt);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
- }
- //5 mip levels for depth texture, but base is read separately
-
- glGenTextures(1, &rt->effects.ssao.linear_depth);
- glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.linear_depth);
-
- int ssao_w = rt->width / 2;
- int ssao_h = rt->height / 2;
-
- for (int i = 0; i < 4; i++) { //5, but 4 mips, base is read directly to save bw
-
- glTexImage2D(GL_TEXTURE_2D, i, GL_R16UI, ssao_w, ssao_h, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL);
- ssao_w >>= 1;
- ssao_h >>= 1;
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
-
- for (int i = 0; i < 4; i++) { //5, but 4 mips, base is read directly to save bw
-
- GLuint fbo;
- glGenFramebuffers(1, &fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.linear_depth, i);
- rt->effects.ssao.depth_mipmap_fbos.push_back(fbo);
- }
-
- //////Exposure
-
- glGenFramebuffers(1, &rt->exposure.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->exposure.fbo);
-
- glGenTextures(1, &rt->exposure.color);
- glBindTexture(GL_TEXTURE_2D, rt->exposure.color);
- if (config.framebuffer_float_supported) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL);
- } else if (config.framebuffer_half_float_supported) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, 1, 1, 0, GL_RED, GL_HALF_FLOAT, NULL);
- } else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, NULL);
- }
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0);
-
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- _render_target_clear(rt);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
- } else {
- rt->buffers.effects_active = false;
- }
- } else {
- rt->buffers.active = false;
- rt->buffers.effects_active = true;
- }
-
- if (!rt->flags[RENDER_TARGET_NO_SAMPLING] && rt->width >= 2 && rt->height >= 2) {
-
- for (int i = 0; i < 2; i++) {
-
- ERR_FAIL_COND(rt->effects.mip_maps[i].sizes.size());
- int w = rt->width;
- int h = rt->height;
-
- if (i > 0) {
- w >>= 1;
- h >>= 1;
- }
-
- glGenTextures(1, &rt->effects.mip_maps[i].color);
- glBindTexture(GL_TEXTURE_2D, rt->effects.mip_maps[i].color);
-
- int level = 0;
- int fb_w = w;
- int fb_h = h;
-
- while (true) {
-
- RenderTarget::Effects::MipMaps::Size mm;
- mm.width = w;
- mm.height = h;
- rt->effects.mip_maps[i].sizes.push_back(mm);
-
- w >>= 1;
- h >>= 1;
-
- if (w < 2 || h < 2)
- break;
-
- level++;
- }
-
- glTexStorage2DCustom(GL_TEXTURE_2D, level + 1, color_internal_format, fb_w, fb_h, color_format, color_type);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
- glDisable(GL_SCISSOR_TEST);
- glColorMask(1, 1, 1, 1);
- if (!rt->buffers.active) {
- glDepthMask(GL_TRUE);
- }
-
- for (int j = 0; j < rt->effects.mip_maps[i].sizes.size(); j++) {
-
- RenderTarget::Effects::MipMaps::Size &mm = rt->effects.mip_maps[i].sizes.write[j];
-
- glGenFramebuffers(1, &mm.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.mip_maps[i].color, j);
- bool used_depth = false;
- if (j == 0 && i == 0) { //use always
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
- used_depth = true;
- }
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- _render_target_clear(rt);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
-
- float zero[4] = { 1, 0, 1, 0 };
- glViewport(0, 0, rt->effects.mip_maps[i].sizes[j].width, rt->effects.mip_maps[i].sizes[j].height);
- glClearBufferfv(GL_COLOR, 0, zero);
- if (used_depth) {
- glClearDepth(1.0);
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- rt->effects.mip_maps[i].levels = level;
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- }
-}
-
-RID RasterizerStorageGLES3::render_target_create() {
-
- RenderTarget *rt = memnew(RenderTarget);
-
- Texture *t = memnew(Texture);
-
- t->type = VS::TEXTURE_TYPE_2D;
- t->flags = 0;
- t->width = 0;
- t->height = 0;
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->format = Image::FORMAT_R8;
- t->target = GL_TEXTURE_2D;
- t->gl_format_cache = 0;
- t->gl_internal_format_cache = 0;
- t->gl_type_cache = 0;
- t->data_size = 0;
- t->compressed = false;
- t->srgb = false;
- t->total_data_size = 0;
- t->ignore_mipmaps = false;
- t->mipmaps = 1;
- t->active = true;
- t->tex_id = 0;
- t->render_target = rt;
-
- rt->texture = texture_owner.make_rid(t);
-
- return render_target_owner.make_rid(rt);
-}
-
-void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) {
- //only used in GLES2
-}
-
-void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_width, int p_height) {
-
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (rt->width == p_width && rt->height == p_height)
- return;
-
- _render_target_clear(rt);
- rt->width = p_width;
- rt->height = p_height;
- _render_target_allocate(rt);
-}
-
-RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) const {
-
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- if (rt->external.fbo == 0) {
- return rt->texture;
- } else {
- return rt->external.texture;
- }
-}
-
-void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (p_texture_id == 0) {
- if (rt->external.fbo != 0) {
- // free this
- glDeleteFramebuffers(1, &rt->external.fbo);
-
- // clean up our texture
- Texture *t = texture_owner.getornull(rt->external.texture);
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->width = 0;
- t->height = 0;
- t->active = false;
- texture_owner.free(rt->external.texture);
- memdelete(t);
-
- rt->external.fbo = 0;
- }
- } else {
- Texture *t;
-
- if (rt->external.fbo == 0) {
- // create our fbo
- glGenFramebuffers(1, &rt->external.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
-
- // allocate a texture
- t = memnew(Texture);
-
- t->type = VS::TEXTURE_TYPE_2D;
- t->flags = 0;
- t->width = 0;
- t->height = 0;
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->format = Image::FORMAT_RGBA8;
- t->target = GL_TEXTURE_2D;
- t->gl_format_cache = 0;
- t->gl_internal_format_cache = 0;
- t->gl_type_cache = 0;
- t->data_size = 0;
- t->compressed = false;
- t->srgb = false;
- t->total_data_size = 0;
- t->ignore_mipmaps = false;
- t->mipmaps = 1;
- t->active = true;
- t->tex_id = 0;
- t->render_target = rt;
-
- rt->external.texture = texture_owner.make_rid(t);
- } else {
- // bind our frame buffer
- glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
-
- // find our texture
- t = texture_owner.getornull(rt->external.texture);
- }
-
- // set our texture
- t->tex_id = p_texture_id;
-
- // size shouldn't be different
- t->width = rt->width;
- t->height = rt->height;
- t->alloc_height = rt->width;
- t->alloc_width = rt->height;
-
- // is there a point to setting the internal formats? we don't know them..
-
- // set our texture as the destination for our framebuffer
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
-
- // check status and unbind
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- printf("framebuffer fail, status: %x\n", status);
- }
-
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
-}
-
-void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
-
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND(!rt);
-
- rt->flags[p_flag] = p_value;
-
- switch (p_flag) {
- case RENDER_TARGET_HDR:
- case RENDER_TARGET_NO_3D:
- case RENDER_TARGET_NO_SAMPLING:
- case RENDER_TARGET_NO_3D_EFFECTS: {
- //must reset for these formats
- _render_target_clear(rt);
- _render_target_allocate(rt);
-
- } break;
- default: {
- }
- }
-}
-bool RasterizerStorageGLES3::render_target_was_used(RID p_render_target) {
-
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
-
- return rt->used_in_frame;
-}
-
-void RasterizerStorageGLES3::render_target_set_as_unused(RID p_render_target) {
-
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND(!rt);
-
- rt->used_in_frame = false;
-}
-
-void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, VS::ViewportMSAA p_msaa) {
-
- RenderTarget *rt = render_target_owner.getornull(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (rt->msaa == p_msaa)
- return;
-
- _render_target_clear(rt);
- rt->msaa = p_msaa;
- _render_target_allocate(rt);
-}
-
-/* CANVAS SHADOW */
-
-RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) {
-
- CanvasLightShadow *cls = memnew(CanvasLightShadow);
- if (p_width > config.max_texture_size)
- p_width = config.max_texture_size;
-
- cls->size = p_width;
- cls->height = 16;
-
- glActiveTexture(GL_TEXTURE0);
-
- glGenFramebuffers(1, &cls->fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
-
- glGenRenderbuffers(1, &cls->depth);
- glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cls->size, cls->height);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
-
- glGenTextures(1, &cls->distance);
- glBindTexture(GL_TEXTURE_2D, cls->distance);
- if (config.use_rgba_2d_shadows) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- } else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, NULL);
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- //printf("errnum: %x\n",status);
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- memdelete(cls);
- ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID());
- }
-
- return canvas_light_shadow_owner.make_rid(cls);
-}
-
-/* LIGHT SHADOW MAPPING */
-
-RID RasterizerStorageGLES3::canvas_light_occluder_create() {
-
- CanvasOccluder *co = memnew(CanvasOccluder);
- co->index_id = 0;
- co->vertex_id = 0;
- co->len = 0;
- glGenVertexArrays(1, &co->array_id);
-
- return canvas_occluder_owner.make_rid(co);
-}
-
-void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector &p_lines) {
-
- CanvasOccluder *co = canvas_occluder_owner.getornull(p_occluder);
- ERR_FAIL_COND(!co);
-
- co->lines = p_lines;
-
- if (p_lines.size() != co->len) {
-
- if (co->index_id)
- glDeleteBuffers(1, &co->index_id);
- if (co->vertex_id)
- glDeleteBuffers(1, &co->vertex_id);
-
- co->index_id = 0;
- co->vertex_id = 0;
- co->len = 0;
- }
-
- if (p_lines.size()) {
-
- PoolVector geometry;
- PoolVector indices;
- int lc = p_lines.size();
-
- geometry.resize(lc * 6);
- indices.resize(lc * 3);
-
- PoolVector::Write vw = geometry.write();
- PoolVector::Write iw = indices.write();
-
- PoolVector::Read lr = p_lines.read();
-
- const int POLY_HEIGHT = 16384;
-
- for (int i = 0; i < lc / 2; i++) {
-
- vw[i * 12 + 0] = lr[i * 2 + 0].x;
- vw[i * 12 + 1] = lr[i * 2 + 0].y;
- vw[i * 12 + 2] = POLY_HEIGHT;
-
- vw[i * 12 + 3] = lr[i * 2 + 1].x;
- vw[i * 12 + 4] = lr[i * 2 + 1].y;
- vw[i * 12 + 5] = POLY_HEIGHT;
-
- vw[i * 12 + 6] = lr[i * 2 + 1].x;
- vw[i * 12 + 7] = lr[i * 2 + 1].y;
- vw[i * 12 + 8] = -POLY_HEIGHT;
-
- vw[i * 12 + 9] = lr[i * 2 + 0].x;
- vw[i * 12 + 10] = lr[i * 2 + 0].y;
- vw[i * 12 + 11] = -POLY_HEIGHT;
-
- iw[i * 6 + 0] = i * 4 + 0;
- iw[i * 6 + 1] = i * 4 + 1;
- iw[i * 6 + 2] = i * 4 + 2;
-
- iw[i * 6 + 3] = i * 4 + 2;
- iw[i * 6 + 4] = i * 4 + 3;
- iw[i * 6 + 5] = i * 4 + 0;
- }
-
- //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
-
- if (!co->vertex_id) {
- glGenBuffers(1, &co->vertex_id);
- glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
- glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW);
- } else {
-
- glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
- glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr());
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- if (!co->index_id) {
-
- glGenBuffers(1, &co->index_id);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW);
- } else {
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
- glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, lc * 3 * sizeof(uint16_t), iw.ptr());
- }
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
-
- co->len = lc;
- glBindVertexArray(co->array_id);
- glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
- glBindVertexArray(0);
- }
-}
-
-VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
-
- if (mesh_owner.owns(p_rid)) {
- return VS::INSTANCE_MESH;
- }
-
- if (multimesh_owner.owns(p_rid)) {
- return VS::INSTANCE_MULTIMESH;
- }
-
- if (immediate_owner.owns(p_rid)) {
- return VS::INSTANCE_IMMEDIATE;
- }
-
- if (particles_owner.owns(p_rid)) {
- return VS::INSTANCE_PARTICLES;
- }
-
- if (light_owner.owns(p_rid)) {
- return VS::INSTANCE_LIGHT;
- }
-
- if (reflection_probe_owner.owns(p_rid)) {
- return VS::INSTANCE_REFLECTION_PROBE;
- }
-
- if (gi_probe_owner.owns(p_rid)) {
- return VS::INSTANCE_GI_PROBE;
- }
-
- if (lightmap_capture_data_owner.owns(p_rid)) {
- return VS::INSTANCE_LIGHTMAP_CAPTURE;
- }
-
- return VS::INSTANCE_NONE;
-}
-
-bool RasterizerStorageGLES3::free(RID p_rid) {
-
- if (render_target_owner.owns(p_rid)) {
-
- RenderTarget *rt = render_target_owner.getornull(p_rid);
- _render_target_clear(rt);
- Texture *t = texture_owner.getornull(rt->texture);
- texture_owner.free(rt->texture);
- memdelete(t);
- render_target_owner.free(p_rid);
- memdelete(rt);
-
- } else if (texture_owner.owns(p_rid)) {
- // delete the texture
- Texture *texture = texture_owner.getornull(p_rid);
- ERR_FAIL_COND_V(texture->render_target, true); //can't free the render target texture, dude
- info.texture_mem -= texture->total_data_size;
- texture_owner.free(p_rid);
- memdelete(texture);
-
- } else if (sky_owner.owns(p_rid)) {
- // delete the sky
- Sky *sky = sky_owner.getornull(p_rid);
- sky_set_texture(p_rid, RID(), 256);
- sky_owner.free(p_rid);
- memdelete(sky);
-
- } else if (shader_owner.owns(p_rid)) {
-
- // delete the texture
- Shader *shader = shader_owner.getornull(p_rid);
-
- if (shader->shader && shader->custom_code_id)
- shader->shader->free_custom_shader(shader->custom_code_id);
-
- if (shader->dirty_list.in_list())
- _shader_dirty_list.remove(&shader->dirty_list);
-
- while (shader->materials.first()) {
-
- Material *mat = shader->materials.first()->self();
-
- mat->shader = NULL;
- _material_make_dirty(mat);
-
- shader->materials.remove(shader->materials.first());
- }
-
- //material_shader.free_custom_shader(shader->custom_code_id);
- shader_owner.free(p_rid);
- memdelete(shader);
-
- } else if (material_owner.owns(p_rid)) {
-
- // delete the texture
- Material *material = material_owner.getornull(p_rid);
-
- if (material->shader) {
- material->shader->materials.remove(&material->list);
- }
-
- if (material->ubo_id) {
- glDeleteBuffers(1, &material->ubo_id);
- }
-
- //remove from owners
- for (Map::Element *E = material->geometry_owners.front(); E; E = E->next()) {
-
- Geometry *g = E->key();
- g->material = RID();
- }
- for (Map::Element *E = material->instance_owners.front(); E; E = E->next()) {
- RasterizerScene::InstanceBase *ins = E->key();
- if (ins->material_override == p_rid) {
- ins->material_override = RID();
- }
-
- for (int i = 0; i < ins->materials.size(); i++) {
- if (ins->materials[i] == p_rid) {
- ins->materials.write[i] = RID();
- }
- }
- }
-
- material_owner.free(p_rid);
- memdelete(material);
-
- } else if (skeleton_owner.owns(p_rid)) {
-
- // delete the texture
- Skeleton *skeleton = skeleton_owner.getornull(p_rid);
- if (skeleton->update_list.in_list()) {
- skeleton_update_list.remove(&skeleton->update_list);
- }
-
- for (Set::Element *E = skeleton->instances.front(); E; E = E->next()) {
- E->get()->skeleton = RID();
- }
-
- skeleton_allocate(p_rid, 0, false);
-
- glDeleteTextures(1, &skeleton->texture);
- skeleton_owner.free(p_rid);
- memdelete(skeleton);
-
- } else if (mesh_owner.owns(p_rid)) {
-
- // delete the texture
- Mesh *mesh = mesh_owner.getornull(p_rid);
- mesh->instance_remove_deps();
- mesh_clear(p_rid);
-
- while (mesh->multimeshes.first()) {
- MultiMesh *multimesh = mesh->multimeshes.first()->self();
- multimesh->mesh = RID();
- multimesh->dirty_aabb = true;
- mesh->multimeshes.remove(mesh->multimeshes.first());
-
- if (!multimesh->update_list.in_list()) {
- multimesh_update_list.add(&multimesh->update_list);
- }
- }
-
- mesh_owner.free(p_rid);
- memdelete(mesh);
-
- } else if (multimesh_owner.owns(p_rid)) {
-
- // delete the texture
- MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
- multimesh->instance_remove_deps();
-
- if (multimesh->mesh.is_valid()) {
- Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
- if (mesh) {
- mesh->multimeshes.remove(&multimesh->mesh_list);
- }
- }
-
- multimesh_allocate(p_rid, 0, VS::MULTIMESH_TRANSFORM_2D, VS::MULTIMESH_COLOR_NONE); //frees multimesh
- update_dirty_multimeshes();
-
- multimesh_owner.free(p_rid);
- memdelete(multimesh);
- } else if (immediate_owner.owns(p_rid)) {
-
- Immediate *immediate = immediate_owner.getornull(p_rid);
- immediate->instance_remove_deps();
-
- immediate_owner.free(p_rid);
- memdelete(immediate);
- } else if (light_owner.owns(p_rid)) {
-
- // delete the texture
- Light *light = light_owner.getornull(p_rid);
- light->instance_remove_deps();
-
- light_owner.free(p_rid);
- memdelete(light);
-
- } else if (reflection_probe_owner.owns(p_rid)) {
-
- // delete the texture
- ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
- reflection_probe->instance_remove_deps();
-
- reflection_probe_owner.free(p_rid);
- memdelete(reflection_probe);
-
- } else if (gi_probe_owner.owns(p_rid)) {
-
- // delete the texture
- GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
- gi_probe->instance_remove_deps();
-
- gi_probe_owner.free(p_rid);
- memdelete(gi_probe);
- } else if (gi_probe_data_owner.owns(p_rid)) {
-
- // delete the texture
- GIProbeData *gi_probe_data = gi_probe_data_owner.getornull(p_rid);
-
- glDeleteTextures(1, &gi_probe_data->tex_id);
- gi_probe_data_owner.free(p_rid);
- memdelete(gi_probe_data);
- } else if (lightmap_capture_data_owner.owns(p_rid)) {
-
- // delete the texture
- LightmapCapture *lightmap_capture = lightmap_capture_data_owner.getornull(p_rid);
- lightmap_capture->instance_remove_deps();
-
- lightmap_capture_data_owner.free(p_rid);
- memdelete(lightmap_capture);
-
- } else if (canvas_occluder_owner.owns(p_rid)) {
-
- CanvasOccluder *co = canvas_occluder_owner.getornull(p_rid);
- if (co->index_id)
- glDeleteBuffers(1, &co->index_id);
- if (co->vertex_id)
- glDeleteBuffers(1, &co->vertex_id);
-
- glDeleteVertexArrays(1, &co->array_id);
-
- canvas_occluder_owner.free(p_rid);
- memdelete(co);
-
- } else if (canvas_light_shadow_owner.owns(p_rid)) {
-
- CanvasLightShadow *cls = canvas_light_shadow_owner.getornull(p_rid);
- glDeleteFramebuffers(1, &cls->fbo);
- glDeleteRenderbuffers(1, &cls->depth);
- glDeleteTextures(1, &cls->distance);
- canvas_light_shadow_owner.free(p_rid);
- memdelete(cls);
- } else if (particles_owner.owns(p_rid)) {
- Particles *particles = particles_owner.getornull(p_rid);
- particles->instance_remove_deps();
- particles_owner.free(p_rid);
- memdelete(particles);
- } else {
- return false;
- }
-
- return true;
-}
-
-bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const {
-
- if (p_feature == "bptc")
- return config.bptc_supported;
-
- if (p_feature == "s3tc")
- return config.s3tc_supported;
-
- if (p_feature == "etc")
- return config.etc_supported;
-
- if (p_feature == "etc2")
- return config.etc2_supported;
-
- if (p_feature == "pvrtc")
- return config.pvrtc_supported;
-
- return false;
-}
-
-////////////////////////////////////////////
-
-void RasterizerStorageGLES3::set_debug_generate_wireframes(bool p_generate) {
-
- config.generate_wireframes = p_generate;
-}
-
-void RasterizerStorageGLES3::render_info_begin_capture() {
-
- info.snap = info.render;
-}
-
-void RasterizerStorageGLES3::render_info_end_capture() {
-
- info.snap.object_count = info.render.object_count - info.snap.object_count;
- info.snap.draw_call_count = info.render.draw_call_count - info.snap.draw_call_count;
- info.snap.material_switch_count = info.render.material_switch_count - info.snap.material_switch_count;
- info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count;
- info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count;
- info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count;
-}
-
-int RasterizerStorageGLES3::get_captured_render_info(VS::RenderInfo p_info) {
-
- switch (p_info) {
- case VS::INFO_OBJECTS_IN_FRAME: {
-
- return info.snap.object_count;
- } break;
- case VS::INFO_VERTICES_IN_FRAME: {
-
- return info.snap.vertices_count;
- } break;
- case VS::INFO_MATERIAL_CHANGES_IN_FRAME: {
- return info.snap.material_switch_count;
- } break;
- case VS::INFO_SHADER_CHANGES_IN_FRAME: {
- return info.snap.shader_rebind_count;
- } break;
- case VS::INFO_SURFACE_CHANGES_IN_FRAME: {
- return info.snap.surface_switch_count;
- } break;
- case VS::INFO_DRAW_CALLS_IN_FRAME: {
- return info.snap.draw_call_count;
- } break;
- default: {
- return get_render_info(p_info);
- }
- }
-}
-
-int RasterizerStorageGLES3::get_render_info(VS::RenderInfo p_info) {
-
- switch (p_info) {
- case VS::INFO_OBJECTS_IN_FRAME:
- return info.render_final.object_count;
- case VS::INFO_VERTICES_IN_FRAME:
- return info.render_final.vertices_count;
- case VS::INFO_MATERIAL_CHANGES_IN_FRAME:
- return info.render_final.material_switch_count;
- case VS::INFO_SHADER_CHANGES_IN_FRAME:
- return info.render_final.shader_rebind_count;
- case VS::INFO_SURFACE_CHANGES_IN_FRAME:
- return info.render_final.surface_switch_count;
- case VS::INFO_DRAW_CALLS_IN_FRAME:
- return info.render_final.draw_call_count;
- case VS::INFO_USAGE_VIDEO_MEM_TOTAL:
- return 0; //no idea
- case VS::INFO_VIDEO_MEM_USED:
- return info.vertex_mem + info.texture_mem;
- case VS::INFO_TEXTURE_MEM_USED:
- return info.texture_mem;
- case VS::INFO_VERTEX_MEM_USED:
- return info.vertex_mem;
- default:
- return 0; //no idea either
- }
-}
-
-String RasterizerStorageGLES3::get_video_adapter_name() const {
-
- return (const char *)glGetString(GL_RENDERER);
-}
-
-String RasterizerStorageGLES3::get_video_adapter_vendor() const {
-
- return (const char *)glGetString(GL_VENDOR);
-}
-
-void RasterizerStorageGLES3::initialize() {
-
- RasterizerStorageGLES3::system_fbo = 0;
-
- //// extensions config
- ///
-
- {
-
- int max_extensions = 0;
- glGetIntegerv(GL_NUM_EXTENSIONS, &max_extensions);
- for (int i = 0; i < max_extensions; i++) {
- const GLubyte *s = glGetStringi(GL_EXTENSIONS, i);
- if (!s)
- break;
- config.extensions.insert((const char *)s);
- }
- }
-
- config.shrink_textures_x2 = false;
- config.use_fast_texture_filter = int(ProjectSettings::get_singleton()->get("rendering/quality/filters/use_nearest_mipmap_filter"));
- config.use_anisotropic_filter = config.extensions.has("rendering/quality/filters/anisotropic_filter_level");
-
- config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
- config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc");
- config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc");
-#ifdef GLES_OVER_GL
- config.etc2_supported = false;
- config.s3tc_supported = true;
- config.rgtc_supported = true; //RGTC - core since OpenGL version 3.0
- config.texture_float_linear_supported = true;
- config.framebuffer_float_supported = true;
- config.framebuffer_half_float_supported = true;
-
-#else
- config.etc2_supported = true;
- config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_dxt1") || config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
- config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc");
- config.texture_float_linear_supported = config.extensions.has("GL_OES_texture_float_linear");
- config.framebuffer_float_supported = config.extensions.has("GL_EXT_color_buffer_float");
- config.framebuffer_half_float_supported = config.extensions.has("GL_EXT_color_buffer_half_float") || config.framebuffer_float_supported;
-
-#endif
-
- config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc");
- config.srgb_decode_supported = config.extensions.has("GL_EXT_texture_sRGB_decode");
-
- config.anisotropic_level = 1.0;
- config.use_anisotropic_filter = config.extensions.has("GL_EXT_texture_filter_anisotropic");
- if (config.use_anisotropic_filter) {
- glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &config.anisotropic_level);
- config.anisotropic_level = MIN(int(ProjectSettings::get_singleton()->get("rendering/quality/filters/anisotropic_filter_level")), config.anisotropic_level);
- }
-
- frame.clear_request = false;
-
- shaders.copy.init();
-
- {
- //default textures
-
- glGenTextures(1, &resources.white_tex);
- unsigned char whitetexdata[8 * 8 * 3];
- for (int i = 0; i < 8 * 8 * 3; i++) {
- whitetexdata[i] = 255;
- }
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, resources.white_tex);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
- glGenerateMipmap(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glGenTextures(1, &resources.black_tex);
- unsigned char blacktexdata[8 * 8 * 3];
- for (int i = 0; i < 8 * 8 * 3; i++) {
- blacktexdata[i] = 0;
- }
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, resources.black_tex);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, blacktexdata);
- glGenerateMipmap(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glGenTextures(1, &resources.normal_tex);
- unsigned char normaltexdata[8 * 8 * 3];
- for (int i = 0; i < 8 * 8 * 3; i += 3) {
- normaltexdata[i + 0] = 128;
- normaltexdata[i + 1] = 128;
- normaltexdata[i + 2] = 255;
- }
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, resources.normal_tex);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, normaltexdata);
- glGenerateMipmap(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glGenTextures(1, &resources.aniso_tex);
- unsigned char anisotexdata[8 * 8 * 3];
- for (int i = 0; i < 8 * 8 * 3; i += 3) {
- anisotexdata[i + 0] = 255;
- anisotexdata[i + 1] = 128;
- anisotexdata[i + 2] = 0;
- }
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, resources.aniso_tex);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata);
- glGenerateMipmap(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glGenTextures(1, &resources.white_tex_3d);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_3D, resources.white_tex_3d);
- glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 2, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
-
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
-
- glGenTextures(1, &resources.white_tex_array);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D_ARRAY, resources.white_tex_array);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 8, 8, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
- glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 1, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
- glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
-
- config.use_rgba_2d_shadows = !config.framebuffer_float_supported;
-
- //generic quadie for copying
-
- {
- //quad buffers
-
- glGenBuffers(1, &resources.quadie);
- glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
- {
- const float qv[16] = {
- -1,
- -1,
- 0,
- 0,
- -1,
- 1,
- 0,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- -1,
- 1,
- 0,
- };
-
- glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- glGenVertexArrays(1, &resources.quadie_array);
- glBindVertexArray(resources.quadie_array);
- glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8));
- glEnableVertexAttribArray(4);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
- }
-
- //generic quadie for copying without touching sky
-
- {
- //transform feedback buffers
- uint32_t xf_feedback_size = GLOBAL_DEF_RST("rendering/limits/buffers/blend_shape_max_buffer_size_kb", 4096);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/buffers/blend_shape_max_buffer_size_kb", PropertyInfo(Variant::INT, "rendering/limits/buffers/blend_shape_max_buffer_size_kb", PROPERTY_HINT_RANGE, "0,8192,1,or_greater"));
-
- for (int i = 0; i < 2; i++) {
-
- glGenBuffers(1, &resources.transform_feedback_buffers[i]);
- glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[i]);
- glBufferData(GL_ARRAY_BUFFER, xf_feedback_size * 1024, NULL, GL_STREAM_DRAW);
- }
-
- shaders.blend_shapes.init();
-
- glGenVertexArrays(1, &resources.transform_feedback_array);
- }
-
- shaders.cubemap_filter.init();
- bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
- shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
- shaders.particles.init();
-
-#ifdef GLES_OVER_GL
- glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS);
-#endif
-
- frame.count = 0;
- frame.delta = 0;
- frame.current_rt = NULL;
- config.keep_original_textures = false;
- config.generate_wireframes = false;
- config.use_texture_array_environment = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");
-
- config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
-
- String renderer = (const char *)glGetString(GL_RENDERER);
-
- config.use_depth_prepass = bool(GLOBAL_GET("rendering/quality/depth_prepass/enable"));
- if (config.use_depth_prepass) {
-
- String vendors = GLOBAL_GET("rendering/quality/depth_prepass/disable_for_vendors");
- Vector vendor_match = vendors.split(",");
- for (int i = 0; i < vendor_match.size(); i++) {
- String v = vendor_match[i].strip_edges();
- if (v == String())
- continue;
-
- if (renderer.findn(v) != -1) {
- config.use_depth_prepass = false;
- }
- }
- }
-}
-
-void RasterizerStorageGLES3::finalize() {
-
- glDeleteTextures(1, &resources.white_tex);
- glDeleteTextures(1, &resources.black_tex);
- glDeleteTextures(1, &resources.normal_tex);
-}
-
-void RasterizerStorageGLES3::update_dirty_resources() {
-
- update_dirty_multimeshes();
- update_dirty_skeletons();
- update_dirty_shaders();
- update_dirty_materials();
- update_particles();
-}
-
-RasterizerStorageGLES3::RasterizerStorageGLES3() {
-}
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
deleted file mode 100644
index 54c2e2b884..0000000000
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ /dev/null
@@ -1,1478 +0,0 @@
-/*************************************************************************/
-/* rasterizer_storage_gles3.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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 RASTERIZERSTORAGEGLES3_H
-#define RASTERIZERSTORAGEGLES3_H
-
-#include "core/self_list.h"
-#include "servers/visual/rasterizer.h"
-#include "servers/visual/shader_language.h"
-#include "shader_compiler_gles3.h"
-#include "shader_gles3.h"
-
-#include "shaders/blend_shape.glsl.gen.h"
-#include "shaders/canvas.glsl.gen.h"
-#include "shaders/copy.glsl.gen.h"
-#include "shaders/cubemap_filter.glsl.gen.h"
-#include "shaders/particles.glsl.gen.h"
-
-#include "core/rid_owner.h"
-
-// WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API instead.
-#ifdef __EMSCRIPTEN__
-void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
-#endif
-
-class RasterizerCanvasGLES3;
-class RasterizerSceneGLES3;
-
-#define _TEXTURE_SRGB_DECODE_EXT 0x8A48
-#define _DECODE_EXT 0x8A49
-#define _SKIP_DECODE_EXT 0x8A4A
-
-void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type);
-
-class RasterizerStorageGLES3 : public RasterizerStorage {
-public:
- RasterizerCanvasGLES3 *canvas;
- RasterizerSceneGLES3 *scene;
- static GLuint system_fbo; //on some devices, such as apple, screen is rendered to yet another fbo.
-
- enum RenderArchitecture {
- RENDER_ARCH_MOBILE,
- RENDER_ARCH_DESKTOP,
- };
-
- struct Config {
-
- bool shrink_textures_x2;
- bool use_fast_texture_filter;
- bool use_anisotropic_filter;
-
- bool s3tc_supported;
- bool latc_supported;
- bool rgtc_supported;
- bool bptc_supported;
- bool etc_supported;
- bool etc2_supported;
- bool pvrtc_supported;
-
- bool srgb_decode_supported;
-
- bool texture_float_linear_supported;
- bool framebuffer_float_supported;
- bool framebuffer_half_float_supported;
-
- bool use_rgba_2d_shadows;
-
- float anisotropic_level;
-
- int max_texture_image_units;
- int max_texture_size;
-
- bool generate_wireframes;
-
- bool use_texture_array_environment;
-
- Set extensions;
-
- bool keep_original_textures;
-
- bool use_depth_prepass;
- bool force_vertex_shading;
- } config;
-
- mutable struct Shaders {
-
- CopyShaderGLES3 copy;
-
- ShaderCompilerGLES3 compiler;
-
- CubemapFilterShaderGLES3 cubemap_filter;
-
- BlendShapeShaderGLES3 blend_shapes;
-
- ParticlesShaderGLES3 particles;
-
- ShaderCompilerGLES3::IdentifierActions actions_canvas;
- ShaderCompilerGLES3::IdentifierActions actions_scene;
- ShaderCompilerGLES3::IdentifierActions actions_particles;
- } shaders;
-
- struct Resources {
-
- GLuint white_tex;
- GLuint black_tex;
- GLuint normal_tex;
- GLuint aniso_tex;
-
- GLuint white_tex_3d;
- GLuint white_tex_array;
-
- GLuint quadie;
- GLuint quadie_array;
-
- GLuint transform_feedback_buffers[2];
- GLuint transform_feedback_array;
-
- } resources;
-
- struct Info {
-
- uint64_t texture_mem;
- uint64_t vertex_mem;
-
- struct Render {
- uint32_t object_count;
- uint32_t draw_call_count;
- uint32_t material_switch_count;
- uint32_t surface_switch_count;
- uint32_t shader_rebind_count;
- uint32_t vertices_count;
-
- void reset() {
- object_count = 0;
- draw_call_count = 0;
- material_switch_count = 0;
- surface_switch_count = 0;
- shader_rebind_count = 0;
- vertices_count = 0;
- }
- } render, render_final, snap;
-
- Info() {
-
- texture_mem = 0;
- vertex_mem = 0;
- render.reset();
- render_final.reset();
- }
-
- } info;
-
- /////////////////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////DATA///////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////
-
- struct Instantiable {
-
- SelfList::List instance_list;
-
- _FORCE_INLINE_ void instance_change_notify(bool p_aabb, bool p_materials) {
-
- SelfList *instances = instance_list.first();
- while (instances) {
-
- instances->self()->base_changed(p_aabb, p_materials);
- instances = instances->next();
- }
- }
-
- _FORCE_INLINE_ void instance_remove_deps() {
- SelfList *instances = instance_list.first();
- while (instances) {
-
- SelfList *next = instances->next();
- instances->self()->base_removed();
- instances = next;
- }
- }
-
- Instantiable() {}
- virtual ~Instantiable() {
- }
- };
-
- struct GeometryOwner : public Instantiable {
-
- virtual ~GeometryOwner() {}
- };
- struct Geometry : Instantiable {
-
- enum Type {
- GEOMETRY_INVALID,
- GEOMETRY_SURFACE,
- GEOMETRY_IMMEDIATE,
- GEOMETRY_MULTISURFACE,
- };
-
- Type type;
- RID material;
- uint64_t last_pass;
- uint32_t index;
-
- virtual void material_changed_notify() {}
-
- Geometry() {
- last_pass = 0;
- index = 0;
- }
- };
-
- /////////////////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////API////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////
-
- /* TEXTURE API */
-
- struct RenderTarget;
-
- struct Texture {
-
- Texture *proxy;
- Set proxy_owners;
-
- String path;
- uint32_t flags;
- int width, height, depth;
- int alloc_width, alloc_height, alloc_depth;
- Image::Format format;
- VS::TextureType type;
-
- GLenum target;
- GLenum gl_format_cache;
- GLenum gl_internal_format_cache;
- GLenum gl_type_cache;
- int data_size; //original data size, useful for retrieving back
- bool compressed;
- bool srgb;
- int total_data_size;
- bool ignore_mipmaps;
-
- int mipmaps;
-
- bool is_npot_repeat_mipmap;
-
- bool active;
- GLuint tex_id;
-
- bool using_srgb;
- bool redraw_if_visible;
-
- uint16_t stored_cube_sides;
-
- RenderTarget *render_target;
-
- Vector[ > images;
-
- VisualServer::TextureDetectCallback detect_3d;
- void *detect_3d_ud;
-
- VisualServer::TextureDetectCallback detect_srgb;
- void *detect_srgb_ud;
-
- VisualServer::TextureDetectCallback detect_normal;
- void *detect_normal_ud;
-
- Texture() :
- proxy(NULL),
- flags(0),
- width(0),
- height(0),
- format(Image::FORMAT_L8),
- type(VS::TEXTURE_TYPE_2D),
- target(GL_TEXTURE_2D),
- data_size(0),
- compressed(false),
- srgb(false),
- total_data_size(0),
- ignore_mipmaps(false),
- mipmaps(0),
- active(false),
- tex_id(0),
- using_srgb(false),
- redraw_if_visible(false),
- stored_cube_sides(0),
- render_target(NULL),
- detect_3d(NULL),
- detect_3d_ud(NULL),
- detect_srgb(NULL),
- detect_srgb_ud(NULL),
- detect_normal(NULL),
- detect_normal_ud(NULL) {
- }
-
- _ALWAYS_INLINE_ Texture *get_ptr() {
- if (proxy) {
- return proxy; //->get_ptr(); only one level of indirection, else not inlining possible.
- } else {
- return this;
- }
- }
-
- ~Texture() {
-
- if (tex_id != 0) {
-
- glDeleteTextures(1, &tex_id);
- }
-
- for (Set::Element *E = proxy_owners.front(); E; E = E->next()) {
- E->get()->proxy = NULL;
- }
-
- if (proxy) {
- proxy->proxy_owners.erase(this);
- }
- }
- };
-
- mutable RID_PtrOwner texture_owner;
-
- Ref _get_gl_image_and_format(const Ref &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &r_srgb, bool p_force_decompress) const;
-
- virtual RID texture_create();
- virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
- virtual void texture_set_data(RID p_texture, const Ref &p_image, int p_layer = 0);
- virtual void texture_set_data_partial(RID p_texture, const Ref &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0);
- virtual Ref texture_get_data(RID p_texture, int p_layer = 0) const;
- virtual void texture_set_flags(RID p_texture, uint32_t p_flags);
- virtual uint32_t texture_get_flags(RID p_texture) const;
- virtual Image::Format texture_get_format(RID p_texture) const;
- virtual VS::TextureType texture_get_type(RID p_texture) const;
- virtual uint32_t texture_get_texid(RID p_texture) const;
- virtual uint32_t texture_get_width(RID p_texture) const;
- virtual uint32_t texture_get_height(RID p_texture) const;
- virtual uint32_t texture_get_depth(RID p_texture) const;
- virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth);
- virtual void texture_bind(RID p_texture, uint32_t p_texture_no);
-
- virtual void texture_set_path(RID p_texture, const String &p_path);
- virtual String texture_get_path(RID p_texture) const;
-
- virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable);
-
- virtual void texture_debug_usage(List *r_info);
-
- virtual RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const;
-
- virtual void textures_keep_original(bool p_enable);
-
- virtual void texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
- virtual void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
- virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
-
- virtual void texture_set_proxy(RID p_texture, RID p_proxy);
- virtual Size2 texture_size_with_proxy(RID p_texture) const;
-
- virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable);
-
- /* SKY API */
-
- struct Sky {
-
- RID panorama;
- GLuint radiance;
- GLuint irradiance;
- int radiance_size;
- };
-
- mutable RID_PtrOwner sky_owner;
-
- virtual RID sky_create();
- virtual void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size);
-
- /* SHADER API */
-
- struct Material;
-
- struct Shader {
-
- RID self;
-
- VS::ShaderMode mode;
- ShaderGLES3 *shader;
- String code;
- SelfList::List materials;
-
- Map uniforms;
- Vector ubo_offsets;
- uint32_t ubo_size;
-
- uint32_t texture_count;
-
- uint32_t custom_code_id;
- uint32_t version;
-
- SelfList dirty_list;
-
- Map default_textures;
-
- Vector texture_types;
- Vector texture_hints;
-
- bool valid;
-
- String path;
-
- struct CanvasItem {
-
- enum BlendMode {
- BLEND_MODE_MIX,
- BLEND_MODE_ADD,
- BLEND_MODE_SUB,
- BLEND_MODE_MUL,
- BLEND_MODE_PMALPHA,
- BLEND_MODE_DISABLED,
- };
-
- int blend_mode;
-
- enum LightMode {
- LIGHT_MODE_NORMAL,
- LIGHT_MODE_UNSHADED,
- LIGHT_MODE_LIGHT_ONLY
- };
-
- int light_mode;
-
- bool uses_screen_texture;
- bool uses_screen_uv;
- bool uses_time;
-
- } canvas_item;
-
- struct Spatial {
-
- enum BlendMode {
- BLEND_MODE_MIX,
- BLEND_MODE_ADD,
- BLEND_MODE_SUB,
- BLEND_MODE_MUL,
- };
-
- int blend_mode;
-
- enum DepthDrawMode {
- DEPTH_DRAW_OPAQUE,
- DEPTH_DRAW_ALWAYS,
- DEPTH_DRAW_NEVER,
- DEPTH_DRAW_ALPHA_PREPASS,
- };
-
- int depth_draw_mode;
-
- enum CullMode {
- CULL_MODE_FRONT,
- CULL_MODE_BACK,
- CULL_MODE_DISABLED,
- };
-
- int cull_mode;
-
- bool uses_alpha;
- bool uses_alpha_scissor;
- bool unshaded;
- bool no_depth_test;
- bool uses_vertex;
- bool uses_discard;
- bool uses_sss;
- bool uses_screen_texture;
- bool uses_depth_texture;
- bool uses_time;
- bool writes_modelview_or_projection;
- bool uses_vertex_lighting;
- bool uses_world_coordinates;
-
- } spatial;
-
- struct Particles {
-
- } particles;
-
- bool uses_vertex_time;
- bool uses_fragment_time;
-
- Shader() :
- dirty_list(this) {
-
- shader = NULL;
- ubo_size = 0;
- valid = false;
- custom_code_id = 0;
- version = 1;
- }
- };
-
- mutable SelfList::List _shader_dirty_list;
- void _shader_make_dirty(Shader *p_shader);
-
- mutable RID_PtrOwner shader_owner;
-
- virtual RID shader_create();
-
- virtual void shader_set_code(RID p_shader, const String &p_code);
- virtual String shader_get_code(RID p_shader) const;
- virtual void shader_get_param_list(RID p_shader, List *p_param_list) const;
-
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;
-
- void _update_shader(Shader *p_shader) const;
-
- void update_dirty_shaders();
-
- /* COMMON MATERIAL API */
-
- struct Material {
-
- Shader *shader;
- GLuint ubo_id;
- uint32_t ubo_size;
- Map params;
- SelfList list;
- SelfList dirty_list;
- Vector texture_is_3d;
- Vector textures;
- float line_width;
- int render_priority;
-
- RID next_pass;
-
- uint32_t index;
- uint64_t last_pass;
-
- Map geometry_owners;
- Map instance_owners;
-
- bool can_cast_shadow_cache;
- bool is_animated_cache;
-
- Material() :
- shader(NULL),
- ubo_id(0),
- ubo_size(0),
- list(this),
- dirty_list(this),
- line_width(1.0),
- render_priority(0),
- last_pass(0),
- can_cast_shadow_cache(false),
- is_animated_cache(false) {
- }
- };
-
- mutable SelfList]